Gemini Live API にテキストを送っても音声が返らない原因
リアルタイム音声対話の検証で、アプリ側から Gemini Live API にテキストを送り、それをきっかけに喋らせる仕組みを作っていました。clientContent でテキストを送ったのに、音声が返ってきません。エラーも返ってきません。転写も、ターン終了のイベントも、何も来ません。
原因は送信メッセージの 1 フィールドでした。`turnComplete: false` で送ったテキストは、完全に無視されます。
まず実測
7 種類のテキストキュー × 2 モデルで、turnComplete の値だけを変えて比較しました(2026-08-18 計測、v1beta の WebSocket 直結)。
- gemini-2.5-flash-native-audio-preview-12-2025
turnComplete: true: 7/7 応答(初動の中央値 976ms)turnComplete: false: 0/7。完全に無応答
- gemini-3.1-flash-live-preview
turnComplete: true: 7/7 応答(初動の中央値 598ms)turnComplete: false: 0/7。完全に無応答
false のときに何が返ってくるかというと、何も返ってきません。音声チャンクなし、転写なし、turnComplete イベントなし、そしてエラーもなしです。接続は生きたまま、ただ沈黙します。ここがハマりどころで、エラーが返れば送信側を疑えますが、無言で無視されると「モデルが不調なのか」「接続が死んでいるのか」「送り方が悪いのか」の切り分けから始めることになります。
なぜ無視されるのか
turnComplete は「ユーザーのターンがここで終わった」という宣言です。false は「まだ入力の途中」を意味するので、モデルは続きを待ちます。仕様として一貫した動作ではあります。
問題は、テキストを分割送信したい場面や「文脈だけ渡して応答はさせたくない」場面で false を使いたくなることです。少なくとも「あとで true を送れば溜めた分に応答してくれるだろう」という期待で false を使うと、応答が来ない理由を延々と探すことになります。アプリ主導でテキストキューを送って喋らせたいなら、答えは単純で、毎回 `turnComplete: true` で送ることです。
{
"clientContent": {
"turns": [{ "role": "user", "parts": [{ "text": "[PHASE:OPENING]" }] }],
"turnComplete": true
}
}ドキュメントとの食い違い
もうひとつ書き残しておくべきことがあります。公式の capabilities ガイド(2026-08 時点)には、3.1 系 live モデルについてこう書かれています。
send_client_contentis only supported for seeding initial context history (requires settinginitial_history_in_client_contentin session config). To send text updates during the conversation, usesend_realtime_inputinstead.
つまり 3.1 系では clientContent は初期履歴の投入専用で、会話中のテキストは realtimeInput で送れ、という記述です。しかし上の実測のとおり、gemini-3.1-flash-live-preview は会話中の clientContent(turnComplete: true)に 7/7 で応答しました。initial_history_in_client_content は設定していません。
どちらを信じるべきかで言えば、設計はドキュメントに寄せておくのが安全です。実測で動いているのは事実ですが、「ドキュメント上サポート外の経路がたまたま動いている」状態は、ドキュメントに明記された動作より先に消える可能性があります。私は当面 clientContent + turnComplete: true で運用しつつ、3.1 系に本格移行する時点で realtimeInput への切り替えを検証項目に入れています。
事前に心配していた事故は起きなかった
テキストキュー方式で心配していたのは、注入したテキストにモデルが口頭で返事してしまうこと(「了解です」と喋ってしまう)でした。これは 35 発話で 0 件でした。ただし条件付きです。システムプロンプトに「角括弧内は舞台指示。読み上げない。返事もしない」と明記した上での数字です。
代わりに実在した事故モードは転写への混入です。2.5 系で 14 発話中 1 件、角括弧テキスト([RIPPING] など)がそのまま出力転写に混ざりました。3.1 系では 0 件でした。転写をそのまま UI に出す設計なら、角括弧のフィルタを 1 枚挟んでおく必要があります。
この構成で気をつけること
- テキストを送って喋らせたいなら `turnComplete: true`。
falseは両モデルで完全に無視される(2026-08-18 実測) - 無視は無言で起きる。エラーが返らないので、応答がないときはまずこのフィールドを確認する
- 3.1 系の
clientContentは、ドキュメント上は初期履歴シード専用。実測では応答するが、恒久的な設計はrealtimeInput側に寄せておく - 舞台指示テキストは「読み上げない・返事しない」をシステムプロンプトに明記する。それでも転写混入は起き得るので、転写を表示するならフィルタを挟む
preview モデルでの計測なので、この挙動自体が今後変わる可能性はあります。ただ「応答がない、エラーもない」という症状に当たったとき、turnComplete が最初の容疑者になることは覚えておいて損がありません。