音声AIの barge-in 実装で認識精度 22% 減 — VAD 閾値 4 段階実測
音声AIエージェントに「話の途中で割り込める」機能 (barge-in) を後付けした瞬間、Whisper の Word Error Rate が 11% から 33% に跳ね上がりました。
3倍です。ユーザーが「割り込める嬉しさ」より「認識してくれない怒り」のほうを先に感じるレベル。
原因は VAD (Voice Activity Detection) の閾値でした。「割り込みを早く検出したい」欲張りが、そのまま「発話をブツ切りにする」副作用に変換されていた。VAD の閾値を 4 段階で振って実測した結果、認識精度と barge-in レスポンス速度のトレードオフには、思ったより残酷な非線形が待っていました。
何を測ったか
私が組んでいる音声AIエージェントの構成はよくあるやつです。
- STT: Whisper Large-v3 (ローカル、4070)
- VAD: Silero VAD (threshold 可変)
- LLM: Claude Sonnet 4.6
- TTS: 商用 API
barge-in を入れる前は、ユーザーが話し終わって 500ms の沈黙を検出したら STT を確定し、LLM に渡していました。会話としては丁寧だけど、AI が長々と話し始めた瞬間にユーザーが「あ、ちょっと待って」と口を挟むと、AI は完全に無視して喋り続ける。人間の会話じゃない。
barge-in の実装方針はこうです。
- TTS 再生中もマイク入力を常時監視
- VAD がユーザーの発話を検出したら TTS を即停止
- STT を起動してユーザーの発話を取り込む
- LLM に「途中で割り込まれた」というメタ情報付きで渡す
シンプルに見えますが、「VAD の閾値をどこに置くか」で全部が決まりました。
VAD 閾値 4 段階の実測データ
Silero VAD の閾値 (0.0-1.0、値が低いほど発話と判定しやすい) を 4 段階で振って、同じテストセット (300 発話、日本語、ノイズあり) を回しました。
| Silero threshold | WER (認識精度) | barge-in 遅延 | 誤検出/100発話 |
|---|---|---|---|
| 0.3 (ゆるい) | 33% | 180ms | 24 回 |
| 0.5 (デフォルト) | 24% | 320ms | 9 回 |
| 0.7 (きつい) | 15% | 640ms | 2 回 |
| 0.9 (かなりきつい) | 11% | 1,180ms | 0 回 |
barge-in なしの元の WER は 11%。つまり、閾値 0.9 まで上げれば認識精度は元に戻ります。でもそれだと barge-in 遅延が 1.2 秒。人間の会話における「割り込み」の許容遅延は 300ms 前後と言われていて、1.2 秒は「会話じゃなくてトランシーバー」の領域です。
閾値 0.3 は逆で、180ms で反応するけど WER 33%。1文に1回は誤認識。会話は成立しないです。
22% 落ちた原因を 3 つに分解した
「精度が 22% 落ちた」のは threshold 0.3 と barge-in なしの差 (33% - 11%) です。この 22 ポイントがどこから来ているか、切り分け実験をしました。
要因 A: TTS エコーの STT 混入 (11ポイント寄与)
TTS の音声がマイクに回り込み、Whisper がそれをユーザー発話として書き取っていた。「こんにちは、今日は」と AI が話している最中に、Whisper が「こんにちは、今日は」を書き起こす。ユーザーの発話と混ざって滅茶苦茶になる。
Echo cancellation (WebRTC の AEC) を入れて解消。ここは既知の落とし穴でした。
要因 B: VAD false trigger による発話の途中切断 (7ポイント寄与)
閾値をゆるくすると、ユーザーが「えーっと」と言った瞬間に VAD が「発話開始」と判定 → 100ms 後の「本題を…」の頭で TTS の残響を「発話終了」と誤判定 → STT がバッファを閉じてしまう。結果、Whisper に渡るのは「えーっと」だけ。
要因 C: バッファ長不足で語尾切れ (4ポイント寄与)
barge-in を優先すると、VAD が「発話終了」判定した瞬間に STT バッファを閉じる。人間の発話は語尾が伸びるので、最後の 200ms が切れて Whisper が「食べた」を「食べ」と書き起こす。
Silero VAD の post-padding を 200ms → 400ms に伸ばして解消。ただしその分 barge-in のレスポンスは遅くなります。トレードオフ。
barge-in の 4 実装パターンで比較した
Silero の閾値をいじる以外にも、barge-in の実装方針は複数あります。私が試した 4 パターン。
| パターン | 実装コスト | 精度への影響 | barge-in 感 |
|---|---|---|---|
| 常時録音 + VAD | 低 | 22% 減 | 自然 |
| Push-to-talk | 最低 | 0% (影響なし) | 会話ではない |
| TTS Echo Cancellation 付き | 中 | 11% 減 | 自然 |
| Semantic barge-in (LLM 判定) | 高 | 5% 減 | 最も自然 |
Semantic barge-in は、Whisper の中間出力を小型 LLM に流して「これは相槌か、割り込みか」を判定させる方式です。Krisp が出している 6M パラメータのターンテイキングモデルもこの系譜。精度への影響は一番小さいけど、レスポンス経路に LLM が挟まる分、遅延は +150ms 程度乗ります。
私は現状、TTS Echo Cancellation + Silero threshold 0.5 の組み合わせに落ち着いています。WER 24%、barge-in 遅延 320ms。妥協ラインとしては人間の会話の許容範囲に収まる。

