Gemini 3.8 TTSが指示まで読み上げるときはspeech_metadataを確認

Gemini 3.8 Flash TTSの台本と話し方の指示を分離し、Interactions APIへの移行と音声応答の確認手順を解説します。

セージ色の背景と淡いカードに黒い線で描いたステンシルシート。タイトルはGemini 3.8 TTS。

Gemini 3.8 Flash TTSでは、発話する言葉は台本へ、継続的な話し方の指示は音声メタデータへ分けます。 文字どおりの台本として扱われるテキストに「落ち着いて話して」と書くと、その指示自体が読み上げられる可能性があります。Gemini 3.8 Flash TTSの移行ガイドは台本と話し方のメタデータを明確に区別しています。

Googleは2026年9月22日のAPIリリースノートで新しいTTSモデルを発表しました。本記事はInteractions REST APIの公式資料に沿った移行例です。リクエスト構造とデコード処理はローカルで確認できますが、実際の音声を聴く試験、音質の向上、このエンドポイントの現在のOfox対応を主張するものではありません。

発話内容と話し方を分ける

情報この例での配置先
聞き手に届けたい言葉textコンテンツのtextフィールド
落ち着いて明瞭に、など継続する話し方speech_metadata注釈のstyle
音声の選択generation_config.speech_config
音声出力の指定response_format

短い指示でも分けておけば、台本との混同を避け、リクエストを確認しやすくなります。ただし登場人物が「落ち着いて話して」と言う台本なら、その言葉は聞かせる内容なので台本に含めます。

モデル文書には特定の時点に入れる発声イベントの説明もあります。以前のプロンプト用タグや任意の注釈がすべて使えると考えず、選んだモデルとAPIの現行リファレンスを確認してください。

リクエストから応答まで同じAPI形式を使う

以下はInteractions APIの例です。input配列やannotationsをGenerateContentの本文、または旧SDKのフィールドと混ぜないでください。この形式の出典は公式音声生成ガイドです。

次の内容をrequest.jsonに保存します。英語の短い台本を使った例をそのまま示します。

{
  "model": "gemini-3.8-flash-tts",
  "input": [{
    "type": "user_input",
    "content": [{
      "type": "text",
      "text": "The next train leaves at noon.",
      "annotations": [{
        "type": "speech_metadata",
        "style": "calm and clear"
      }]
    }]
  }],
  "response_format": {"type": "audio"},
  "generation_config": {
    "speech_config": [{"voice": "Kore"}]
  }
}

権限のある直接Googleアカウントでのリクエストは次のとおりです。

curl --fail-with-body --silent --show-error \
  'https://generativelanguage.googleapis.com/v1beta/interactions' \
  -H "x-goog-api-key: $GEMINI_API_KEY" \
  -H 'Content-Type: application/json' \
  --data-binary @request.json > response.json

自分のキーを環境変数から安全に渡してください。このコマンドは実際のAPIリクエストを送り、利用料金が発生する場合があります。ローカルでJSONを解析できても、モデルへのアクセス権や提供者による受理は確認できません。

これは一人の話者の例です。公式の複数話者設定は構造が異なります。上のspeech_config配列を独自の会話スキーマに作り変えないでください。各発話の話者は設定済みの話者と一致させる必要があります。

応答を確認してから音声をデコードする

response.jsonに保存されたHTTPエラーは音声ではありません。base64をデコードする前にHTTP結果と応答構造を確認します。InteractionsのREST応答ではmodel_outputステップとそのcontentブロックを調べます。SDKの便利なプロパティであるoutput_audioが生のJSONにもあるとは限りません。

堅牢なデコーダーでは次を確認します。

  1. エラー応答を音声ファイルとして書き出さない。
  2. model_outputの音声コンテンツを選び、テキストやツール内容は除く。
  3. 返されたMIMEタイプを確認してから拡張子を決める。
  4. base64をデコードし、元のコンテナを保持する。

移行ガイドによると非ストリーミング応答の既定出力はWAVです。古い生PCMの例からWAVヘッダーを無条件に追加しないでください。既に正しいWAVに二重のヘッダーを付けると破損する場合があります。別形式を指定した場合も、拡張子だけを変えるのではなく実際のMIMEタイプとコンテナに従います。

最初の移行テストを小さくする

一人の話者、短い台本、一つの話し方の指示から始めます。単語の欠落、余分な指示の読み上げ、発音、意図しない声の変化を聴いて確認します。リクエスト、モデルID、時刻、出力を一緒に保存してください。これらは受け入れ確認の提案であり、本記事で得た実測結果ではありません。

その後に台本を長くしたり話者を追加したりします。一度に変える要素は一つにします。メタデータへの移動と同時に声の変更、台本分割、API切り替えまで行うと原因を絞れません。

ナレーションでは映像に組み込む前に、生成音声と正確な台本を照合します。顔出しなし動画の制作ガイドは全体の工程を扱います。TTS移行はその一段階であり、タイミングや発音、特定の声の利用同意まで保証するものではありません。

別の提供者を経由する前の確認

OpenAI互換のテキストAPIがあるだけでは、GoogleのInteractions APIや音声メタデータへの対応は分かりません。音声専用ルート、対応モデルID、出力形式を確認します。本記事の直接Google向け例はOfoxの接続設定例ではありません。

モデル選択とAPI形式の移行も分けます。関連するGemini 3.8 Flash-Lite TTSに文字列だけを変更する前に、そのモデルの資料で対応と挙動を確認してください。マルチモーダルAPIの概要(英語)は全体像の参考になりますが、現行の提供者文書に代わるものではありません。

よくある質問

話し方の指示まで読まれるのはなぜですか?
新しいモデルは入力テキストを文字どおりの台本として扱います。継続的な話し方の指示は台本に混ぜず、文書で指定された音声メタデータへ置いてください。
このJSONをGenerateContentに使えますか?
いいえ。この例はInteractionsの入力・注釈フィールドを使います。GenerateContentはリクエスト構造が異なるため、そのAPI用の公式例で全体を統一してください。
出力は必ず生PCMですか?
いいえ。移行ガイドでは非ストリーミング応答の既定値はWAVです。実際の応答形式を確認し、WAVヘッダーを二重に追加しないでください。