Gemini Live API にテキストを送っても音声が返らない原因
リアルタイム音声対話の検証で、アプリ側から Gemini Live API にテキストを送り、それをきっかけに喋らせる仕組みを作っていました(テキストキューで喋らせる理由は Gemini Live API の proactive audio は自発的に喋らない)。clientContent でテキストを送ったのに、音声もエラーも、転写もターン終了のイベントも返ってきませんでした。
原因は送信メッセージの 1 フィールドで、`turnComplete: false` で送ったテキストは完全に無視されます。
まず実測
7 種類のテキストキュー × 2 モデルで、turnComplete の値だけを変えて比較しました(2026-08-18 計測、v1beta の WebSocket 直結。接続の仕方は SDK なしで Gemini Live API を WebSocket で直接叩く)。
- gemini-2.5-flash-native-audio-preview-12-2025
turnComplete: true: 7/7 応答(初動の中央値 976ms。初動の遅れは Gemini Live API の音声応答が 6 秒遅れる原因は thinking)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 に出す設計なら、角括弧のテキストを除くフィルタを入れておく必要があります。
テキストキューは毎回 turnComplete: true で送り、転写に出た角括弧は除く
- テキストを送って喋らせたいなら `turnComplete: true`。
falseは両モデルで完全に無視される(2026-08-18 実測) - 無視されてもエラーは返らないので、応答がないときはまずこのフィールドを確認する
- 3.1 系の
clientContentは、ドキュメント上は初期履歴シード専用。実測では応答するが、恒久的な設計はrealtimeInputで送る形にしておく - 舞台指示テキストは「読み上げない・返事しない」をシステムプロンプトに明記する。それでも転写混入は起き得るので、転写を表示するならフィルタを挟む
preview モデルでの計測なので、この挙動自体が今後変わる可能性はあります。ただ「応答がない、エラーもない」という症状に当たったとき、最初に確かめるのは turnComplete の値です。