「gpt-4o-mini-tts」を試す
公式記事
本日、API で新しい音声合成およびテキスト読み上げ音声モデルを発表します。これにより、真の価値を提供する、より強力でカスタマイズ可能なインテリジェント音声エージェントを構築することが可能になります。
新しいテキスト読み上げモデル
より優れた操縦性を備えた新しいgpt-4o-mini-ttsモデルも発表します。開発者は今回初めて、モデルに「指示」を出すことができるようになりました。指示の内容は、何を言うかだけでなく、どのように言うかにも及びます。これにより、カスタマーサービスからクリエイティブなストーリーテリングまで、さまざまなユースケースにおいて、よりカスタマイズされた体験が可能になります。このモデルは、テキスト読み上げAPIでご利用いただけます(新しいウィンドウが開きます)。これらのテキスト読み上げモデルは、人工的なプリセット音声に限定されており、弊社がモニタリングを行い、合成プリセットと常に一致するよう確認しています。
新しいTTSは以下で試せる
公式ドキュメントに従って進めてみる
Colaboratoryで。
パッケージインストール。v1.68.0以上が必要。
!pip install -U openai
!pip freeze | grep -i openai
openai==1.68.0
APIキーをセット
from google.colab import userdata
import os
os.environ['OPENAI_API_KEY'] = userdata.get('OPENAI_API_KEY')
ではTTS。比較のため、tts-1
、tts-1-hd
、gpt-4o-mini-tts
で同じ文章を発話させてみる。
text = "今日はとてもいいお天気ですね。こんな日は競馬観戦に行きたくなりますね!そろそろ春のG1シリーズが始まるので頑張るぞ!"
from openai import OpenAI
client = OpenAI()
response = client.audio.speech.create(
model="tts-1",
voice="alloy",
input=text
)
response.stream_to_file("tts-1_alloy_normal.mp3")
response = client.audio.speech.create(
model="tts-1-hd",
voice="alloy",
input=text
)
response.stream_to_file("tts-1-hd_alloy_normal.mp3")
response = client.audio.speech.create(
model="gpt-4o-mini-tts",
voice="alloy",
input=text
)
response.stream_to_file("gpt-4o-mini-tts_alloy_normal.mp3")
Colab上で確認
from IPython.display import display, Audio
display(Audio("tts-1_alloy_normal.mp3"))
display(Audio("tts-1-hd_alloy_normal.mp3"))
display(Audio("gpt-4o-mini-tts_alloy_normal.mp3"))
実際に生成されたものはこちら
tts-1
tts-1-hd
gpt-4o-mini-tts
ちょっと声が変わったぐらいに感じるが、これまでよりもかなり結構自然な感じになったように思える。
そして``gpt-4o-mini-tts`ではプロンプトで以下のような観点で発話の調整ができる。
- アクセント
- 感情の幅
- イントネーション
- 印象
- 発話のスピード
- トーン
- ささやき
response = client.audio.speech.create(
model="gpt-4o-mini-tts",
voice="alloy",
input=text,
instructions="囁くように話してください。",
)
response.stream_to_file("gpt-4o-mini-tts_alloy_whisper.mp3")
display(Audio("gpt-4o-mini-tts_alloy_whisper.mp3"))
(snip)
instructions="ミュージカルの俳優のように大げさに話してください。",
(snip)
プロンプトで発話が大きく変わることがわかる。
https://www.openai.fm/ の例を見てみるといろいろ設定されている。"calm"というプロンプトはこんな感じになっていた。日本語訳。
声の表現: 落ち着きがあり、冷静で安心感を与える;静かな威厳と自信を表現する。
口調: 誠実で共感的、そして穏やかな威厳を持ち、能力を示しながら心からの謝罪を伝える。
話す速度: 安定していて程よい;配慮を示すために急がず、かつプロフェッショナリズムを示すのに十分効率的である。
感情: 本物の共感と理解を込め、特に謝罪の際には(「ご迷惑をおかけして大変申し訳ございません…」)温かみをもって話す。
発音: 明瞭で正確な発音を心がけ、重要な安心表現(「スムーズに」、「迅速に」、「即座に」)を強調して自信を補強する。
間(ポーズ): 援助を申し出た後や詳細を尋ねた後に短い間を置き、聞く姿勢と支援の意志を強調する。
色々参考になりそう。
ポッドキャストっぽいサンプル。文章は別のTTSの記事で使ったもの。
!pip install pydub
from pydub import AudioSegment
conversation_script = """
こんにちは、太郎です。今日は花子さんと、2025年春の競馬、G1レースの展望について語りたいと思います。まずは、各レースの見どころについて教えてください。
こんにちは、花子です。春のG1レースは例年通り熱い展開が期待されますね。たとえば、フェブラリーステークスで見せたコスタノヴァの走りは印象的でしたし、今後のレースにも大きな影響を与えそうです。
確かに。さらに、皐月賞ではファウストラーゼンやピコチャンブラックといった有力馬が注目されています。若手の勢いがこのレースの鍵になりそうですね。
その通りです。そして、NHKマイルカップからはアドマイヤズームの動きにも期待が高まっています。各レースで個性豊かな馬たちが戦うので、騎手や調教師の戦略も見逃せません。
また、春の締めくくりとして注目される天皇賞(春)も、昨シーズンの歴史を踏まえて、今年はより一層白熱した争いが予想されますね。
まさにその通りです。伝統と革新が融合する春のG1レース、ファンにとっては見逃せないシーズンになりそうです。
今日は、各レースの見どころや有力馬について熱く語れましたね。来たる春のレース、私たちもワクワクしながら応援していきましょう!
はい、最新情報をしっかりチェックしながら、競馬ファンとして楽しみたいですね。ご清聴ありがとうございました。
ありがとうございました。次回もお楽しみに!
"""
utterances = [line.strip() for line in conversation_script.split("\n") if line.strip()]
speakers = [ "sage","alloy"]
output_files = []
for idx, utterance in enumerate(utterances, start=1):
speaker = idx % 2
print(speakers[speaker], ":", utterance)
response = client.audio.speech.create(
model="gpt-4o-mini-tts",
voice=speakers[speaker],
input=utterance,
instructions="ポッドキャストのMCとして話してください。",
response_format="wav"
)
output_file = "{}_{}.wav".format(idx, speakers[speaker])
response.stream_to_file(output_file)
output_files.append(output_file)
combined = AudioSegment.empty()
for wav_file in output_files:
sound = AudioSegment.from_wav(wav_file)
combined += sound
combined.export("combined.wav", format="wav")
display(Audio("combined.wav"))
おー、この発話精度なら全然使えそうだなぁ
(〜)
で指定したところから発話を変えるってこともできるみたい。
ただ、(〜)
をそのまま発話しちゃう場合もあるらしい。詳しくは以下。
ただこれは正しい使い方なのかはちょっとわからないな。SDKの書き方を見る限りは、プロンプトと音声に変換したいテキストは別フィールドに分かれているわけだし。一緒に入れてよしなに発話させたいってのはニーズとしてはわかるんだけど。
あと、これ気になっている。
ただこれは正しい使い方なのかはちょっとわからないな。SDKの書き方を見る限りは、プロンプトと音声に変換したいテキストは別フィールドに分かれているわけだし。一緒に入れてよしなに発話させたいってのはニーズとしてはわかるんだけど。
あらためて元記事を読んでたんだけども、ここは自分の理解が違ってた。
そもそもプロンプトで指示することを、音声に変換したいテキスト部分にプロンプト的な指示を埋め込んだ場合にそれに従ってしまう、というのは「プロンプトインジェクション」と変わらない。フィールドが分かれているかどうかではなかった(これは開発者側の視点だった)
あるべき姿としてはこの2パターンになるのかな?
- 特別な指示などを気にせず「そのまま」読み上げる
- 意図しない動作を一切許容しない。安全で一貫性を重視。
- その代わり生成物が全てとなり、カスタマイズや調整の余地がなくなる。
- 「フォーマットに従って」読み上げを調整する
- 所定のフォーマットで書かれた文字列、意図を踏まえて生成に反映する。柔軟にカスタマイズが可能
- フォーマットの認識精度は100%でなければならない、それ以外の場合は想定しない動作が起きる可能性がある。
現状、プロンプト指示ができるTTSは常にこういう問題を抱えているということになるのか。まあTTSの使い方にもよるとは思うが、音声対話エージェントだと、TTSへの入力はLLMの出力になると思うので、制御が難しいところがあるかもしれない。
というところになるので、
あと、これ気になっている。
公式のフォーラムで教えてもらった(ただし公式の回答ではない)
多分アイコンが付いている音声のほうが感情表現が豊かってことでいいと思う。