無線機から電話へ ― サーバーVADでハンズフリー通話を実装する

リアルタイム音声AIはこれまでPush-to-Talk(PTT)方式だった。ボタンを押している間だけ録音し、離すと応答が返る——業務無線のスタイルである。今回、サーバーVAD(音声区間検知)によるハンズフリー通話モードを実装し、UIで切り替えられるようにした。無線機と電話、両方持つことになった。

PTTとVAD、何が変わるのか

押して話す(PTT) ハンズフリー通話(VAD)
発話の区切り ボタン(手動commit) サーバーVADが自動検知
応答の開始 クライアントが要求 OpenAIが自動生成
割り込み ボタン押下でキャンセル かぶせて話すと自動バージイン
コスト 話した分だけ 無音の間も課金

実装の中核は、セッション設定の turn_detectionnull(手動)から {"type": "server_vad"} に切り替えるだけ——発話の始終検知・自動commit・自動応答・バージインを全部OpenAI側が引き受けてくれる。検証では、commitもresponse.createも一切送らず「音声+2秒の無音」をストリームしただけで、speech_startedspeech_stopped→自動文字起こし→自動応答が成立した。クライアント制御ゼロで会話が回る。

ボタンの第二の人生

ハンズフリーでは「押して話す」ボタンが失業する。そこでミュートトグルに転職させた。クリック(またはスペースキー)でマイクのON/OFF。実はこれ、切実な機能である。以前、裏で流していたYouTubeの音声がマイクに回り込み、文字起こしが単語サラダになる事件があった。常時マイクが開くVADモードでは、この手の混入が構造的に起きやすい。即座に黙らせるボタンは保険として必須だった。

細かい作り込みも要った。Web検索の実行中は自動ミュート(検索結果と新規発話の混線防止)。WebSocket回線では speech_started を受けたらローカルの再生キューを止める(バージインの実装)。WebRTC回線ならこれらの大半をプロトコルが勝手にやってくれる。

無線と電話の経済学

このプロジェクトが$5の無料クレジットで長く遊べた最大の理由は、PTT設計だった。押している間しか音声を送らない=無音に課金されない。タクシー無線が少ないチャンネルを大勢で共有できるのと同じ、トランキングの経済性である。

VADモードはその節約装置を自分から手放す。無音の間も音声ストリームが流れ続け、通話1時間で数ドル規模になる。だからUIのヒントに「無音の間も音声を送信・課金されます」と明示した。自然さはタダではない。とはいえ、ボタンから指を離して布団ちゃん(AIペルソナ)と垂れ流しで雑談できる体験は、明確に別物である。会話のテンポにAIの応答が溶け込んでくると、「アプリを操作している」感覚が消える。

これで構成は「回線2種(WebSocket中継/WebRTC直結)×モード2種(PTT/ハンズフリー)」の4通りになった。無線機として使うか、電話として使うか——用途が選べばいい。

コードは yoshiharu-ishii/realtime_voice で公開している。


リアルタイム音声AI 開発シリーズ

シリーズ目次(全7回のあらすじ)はこちら

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール