はじめに

2026年9月15日、Google DeepMind が音声対音声(audio-to-audio)の新モデル Gemini 3.8 LiveGemini 3.8 Live Extended Thinking を発表し、同日の Gemini API リリースノートは両モデルを Live API で GA(一般提供) と記しました。モデル ID は gemini-3.8-livegemini-3.8-live-extended-thinking です。Google の開発者向け記事は、音声入力 $0.005/分・音声出力 $0.018/分という価格と、「会話を続けながら裏でツールを実行する」非同期 function calling を看板に掲げています。

当サイトには、この API を ESP32-S3 から直接つないでいる実機があります。8月に公開したスタックチャンの習慣コーチは、PC を頭脳、M5 の CoreS3 を顔と声に分け、音声だけを Live API へ WebSocket で直結しています。そこで使っているモデルは gemini-3.1-flash-live-preview。Google のドキュメントは今回、このモデルを「レガシーのプレビュー。3.8 Live への更新を推奨」と位置づけました。つまり、うちのロボットの「声」に世代交代の順番が回ってきた、というニュースです。

この記事は、載せ替えの前に一次ドキュメントを読んで整理した「設計図」です。扱うのは次の 5 点です。

  1. Live API とは — STT→LLM→TTS の 3 段パイプラインと何が違うのか。WebSocket 双方向・16 kHz 入力・24 kHz 出力・割り込みの仕組み
  2. ephemeral token とは — デバイスに API キーを置かずに直結する短命トークン。発行の流れと制約
  3. Extended Thinking とは — 「考えながら話す」を API がどう表現するか(interaction_status
  4. 何が変わったか — 2.0 → 2.5 → 3.1 → 3.8 の系譜、料金表、3.1 からの移行で削る設定・足す設定
  5. スタックチャンで変える点と実測の計画 — モデル ID・鍵の渡し方・思考の扱い。遅延・内部 RAM・費用は何をどう測るかを決めた(測るのは次の回)
⚠️ 数値の帰属と時点

本記事の仕様・料金・ベンチマークは、Google DeepMind のブログ(9月15日・17日更新)、Google の開発者向け記事(9月15日)、ai.google.dev の Live API ドキュメント群(Last updated 2026-09-15〜18)、料金ページ(2026-09-16)、モデルカード(9月15日) にあるものだけを使い、2026年9月19日に取得しました。ベンチマークの数値は Google 自身の発表値です。実機での遅延・RAM・費用は本記事の時点(2026年9月20日)では まだ測っていません。「📊 実測の計画」の節には、何をどう測るかだけを置いています。X(旧 Twitter)の投稿は出典に使っていません。

📌 この記事の3行まとめ
  • 9月15日、gemini-3.8-livegemini-3.8-live-extended-thinking が Live API で GA。 前者は低遅延の既定、後者は会話を止めずに裏で推論する高推論版。どちらも安定版(Stable)の ID で、非同期 function calling が既定。旧 gemini-3.1-flash-live-preview は「3.8 Live へ更新推奨」に
  • 料金は音声入力 $3.00/1M トークン(約 $0.005/分)・音声出力 $12.00/1M(約 $0.018/分)。 音声単価は 2.5 Flash Native Audio と同じで、テキスト単価だけ上がった(入力 $0.50→$0.75・出力 $2.00→$4.50)。3.8 では Proactive audio が常時 ON になり、聞いている時間ぶん入力トークンが課金されると公式が明記
  • スタックチャンで変えるのは 3 点。 モデル ID の 1 行、API キー直結(?key=)から PC で発行する ephemeral token(?access_token=・別エンドポイント)への切り替え、Extended Thinking を使うなら turnComplete ではなく interaction_status で状態機械を回す改修

🧭 1. Live API とは — 音声を「文字にしてから考える」をやめた API

Live API は、Gemini とのあいだで音声・画像・テキストを連続したストリームとして双方向にやり取りするための API です。公式の技術仕様は次の 3 行に集約されます。

項目 仕様(Live API overview・2026-09-15)
入力 音声(raw 16-bit PCM・16 kHz・リトルエンディアン)、画像(JPEG・1 fps 以下)、テキスト
出力 音声(raw 16-bit PCM・24 kHz・リトルエンディアン)
プロトコル ステートフルな WebSocket 接続(WSS)

3 段パイプラインとの違い

音声で AI と会話する仕組みは、大きく 2 通りあります。

flowchart LR subgraph CAS["カスケード方式(従来の 3 段)"] direction TB M1["マイク"] --> S1["音声認識(STT)"] --> L1["LLM(テキスト)"] --> T1["音声合成(TTS)"] --> P1["スピーカー"] end subgraph A2A["audio-to-audio(Live API)"] direction TB M2["マイク"] --> G["Gemini Live
音声を直接入出力"] --> P2["スピーカー"] end CAS ~~~ A2A

カスケード方式は、話し終わりを検出してから、音声認識(STT)で文字にし、LLM が返答を作り、音声合成(TTS)で読み上げます。3 つの処理が直列に並ぶので、遅延はそれぞれの足し算になります。声の調子や言いよどみは STT の段階で文字に潰れ、LLM には届きません。ユーザーが途中で割り込むと、3 段すべてを止めて捨てる制御が必要です。

audio-to-audio は、1 つのモデルが音声トークンを直接受け取り、音声トークンを直接出します。Google の開発者向け記事はこれを「カスケード構成に対する、より簡素な代替」と表現しています。話し終わりの検出(VAD)は既定ではサーバー側で行われ、ユーザーが割り込むと生成中の応答はサーバー側で打ち切られて捨てられ、クライアントには interrupted の通知が届く(capabilities ページ)。会話の履歴も文字ではなく音声トークンのまま保持されると、料金の説明に明記されています。

💡 ワード解説:WebSocket と VAD(barge-in)
  • WebSocket:HTTP のリクエスト/レスポンスと違い、一度つないだら双方が好きなタイミングでメッセージを送れる常時接続の仕組み。マイクの音声を細切れに送り続けながら、同じ接続でスピーカー用の音声を受け取れる。Live API では wss://(TLS 付き)で接続する
  • VAD(Voice Activity Detection):「いま人が話しているか」を検出する処理。Live API では既定でサーバー側が行い、モデルが話している最中にユーザーが話し始めると生成を打ち切る。この「話しかぶり」を barge-in(割り込み) と呼ぶ
  • PCM(Pulse Code Modulation):圧縮していない生の音声サンプル列。16-bit・16 kHz なら 1 秒あたり 32,000 バイト。ESP32 の I2S マイク/スピーカーが扱うのもこの形式なので、変換なしでそのまま流せる

接続の一生:setup → realtimeInput → serverContent

WebSocket を張った後のメッセージの流れは、次のとおりです。当サイトのスタックチャンが実際に送受信しているフィールド名で書いています。

sequenceDiagram participant D as ESP32-S3(マイク/スピーカー) participant G as Live API(wss) D->>G: setup(model・responseModalities AUDIO
systemInstruction・tools・sessionResumption) G-->>D: setupComplete loop 会話ターン D->>G: realtimeInput.audio(PCM 16 kHz・base64)を送り続ける G-->>D: serverContent.modelTurn
parts[].inlineData(PCM 24 kHz) G-->>D: inputTranscription / outputTranscription(有効化時) G-->>D: toolCall(関数呼び出し) D->>G: toolResponse G-->>D: serverContent.turnComplete end G-->>D: goAway(接続終了の予告)
sessionResumptionUpdate(再開ハンドル)
  • 最初のメッセージは必ず setup モデル名、応答モダリティ(音声)、システム指示、関数宣言、セッション再開の指定をここで渡します
  • 音声は realtimeInput で送り続ける。 話し終わりを自分で判定して送る必要はなく、サーバー側の VAD が区切ります
  • 応答は serverContent で細切れに返る。 modelTurn.parts[].inlineData が 24 kHz の PCM で、届いた順にスピーカーへ流します。1 つのサーバーイベントに複数のパート(音声と文字起こしなど)が同時に入るので、全部処理しないと取りこぼす、と公式が注意しています
  • turnComplete でターンが終わる。 ただし後述の Extended Thinking では、この意味が変わります

セッションの寿命と再接続

Live API の「セッション」は 1 本の持続的な接続です。ここに公式の上限があります(Session management・2026-09-15)。

制約 回避策
音声のみのセッション 15 分(圧縮なし) コンテキストウィンドウ圧縮(contextWindowCompression)で無制限
音声+映像のセッション 2 分(圧縮なし) 同上
1 本の接続の寿命 約 10 分 セッション再開(sessionResumption)。終了前に goAway が届く
再開ハンドルの有効期限 最後のセッション終了から 2 時間

スタックチャンのファーム(土台の ciniml/stackchan-idf)は、goAway を受けたら再開ハンドルで先回りして張り直す処理を持っています。この節の話は、次の ephemeral token で効いてきます。

2 つの実装形態:server-to-server と client-to-server

公式は実装を 2 通りに分けています。

  • server-to-server:自分のバックエンドが Live API とつなぎ、端末はバックエンドに音声を送る
  • client-to-server:端末(ブラウザやデバイス)が Live API に直接つなぐ。バックエンドは経由しない

公式は「client-to-server のほうがストリーミングの性能は一般に良く、プロキシを書かなくてよいので簡単。ただし本番では標準の API キーではなく ephemeral token を使うことを推奨」と書いています。スタックチャンは ESP32-S3 が直結する client-to-server そのものです。だから次の節が、載せ替えの本丸になります。


🔑 2. ephemeral token とは — デバイスに API キーを置かないための短命の鍵

スタックチャンの現行ファームは、WebSocket の URL に ?key=<API キー> を付けて直結しています。中継サーバが要らない代わりに、API キーそのものが端末の NVS に入っている構成です。公式は client-to-server の本番構成としてこれを勧めておらず、代わりに用意されているのが ephemeral token(短命トークン)です。ドキュメント上は Preview 扱いで、Live API 専用(他の API では使えない)です。

仕組み

flowchart TD C["端末(ブラウザ/ESP32)"] -->|"① 自前の認証"| B["自分のバックエンド
(API キーはここだけ)"] B -->|"② auth_tokens.create"| P["Gemini API のトークン発行"] P -->|"③ 短命トークン"| B B -->|"④ トークンを端末へ"| C C -->|"⑤ access_token で
WSS 直結"| L["Live API"]

公式の説明を順に追うと、① 端末が自分のバックエンドに認証し、② バックエンドが API キーで Gemini API の発行サービスにトークンを要求し、③ 短命トークンが発行され、④ バックエンドが端末に渡し、⑤ 端末はそれを API キーの代わりに使って Live API へ直結します。音声はバックエンドを通らないので、遅延の利点はそのまま残ります。

公式は「ephemeral token も標準の API キーと同じくクライアント側から抜き出せる」と正直に書いたうえで、すぐ失効し、用途を制限できるので本番環境のリスクを大きく下げる、と位置づけています。

既定値と制約

項目 既定値/仕様(Ephemeral tokens・2026-09-15)
使用回数 uses 1(新しいセッションを 1 回だけ開始できる)
新規セッションを開始できる期限 newSessionExpireTime 発行から 1 分
メッセージを送れる期限 expireTime 発行から 30 分
10 分ごとの接続張り直し expireTime 内なら同じトークンでセッション再開(uses: 1 でも可)
設定のロック liveConnectConstraints モデル名・responseModalitiessessionResumption などをトークンに固定できる
接続先 BidiGenerateContentConstrained?access_token=<トークン>v1beta のみ

2 点、設計に効く仕様があります。

1 つは 接続先エンドポイントが変わることです。API キーは .../BidiGenerateContent?key=...、トークンは .../BidiGenerateContentConstrained?access_token=...。SDK を使わない生 WebSocket では、パスとクエリ名の両方を差し替えます(HTTP ヘッダ Authorization: Token <トークン> でも渡せます)。

もう 1 つは 設定のロックです。発行時に live_connect_constraints でモデル名や応答モダリティを固定でき、公式は「システム指示をサーバー側に置いておくためにも有用」としています。スタックチャンは人格プロンプトを NVS の 2,048 バイトに詰めていました。トークンに設定を載せる方式なら、その制約の外に出せる可能性があります(ここは実機で確かめる項目です)。

# バックエンド側(PC)でトークンを発行する最小例。公式ドキュメントの例をもとに、
# モデルと応答モダリティを固定している。token.name を端末に渡す
from google import genai

client = genai.Client()  # 環境変数 GEMINI_API_KEY を読む。キーはコードに書かない
token = client.auth_tokens.create(
    config={
        "uses": 1,
        "live_connect_constraints": {
            "model": "gemini-3.8-live",
            "config": {
                "session_resumption": {},
                "response_modalities": ["AUDIO"],
            },
        },
    }
)
print(token.name[:12] + "...")  # 端末へ渡す値。ログには全文を出さない

🧠 3. Extended Thinking とは — 「ちょっと待ってね」と言いながら裏で考える

gemini-3.8-live-extended-thinking は、Live API にバックグラウンド推論を持ち込んだモデルです。公式の「Thinking in the Live API」の説明を、仕組みとして分解します。

何が問題だったか

通常の音声モデルは、話しかけられたら即座に返事を生成します。すぐ答えられる会話には向いていますが、計画・複雑な分析・外部ツールが必要な依頼が来ると、公式の言葉で「推論なしに答えるか、ツールが終わるまで黙って止まるか」の二択になっていました。

どう解決したか

Extended Thinking は、推論と非同期ツール呼び出しを裏で回しながら、表では「つなぎの発話」を続けます。公式の例は「いまフライトの選択肢を確認しています」。DeepMind のブログでは「Let me check that…」のような早めの相づちと、複数ステップの進捗を声で実況する挙動が紹介されています。

これは会話のライフサイクルを 2 点で変えます

sequenceDiagram participant U as ユーザー participant M as 3.8 Live Extended Thinking U->>M: 「来週のシアトル行き、安い便ある?」 M-->>U: 音声「ちょっと調べますね」+ turnComplete: true
(interactionStatus: IN_PROGRESS) Note over M: 裏で推論・非同期ツール呼び出し M-->>U: toolCall(interactionStatus: IN_PROGRESS) U->>M: toolResponse M-->>U: 音声「3 便ありました。いちばん安いのは…」
+ turnComplete: true(interactionStatus: IDLE)
  1. つなぎの発話:1 つの依頼に対してモデルが複数回話す。最初の turnComplete: true は「一言終わった」であって「用が済んだ」ではない
  2. interaction_status:サーバーメッセージに IN_PROGRESS(裏で処理中。まだ音声やツール呼び出しが来る)と IDLE(全部終わった。入力待ち)が付く。クライアントは turnComplete ではなく interaction_status で「聞いていい状態か」を決める

3.8 Live と 3.8 Live Extended Thinking の違い

同日に出た 2 モデルの差は、公式の比較表に整理されています。

項目 Gemini 3.8 Live Gemini 3.8 Live Extended Thinking
推奨用途 低遅延の音声エージェント・直接的な指示・ミリ秒で返るツール(公式例:センサー値の読み取り・スマート機器の操作) 複数ステップの問題解決・複雑な計画・数秒かかるツール(診断・予約・STEM の家庭教師)
推論 interleaved reasoning(固定の遅延プロファイル)。thinking_level非対応(setup から省く) 裏で推論。thinking_levellowmediumhighminimal は非対応)
ターンの境界 turnComplete: true でターン終了=待機に戻る turnComplete: true は「一言終わった」。interaction_status がセッションの状態を決める
つなぎの発話 ツール実行が終わるまで話さない 処理中に中間の発話を流す
ツール実行 同期(BLOCKING)・非同期(NON_BLOCKING)どちらも可。非同期が既定 非同期のみBLOCKING を指定するとエラー
💡 ワード解説:interleaved reasoning と非同期 function calling
  • interleaved reasoning:公式は 3.8 Live の推論をこう呼び、thinking_level で深さを変える方式ではなく「固定の遅延プロファイル」だと説明している。ユーザーが待たされない範囲で、音声生成の合間に推論が挟まる、という理解でよい(内部の実装は公開されていない)
  • 非同期 function calling(behavior: NON_BLOCKING:関数呼び出しの結果を待たずにモデルが話し続ける方式。結果は後から toolResponse で返し、モデルがそれを会話に織り込む。3.8 Live では既定になり、従来どおり結果を待たせたいときは関数宣言に behavior: BLOCKING を付ける。Live API に非同期呼び出しが入ったのは 2025年5月(リリースノート)で、3.8 で「既定」に昇格した

📅 4. 何が変わったか — 系譜・料金・移行で削る設定

Live API モデルの系譜

Gemini API のリリースノートと非推奨ページから、Live API のモデルだけを抜き出すと次のようになります。

timeline title Live API のモデル世代交代 2024-12〜2025 : 2024-12 Live API 初出 2.0 Flash 実験版 : 2025-04 2.0-flash-live-001 課金つき プレビュー : 2025-05〜12 2.5 native audio プレビュー 3 版 : 2025-12-09 2.0 系 終了 2026 上半期 : 2026-03 3.1 Flash Live プレビュー : 2026-08 3.5 Transcribe Live GA 2026-09-15 : 3.8 Live GA 非同期ツール 既定 : 3.8 Live ET GA 裏で推論 : 3.1 は legacy 3.8 へ 更新推奨
モデル ID 公開 状態(非推奨ページ・2026-09-17)
gemini-2.0-flash-live-001 2025-04-09 2025-12-09 に終了。後継は 3.8 Live
gemini-live-2.5-flash-preview 2025-06-17 2025-12-09 に終了。後継は 3.8 Live
gemini-2.5-flash-native-audio-preview-12-2025 2025-12-12 終了日未定。後継は 3.8 Live
gemini-3.1-flash-live-preview 2026-03(リリースノート 3/26・非推奨ページは 3/11) 終了日未定。「レガシー。3.8 Live へ更新推奨」
gemini-3.8-live 2026-09-15 Stable・終了日未定
gemini-3.8-live-extended-thinking 2026-09-15 Stable・終了日未定

スタックチャンの制作中に「音声側・テキスト側の両方でモデルの提供終了に遭遇した」と前回書きましたが、この表を見ると Live 系は 2025年12月に 2 本が同時に終了しています。プレビュー版のモデル名をコードに直書きしない、という前回の教訓はそのまま生きています。3.8 は初めて Stable の ID が付いた Live モデルで、ここは前進です。

仕様の要点(モデルページ・モデルカード)

項目
入力トークン上限 131,072(モデルカードでは「最大 128K」)
出力トークン上限 65,536
入力 テキスト・画像・音声・映像
出力 音声(テキストの書き起こしは outputAudioTranscription を有効化)
ベースモデル Gemini 3 Pro(モデルカード)
知識のカットオフ 2025年1月(モデルカード)
対応する機能 Function calling・Google 検索グラウンディング・Live API・Thinking
非対応 キャッシュ・コード実行・構造化出力・URL context・Batch API
生成音声の透かし すべての生成音声に SynthID(DeepMind ブログ)

対応言語数は、Google の一次資料どうしで数字が割れています。 DeepMind のブログは「97 の対応言語を会話中に自動で検出・切り替え」、開発者向け記事は「97+ 言語」と書き、一方で Live API の概要ページ(2026-09-15 更新)は「70 の対応言語」のままです。モデル別の数(97)と API 全体の説明(70)の差なのか、ページの更新漏れなのかは明記がありません。本記事は両方を併記し、日本語が含まれることだけを前提にします(3.1 世代で日本語会話が成立していることは前回の実機で確認済みです)。

ベンチマーク(Google 発表値)

DeepMind のブログが挙げる数値は次のとおりです。いずれも Google 自身の発表値で、当サイトで再現はしていません。

  • 3.8 Live Extended Thinking:Artificial Analysis の Speech to Speech Quality Index で総合 1 位(82.6)、τ-Voice 68.6%、Sierra の τ-Voice-banking 35.1%、Big Bench Audio 97.7%
  • 3.8 Live:Speech Agent Arena で 2 位
  • ServiceNow の EVA-Bench で「精度と会話品質のパレート最前線を押し上げた」。ブログには「Gemini Enterprise Agent Platform 上の Live API で計測」との注記あり

料金

料金ページ(2026-09-16 更新)の Live 系の行です。3.8 Live・3.8 Live Extended Thinking・3.1 Flash Live Preview は同じ行にまとめられています。

Free Tier Paid Tier(1M トークンあたり・USD)
入力・テキスト 無料 $0.75
入力・音声 無料 $3.00(約 $0.005/分
入力・画像/映像 無料 $1.00(約 $0.002/分)
出力・テキスト 無料 $4.50
出力・音声(思考トークン込み) 無料 $12.00(約 $0.018/分
Google 検索グラウンディング 対応 月 5,000 回まで無料(3.x 全体で共有)、以降 1,000 回 $14
製品改善への利用 あり なし

比較のため、同じページにある 2.5 Flash Native Audio(gemini-2.5-flash-native-audio-preview-12-2025)は、入力テキスト $0.50・入力音声 $3.00、出力テキスト $2.00・出力音声 $12.00 です。音声の単価は据え置きで、テキストの単価だけ上がった、と読めます。

ただし Live API の課金は「1 回いくら」ではありません。Best practices ページの「Pricing and billing」に、次の 4 点が書かれています。

⚠️ Live API の課金は「ターンごとに文脈を丸ごと再計算」
  1. ターンごとに、セッションの文脈に入っている全トークンが課金対象。前のターンの音声も毎回「再処理」として数えられるので、会話が長くなるほど 1 ターンの費用が増える(公式は compounding model と表現)
  2. 履歴は音声トークンのまま保持され、毎ターン音声入力の単価で課金される
  3. 文字起こしを有効にすると追加課金inputAudioTranscriptionoutputAudioTranscription で生成されるテキストは、音声とは別にテキスト出力の単価($4.50/1M) で課金
  4. 3.8 では Proactive audio が常時 ON。公式は「Proactive audio が有効なとき、API は聞いている間ずっと入力トークンを課金し、出力は応答したときだけ課金する」と明記。3.1 では Proactive audio が非対応で、能動的に音声を送っている間だけの課金だった

4 点目は、机の上に置きっぱなしにする会話ロボットにとって、課金の単位が「発話」から「聞いている時間」に変わることを意味します。公式が挙げる対策は contextWindowCompression で文脈の上限(例:25,000 トークンで発動・8,000 トークンの窓)を決めておくこと。実機側では、話していないときにセッションを閉じる待機モードが、そのまま費用の蓋になります。

3.1 Flash Live から 3.8 Live へ:公式の移行チェックリスト

3.8 Live のモデルページに「Migrating from Gemini 3.1 Flash Live」として列挙されている変更点です。削る設定と、意味が変わる設定が混じっています。

項目 3.8 Live での扱い
モデル文字列 gemini-3.1-flash-live-previewgemini-3.8-live
thinking_levelthinking_config 非対応。setup から省く(付けるとエラー)
Function calling 非同期(NON_BLOCKING)が既定。従来どおりにするなら宣言に behavior: BLOCKING。スケジューリング(SILENTWHEN_IDLEINTERRUPTED)対応
send_client_content セッション中いつでも送れる(role を明示)。turn_complete=true無条件に生成を中断
Proactive audio 常時有効proactive_audio: false を送るとエラー
Affective dialogue API から削除enable_affective_dialog の設定を消す
Turn coverage 既定が TURN_INCLUDES_AUDIO_ACTIVITY_AND_ALL_VIDEO映像フレームは送った分だけ既定でモデルに渡るので、必要なときだけ送る
応答モダリティ 音声のみ。文字が要るなら outputAudioTranscription

Extended Thinking へ上げる場合は、これに加えて interaction_status の監視全関数宣言を NON_BLOCKINGthinking_configlowmediumhigh を指定の 3 点が公式の「Upgrading」に書かれています。


🤖 5. スタックチャンで変える点 — モデル ID・鍵の渡し方・思考の扱い

現行の構成(8月の記事の要約)

前回の記事の構成を、載せ替えに関係する部分だけ抜き出します。

flowchart LR subgraph PCBOX["PC アプリ(Python・FastAPI)=頭脳"] Q["今日の課題・履歴
GET /context・POST /report"] end subgraph DEV["CoreS3(ESP32-S3・ESP-IDF 5.5)=顔と声"] F["ciniml/stackchan-idf
+ 当サイトのパッチ 7 本"] end G["Live API
gemini-3.1-flash-live-preview"] PCBOX -->|"起動時に課題と指示を渡す"| DEV DEV -->|"達成報告・書き起こし"| PCBOX DEV <-->|"wss ... BidiGenerateContent?key=API キー"| G
  • 音声は PC を通らない。 CoreS3 が Live API に WebSocket で直結し、16 kHz で送って 24 kHz を再生する
  • モデルは gemini-3.1-flash-live-preview 土台の ciniml/stackchan-idf の既定は gemini-2.0-flash-live-001 で、そこから 2.5 Flash Native Audio を経て 3.1 に上げた(当サイトのパッチ 0003)。モデル名は main/conversation_task.cpp の 1 行
  • setup で送っているもの:モデル名、responseModalities: ["AUDIO"]、声(speechConfig)、人格プロンプト(systemInstruction)、入力/出力の文字起こし、関数宣言(達成報告などのツール)、sessionResumptionthinking_configenable_affective_dialogproactive_audio は送っていない
  • 鍵は ?key= でクエリに載せる。 API キーは NVS に注入され、PC アプリと共用
  • 内部 RAM が主戦場。 設定用 httpd と TLS/WebSocket が連続した内部 RAM を奪い合い、最小空きが 23 バイトまで落ちた。会話モードでは httpd を起動しない対策で、最大連続ブロックが 8.7 KB → 19.5 KB に回復
  • PC が居なくても単体で動く。 2 秒だけ PC への到達を試し、居なければ人格だけで会話を始める

載せ替えで変える 3 点

公式の移行チェックリストを現行 setup と突き合わせると、削るべき設定はもともと送っていないので、変更は次の 3 点に絞れます。

# 変える点 どこを 内容
1 モデル ID main/conversation_task.cpp のモデル指定(パッチ 0003 の対象行) gemini-3.1-flash-live-previewgemini-3.8-livethinking_level は送っていないので他に触る箇所なし。関数宣言に behavior が無いため、3.8 では非同期が既定になる。達成報告ツールは PC への HTTP 1 往復(前回の記事でコンテキスト取得が 267〜323 ms)なので、公式の「ミリ秒で返るツール」の範囲。まず BLOCKING を明示して従来と同じ挙動で測り、次に既定の非同期で測る、の 2 段階にする
2 鍵の渡し方 components/conversation/gemini_live_client.cpp の URL 組み立て(パス定数と ?key=)+ PC アプリ パスを BidiGenerateContentBidiGenerateContentConstrained、クエリを ?key=?access_token= に。トークンは PC アプリが auth_tokens.create で発行し、既存の GET /context(セッション開始時に 1 回)の応答に同梱する。newSessionExpireTime が 1 分なので、取得してすぐ接続する現在の順序と合う。10 分ごとの張り直しは既存の goAway → 再開ハンドルの処理で、同じトークンのまま通る(公式)
3 思考の扱い conversation_task.cpp の状態機械(Listening → Thinking → Speaking) 3.8 Live なら変更なしturnComplete で Listening に戻す現行のままでよい、と公式)。Extended Thinking を試すなら要改修:現行は turnComplete で Listening(顔の背景が緑=話しかけて OK)に戻すので、裏で推論中に緑が点く。interactionStatusIN_PROGRESS の間は Thinking(青)を維持し、IDLE で緑に戻す。関数宣言は全部 NON_BLOCKING に。15 秒の Thinking タイムアウトも IDLE 基準に見直す
✅ ephemeral token で「PC が居ない日」をどうするか

現行は PC 不在でも API キーで単体動作します。トークンを発行できるのは API キーを持つ側(PC)だけなので、トークン方式に全面移行すると PC 不在=声なしになります。選択肢は 2 つ。(a) PC 不在時だけ従来の ?key= 直結にフォールバックする(キーは NVS に残る。安全性の改善は「PC が居る日」に限られる)、(b) NVS からキーを消し、PC 不在の日は単体動作を諦める(前回の記事で「フォールバックの徹底」と書いた設計思想を一部手放す)。この記事では決めません。実機の運用で PC が落ちている頻度を見て決める項目です。

載せ替え後の構成

flowchart TD subgraph PCBOX["PC アプリ=頭脳+鍵の番人"] K["API キーは PC の .env だけ"] -->|"auth_tokens.create"| Q["GET /context に
短命トークンを同梱"] end subgraph DEV["CoreS3=顔と声"] F["NVS にキーを置かない
(選択肢 b の場合)"] end G["Live API
gemini-3.8-live"] Q -->|"トークン
(1 分以内に接続・30 分有効)"| DEV DEV <-->|"wss ...Constrained
?access_token=トークン"| G

📊 6. 実測の計画 — 遅延・内部 RAM・費用は実験室 #3 で測る

3.8 Live に載せ替えたときの遅延・内部 RAM・費用は、本記事の時点(2026年9月20日)ではまだ測っていません。この節に置くのは、何をどの順で測るかの計画です。測る作業そのものは 【連載】Google AI 実験室 の次の回(#3)で行い、結果はそちらの記事にまとめます。前提の環境は次のとおり。

  • PC 側Google AI 実験室 #1 の環境(記事専用の Google Cloud プロジェクト・Tier 1・キーは 01-setup/.env だけ・uv+Python 3.12+google-genai)。Live 系は Free Tier でも呼べますが、費用を測るので課金プロジェクトで回します
  • 実機側前回の記事のビルド環境(ESP-IDF 5.5・build-cores3firmware/README.md の PowerShell 手順)
  • 比較の相手:現行の gemini-3.1-flash-live-preview。前回の記事で公開済みの値を基準にし、今回同じ条件で測り直した値と並べる

手順 0:モデルが見えることを確認する

# Google AI 実験室 #1 の list_models.py をそのまま使う。Live の 2 本が出れば OK
uv run 01-setup/list_models.py | Select-String -Pattern "live"

見るもの:出力に gemini-3.8-livegemini-3.8-live-extended-thinking が並ぶこと。

手順 1:PC からトークンを発行し、有効期限を読む

第 2 節のコードを 03-live/mint_token.py として置き、uv run で実行します。表示するのはトークンの先頭だけにし、全文はログにも記事にも出しません。

  • 読むもの:token.name の先頭 12 文字と、expire_timenew_session_expire_time の実際の値
  • 確かめること:live_connect_constraints でモデルを固定したトークンで、setup 側に別のモデル名を書いたときの挙動(エラーか、トークン側が勝つか。公式に明記なし)

手順 2:PC 単体で 1 往復し、トークンの内訳を読む

実機を触る前に、SDK で 1 往復だけ回して usageMetadata の内訳(モダリティ別トークン数)を取ります。実機側のファームは usageMetadata を解析していないので、費用の一次データは PC 側で取るのがいちばん確実です。

# 03-live/one_turn.py — テキストで 1 問投げ、音声を受け取り、トークン内訳を出す
# 公式 capabilities ページの「Establishing a connection」「Token count」の例を組み合わせたもの
import asyncio
from dotenv import load_dotenv
from google import genai

load_dotenv()
client = genai.Client()  # GEMINI_API_KEY を環境変数から読む

MODEL = "gemini-3.8-live"  # 比較時は gemini-3.1-flash-live-preview に差し替える
CONFIG = {"response_modalities": ["AUDIO"], "output_audio_transcription": {}}

async def main():
    audio_bytes = 0
    async with client.aio.live.connect(model=MODEL, config=CONFIG) as session:
        await session.send_realtime_input(text="一言で自己紹介してください。")
        async for msg in session.receive():
            sc = msg.server_content
            if sc and sc.model_turn:
                for part in sc.model_turn.parts:
                    if part.inline_data:
                        audio_bytes += len(part.inline_data.data)
            if sc and sc.output_transcription:
                print("Gemini:", sc.output_transcription.text)
            if msg.usage_metadata:
                u = msg.usage_metadata
                print("total:", u.total_token_count)
                for d in u.response_tokens_details or []:
                    print(" ", d.modality, d.token_count)
            if sc and sc.turn_complete:
                break
    print("audio bytes:", audio_bytes, "≈", audio_bytes / (24000 * 2), "sec @24kHz")

asyncio.run(main())

同じ質問を 3.1 Flash Live Preview・3.8 Live・3.8 Live Extended Thinking(thinking_level: low)の 3 本に投げ、次を並べます。

  • 応答音声の長さ(秒)
  • 入力トークンと出力トークン(音声/テキストのモダリティ別)
  • 思考トークン(Extended Thinking のみ)
  • AI Studio「利用額」の増分(円)

手順 3:実機のモデルを差し替えてビルド・書き込み

パッチ 0003 の対象行を gemini-3.8-live に変え、firmware/README.md の手順どおりにビルドします(環境変数の活性化・SDKCONFIG_DEFAULTSidf.py -B build-cores3 buildflash)。シリアルログは firmware/read_serial.py で非対話に取ります。

  • 記録するもの:ビルド成功(Successfully created esp32s3 image.)とバイナリサイズ(前回 3,579,120 B)
  • 初回接続で setupComplete が返るまでの時間(電源 ON から。前回は約 8 秒)

手順 4:遅延 — 発話終了から応答開始まで

ファームのログは「モデルの音声が届き始めた時刻」は刻みますが、「人が話し終えた時刻」は持っていません(SpeechStopped イベントは最初の modelTurn 到着時に合成している)。そこで部屋の音をそのまま録る方法で測ります。

  1. PC のマイク(または USB マイク)で Audacity を録音状態にし、スタックチャンに 5 回、同じ長さの質問をする(「今日の課題はなに?」など)
  2. 波形で、自分の声が途切れた点からスピーカーの音が立ち上がった点までを読む。5 回の中央値と最大値を記録する
  3. 余裕があれば、マイク信号とスピーカー端子をオシロスコープの 2 ch に入れ、エッジ間の時間を読む(前回の記事と同じ「絵になる」やり方)

3 モデルで並べる項目は次のとおりです。

  • 発話終了→応答開始の中央値と最大値(ms・5 回)
  • metrics(play)recv_to_queued_ms 平均(前回 3.1:64〜242 ms)
  • played_sps(公称 24,000。前回 3.1:23,055〜23,761)
  • 6 ターン連続での切断回数(前回 3.1:0)

手順 5:内部 RAM — 前回と同じ 3 点で diag を読む

ログの diag: [...] INT free=... largest=... min=... | DMA largest=... | PSRAM free=... を、前回の表と同じ状態で拾います。モデルはサーバー側の話なので内部 RAM は変わらないはずですが、「はず」を数字にするのがこの手順の目的です。基準になる前回(3.1・8月の記事)の値は次のとおりで、3.8 Live と Extended Thinking で同じ 3 状態を測り直します。

状態 前回(3.1・8月の記事)
Wi-Fi 停止(空き/最大連続) 64.2 KB/29.7 KB
会話中・httpd 抑止(空き/最小/最大連続) 33.2 KB/24.3 KB/19.5 KB
最終形・全機能(空き/最小/最大連続) 32.8〜36.7 KB/31.3 KB/21.5〜23.6 KB
ALLOC_FAIL の件数(6 ターン) 0

手順 6:1 会話あたりの費用

課金は前述のとおり「ターンごとに文脈を丸ごと」なので、同じ台本で 6 ターンを回し、AI Studio の「使用量」「利用額」(プロジェクト別)の増分を読みます。Proactive audio が常時 ON の 3.8 では、話しかけずに 5 分間つないだままにした場合の増分も別に測ります。

3 モデルで並べる項目は次のとおりです。

  • 6 ターンの入力トークン(音声)と出力トークン(音声)
  • 6 ターンの利用額(円・AI Studio の表示)
  • 話しかけずに 5 分つないだ利用額(円)
  • 文字起こし ON/OFF の差(円・3.1 と 3.8 Live)

公式単価から机上で置くと、聞くだけで約 $0.005/分、話すぶんは約 $0.018/分です。1 日に 10 分会話して 50 分聞いているロボットなら、日あたりの上限の目安は音声だけで $0.43 程度($0.005×50+$0.018×10)になりますが、文脈の再計算ぶんが上乗せされるので、この式は下限です。実測との差がどれくらいかが、実験室 #3 で知りたいことです。円換算は AI Studio の表示(円)をそのまま使います。


📌 筆者の見方

前回の記事で筆者がいちばん時間を使ったのは、「合計の空き」ではなく「連続した内部 RAM」を見ないと通信が落ちる、という話でした。今回の一次ドキュメントを読んで同じ手触りを感じたのが、Proactive audio が常時 ON になり、聞いている時間ぶん入力トークンが課金されるという一文です。発話ごとの単価は据え置きなのに、机の上で一日じゅう待機しているロボットにとっては、費用の芯が「話した回数」から「つないでいた時間」に移る。ピークの数字ではなく、ずっと流れている底の数字が効いてくる——RAM のときと同じ形をしている、と受け止めました。だから実測の計画には、あえて「話しかけずに 5 分つないだ利用額」の項目を入れています。

もうひとつ、ephemeral token の仕組みは、前回「PC が頭脳・実機が顔と声」と分けた設計の延長線上にきれいに乗る、と感じています。トークンを発行できるのは API キーを持つ側だけで、それは PC です。実機はセッション開始時に PC から「今日の課題」を受け取っており、そこにトークンを同梱するだけで、NVS からキーを消せる道が開けます。設計を先に分けておいたことが、API 側の進化に追随するときの手数を減らしてくれた——これは筆者の意見ですが、個人開発で長く使うものほど「役割を分けておく」ことが、モデルの世代交代への一番の備えになると思っています。

ただし、ここまではすべてドキュメントを読んだ段階の話です。3.8 Live に載せ替えて遅延がどう動くか、Extended Thinking の「ちょっと待ってね」が関西弁の師匠にどう馴染むか、費用が机上の式からどれだけ上振れするかは、実機で測るまで分かりません。実測は実験室 #3 で行い、数字が出た時点でこの記事にも追記します。

まとめ

  • 2026年9月15日、gemini-3.8-livegemini-3.8-live-extended-thinking が Live API で GA。 Live 系で初めて Stable の ID が付き、旧 3.1 プレビューは「更新推奨」に
  • Live API は WebSocket 双方向の audio-to-audio。 16 kHz PCM を送り続け、24 kHz PCM が細切れに返る。割り込みはサーバー側 VAD で処理され、履歴は音声トークンのまま保持される
  • ephemeral token はデバイスにキーを置かないための短命の鍵。 既定は 1 回・1 分以内に接続・30 分有効。接続先が BidiGenerateContentConstrained?access_token= に変わり、モデルなどの設定をトークン側に固定できる。Preview・Live API 専用
  • Extended Thinking は「つなぎの発話」と interaction_status turnComplete は「一言終わった」に意味が変わり、IDLE が来るまで待つ。ツールは非同期のみ
  • 料金は音声据え置き・テキスト値上げ。 Proactive audio 常時 ON で「聞いている時間」が課金対象に。文脈は毎ターン再計算、文字起こしは別料金
  • スタックチャンで変えるのは 3 点。 モデル ID の 1 行、?key= → PC 発行のトークン、Extended Thinking なら状態機械。遅延・内部 RAM・費用は実験室 #3 で測る

よくある質問(FAQ)

Q. Live API と、テキストの Gemini API(Interactions API)は何が違うのですか?

A. Live API は WebSocket で常時接続し、音声を連続ストリームとして送受信します。Interactions API(Google AI 実験室 #1 で使ったもの)は HTTP のリクエスト/レスポンスで、テキストや PDF を投げて結果を受け取ります。モデルも別で、Live API 用は gemini-3.8-live 系、テキスト用は gemini-3.8-flash などです。ephemeral token は Live API でしか使えません。

Q. gemini-3.1-flash-live-preview はいつ止まりますか?

A. 非推奨ページ(2026-09-17 更新)では「終了日未定・推奨の移行先は 3.8 Live」です。2025年12月には Live 系の 2 モデルが同日に終了した実績があるので、モデル名を設定値に追い出しておくのが安全です。

Q. 3.8 Live と 3.8 Live Extended Thinking、スタックチャンにはどちらが向いていますか?

A. 公式の使い分けでは、3.8 Live は「ミリ秒で返るツール(センサー値の読み取り・スマート機器の操作)」を持つ低遅延の会話向け、Extended Thinking は「数秒かかるツール」や複数ステップの計画向けです。スタックチャンのツールは PC への HTTP 1 往復(前回の記事でコンテキスト取得が 267〜323 ms)なので、まず 3.8 Live が本命です。Extended Thinking は状態機械の改修が要るので、遅延を測ってから判断します。

Q. ephemeral token を使えば、ESP32 に API キーを一切置かなくて済みますか?

A. トークンを発行するにはどこかに API キーが要ります。スタックチャンでは PC アプリがその役で、PC が居るあいだは NVS からキーを消せます。PC 不在時に単体で動かしたいなら、キーを残してフォールバックする設計になります。公式も「トークンはバックエンドの認証と同じ強さしか持たない」と注意しています。

Q. 料金はどう見積もればよいですか?

A. 音声入力 $3.00/1M トークン(約 $0.005/分)、音声出力 $12.00/1M(約 $0.018/分)が基本ですが、Live API はターンごとにセッションの文脈全体を再計算して課金し、3.8 では聞いている間も入力トークンが課金されます。文字起こしを有効にするとテキスト出力の単価が上乗せされます。公式は contextWindowCompression で文脈の上限を決めることを勧めています。実額は AI Studio の「利用額」で確認します。

Q. 対応言語は 97 なのですか、70 なのですか?

A. DeepMind のブログと開発者向け記事は 97(97+)、Live API の概要ページは 70 と書いており、2026年9月19日時点で Google の一次資料どうしで数字が違います。本記事は両方を併記しています。日本語は 3.1 世代で実機の会話が成立しているので、含まれる前提で進めます。

Q. 生成された音声には透かしが入りますか?

A. DeepMind のブログは「AI 製品が生成するすべての音声に SynthID の透かしを入れる」と明記しています。人の耳には聞こえない形で音声に埋め込まれ、AI 生成であることを検出できるようにするものです。

関連記事

参考

一次資料は front matter の references に列挙しています。取得日はすべて 2026年9月19日で、各ページの「Last updated」は次のとおりです。

X(旧 Twitter)の投稿は出典に使っていません。