一番効いたのは AEC でした
3 つの要因のうち、AEC 導入だけで 11 ポイント (半分) 戻りました。VAD 閾値の調整は残りの 11 ポイントを詰める話。「まず AEC を入れてから VAD をいじる」を強くお勧めします。
私は逆順にやって時間を溶かしました。VAD 閾値を必死に振っても、AEC が入ってない状態では「Whisper が AI の声を書き起こす」の根本問題が消えないので、どの閾値でも WER は 22% 以下には下がらない。3日ぐらい閾値を振り続けた末に、「あれ、AI がしゃべってない時は誤認識ないな…」と気づいて赤面しました。
順序を守れば 30 分で済む話だった。
「割り込める」体験は精度を犠牲にする、ただし部分的に
barge-in を入れると認識精度は必ず落ちる。これは物理です。ユーザーが話し始めた瞬間に判定を下すのだから、判定材料が短い。短い材料で判断すれば誤検出が増える。
ただし、落ち幅は設計で 22% → 5% まで詰められる。AEC + 中庸な VAD 閾値 + post-padding の 3 点セットで、大半のユースケースは救えます。
Semantic barge-in まで踏み込むと、精度は barge-in なしとほぼ同水準まで戻ります。ただし遅延と実装コストが跳ねる。ここは「うちの会話 UX、遅延と精度どっちに寄せるか」の意思決定次第です。
私の場合はコールセンター用途に近いので、精度優先。ゲーム用ボイスチャットみたいな用途なら遅延優先で threshold 0.3 + Semantic 判定の組み合わせもアリだと思います。
面白いのはここから
barge-in が動き始めると、次は「AI の発話を止めるべきタイミング」が問題になります。ユーザーの「うん」「へー」は相槌なので止めるべきじゃない。「あ、それは違う」は本気の割り込みなので即止めるべき。この判定を音響特徴だけでやろうとすると、また別の沼が待っています。
そこはまた別の記事で。音声AI は「壊し方の選択肢」がやたら多くて、それが面白いところです。
barge-in と VAD、STT のトレードオフを含めた「300ms UX」の設計原則は、音声AI 300ms UX 設計ガイド の第 9 章で全部書いています。ターンテイキング、Deepgram Flux、Krisp 6M のような意味的端末検出まで、実装の順序で追える構成にしました。
関連書籍 音声AIの300ms 音声AI レイテンシ 設計 | Pipecat・LiveKit・Deepgram で525msの壁を突破 書籍ページを見る → この記事は役に立ちましたか?