Twilio ConversationRelay が Deepgram Flux 対応したので相槌割り込みと言語判定を試してみた
はじめに
多言語対応の電話窓口や音声 AI ボットの現場でよく聞かれる悩みが 2 つあります。1 つは、ボットが発信者の相槌 (「はい」「うんうん」) に反応して話を遮ってしまい、対話が不自然になることです。もう 1 つは、発信者の話す言語を、通話前に「日本語の方は 1 を、English speakers press 2」のように選ばせなければならないことです。
Twilio ConversationRelay は 2026 年 5 月 6 日、Deepgram の新しい音声認識モデル Flux への対応を発表しました。音声認識とターン検出 (発話の区切り判定) を 1 つのモデルに統合したもので、Twilio は応答遅延を 200 から 600 ミリ秒短縮し、誤った割り込みを約 30 パーセント減らせるとしています。
本記事では、この 2 つの悩みが実際の通話でどこまで解消されるのか、WebSocket サーバーに届くデータを見ながら確かめます。結果として、日英の言語判定は通常の発話であれば安定して動作しました。一方、相槌による割り込みの抑制や応答速度の改善については、今回の検証では効果を確認できませんでした。
ConversationRelay とは
ConversationRelay は、Twilio の音声通話と音声 AI (音声認識・LLM・音声合成) を WebSocket でつなぐしくみです。通話中の音声がテキストに変換されて自分のサーバーに届き、返したテキストがそのまま音声合成されて電話口に届きます。
検証環境
- WebSocket サーバー: プレーンな Node.js +
ws+twilioパッケージ - Node.js ランタイム: v24.18.0
- デプロイ先: Vercel Functions
- 電話: 米国 Twilio 電話番号
対象読者
- Twilio ConversationRelay で音声 AI ボットを構築している方
- Deepgram Flux の効果を、導入前に自分の目で確かめたい方
- 相槌による誤割り込みや、多言語対応の悩みを抱えている方
参考
- ConversationRelay now supports Deepgram Flux (Twilio Changelog)
- Deepgram launches Flux Multilingual (Deepgram プレスリリース)
- ConversationRelay (TwiML リファレンス)
- WebSocket メッセージリファレンス
背景と課題
ConversationRelay における音声認識まわりの対応は段階的に進んできました。2025 年 9 月に Deepgram の Nova-3 モデルが使えるようになり、2025 年 10 月には自動言語検出設定 (transcriptionLanguage="multi") が追加されました。そして 2026 年 5 月、音声認識とターン検出を統合した Flux への対応が加わりました。Deepgram 側の発表によると、Flux Multilingual は英語・日本語を含む 10 言語に対応し、ターン検出は 400 ミリ秒未満、会話途中の言語切り替え (コードスイッチング) にもネイティブ対応するとされています。
WebSocket 上でやり取りされるメッセージのうち、Twilio 側から送信される prompt メッセージには、認識結果のテキスト (voicePrompt) と、判定された言語 (lang) が含まれます。この lang を見て後続の処理を分岐できるかどうかが言語選択の悩みを解決できるかの鍵になります。
相槌による誤割り込みは、音声 AI ボットの体感品質を大きく左右します。ボットが「本日はお電話ありがとうございます」と話している途中に、発信者が「はい」と相槌を打っただけでボットの発話が止まってしまうと、対話のテンポが崩れ、機械的な印象が強まります。
言語選択の強制も、体験を損なう要因です。多言語対応をうたいながら、電話をかけた直後に「日本語の方は 1 を」と選ばせるのは、発信者にとって余計な一手間です。自動で言語を判定できれば、この一手間を省けます。
検証方法
TwiML 側の設定は、speechModel の指定だけを変えた 3 通りを用意しました。3 つ目の ignoreBackchannel は、speechModel="flux" と組み合わせたときだけ有効になる属性です。相槌のような短い発話を、ボットの発話を止める要因として扱わないようにする設定です。
| variant | speechModel |
ignoreBackchannel |
|---|---|---|
| baseline | 未指定 (既定モデル) | - |
| flux | flux |
- |
| flux_ignore_backchannel | flux |
true |
variant は Voice URL のクエリパラメータで渡します。TwiML は通話開始時に確定し、通話の途中で構成を切り替えることはできないため、3 構成を比較するときは、その都度電話をかけ直しました。
サーバー側では、届いた setup・prompt・interrupt・text などのメッセージをそのまま console.log に記録し、prompt を受信するたびに認識内容を確認する短い応答を返しています。
function replyFor(lang, voicePrompt) {
if ((lang || '').startsWith('ja')) {
return `はい、かしこまりました。今「${voicePrompt}」とおっしゃった内容を、こちらで確認しております。少々そのままでお待ちくださいね。`;
}
if ((lang || '').startsWith('en')) {
return `Sure, I heard you say "${voicePrompt}". I'm just noting that down, so please stay on the line for a moment.`;
}
return `了解しました。「${voicePrompt}」について確認しています。少々お待ちください。`;
}
検証シナリオは大きく 2 種類です。
- 言語判定を見るためのシナリオ
日本語のみ・英語のみ・日英往復・短い発話・混在発話の 5 パターンを、flux 構成で試しました。 - 割り込みと応答速度を見るためのシナリオ
ボットの発話中に相槌を打つケースと、通常の質問をするケースを、3 構成それぞれ 2 回ずつ試しました。
順序による慣れの影響を避けるため、2 回目は構成の順序を入れ替えています。
割り込みについては、体感だけでなく、次の 4 点をログから個別に確認しました。
- ボットの発話を中断する
interruptメッセージが届いたか - 相槌自体が
promptとして認識されたか - 認識されたあとに不要な応答が返ったか
- 発信者の体感
応答速度については、prompt の受信から応答テキストの送出までのサーバー内処理時間はほぼ 0 ミリ秒であり、Twilio 側の音声認識や音声合成にかかる時間とは無関係なため、計測対象にしていません。発信者の体感を一次データとして扱っています。
検証結果: 言語判定の挙動
日本語のみ・英語のみ・日英往復のシナリオは、いずれも想定どおり動作しました。
| シナリオ | 発話 | 結果 |
|---|---|---|
| 日本語のみ | これはテストです | lang=ja |
| 英語のみ | This is a test | lang=en |
| 日→英→日の往復 (1 通話内で 3 ターン) | 今日はいい天気ですね → The weather is nice today → そうですね | 各ターンで lang が ja → en → ja と追随 |
一方、短い発話は 3 回とも認識されませんでした。「もしもし」に続けて「Hello」と発話する通話を 3 回試しました。prompt メッセージが一度も届かないまま、約 27 秒後に接続が切断されました。Twilio 側のエラー通知も記録されておらず、サーバーのログだけでは、認識できなかったのか、通話の状態や発話タイミングに起因するのかは切り分けられませんでした。
次に、日英が混在する発話「ありがとうございます、Thank you」を 2 回試しました。1 回は届かず、1 回は voicePrompt="ありがとうございます。 Thank you."、lang=ja として、2 つに分割されずに 1 件の日本語の発話として 認識されました。
検証結果: 割り込みと応答速度
ボットの発話中に相槌を打つシナリオでは、3 構成のあいだで挙動が大きく異なりました。
| 構成 | 観測した挙動 |
|---|---|
| baseline | 挨拶を interrupt で中断。ただし短い日本語の相槌は、2 回の通話で届いた 5 件すべてが voicePrompt="Hi."、lang=en として認識された |
| flux | 1 回目の通話は setup 以降まったく反応なし。2 回目の通話は 2 回の発話とも lang=ja で正しく認識された |
| flux_ignore_backchannel | 挨拶への interrupt は 2 回とも発生。1 回目は prompt が届かず、2 回目は最初の発話が lang=ja でまとめて認識された |
baseline は相槌そのものは認識するものの、内容を英語の Hi. と取り違える傾向が一貫していました。flux は認識できたときは日本語として正しく判定しましたが、まったく反応しない通話もありました。flux_ignore_backchannel は、interrupt は安定して発生する一方、その発話が応答につながるかどうかは通話によって分かれました。
通常の質問「今日の営業時間を教えてください」を発話するシナリオでは、より単純な傾向が出ました。
| 構成 | 結果 |
|---|---|
| baseline (2 回) | 2 回とも lang=ja で正常に認識。体感の応答時間は 2 から 3 秒 |
| flux (2 回) | 2 回とも無反応 |
| flux_ignore_backchannel (2 回) | 2 回とも無反応 |
flux 系の構成 (flux・flux_ignore_backchannel) は、この質問文を合計 4 回試して、1 回も prompt を受信できませんでした。短い相槌に限らず、通常の長さの発話でも認識されない場合があるということです。
認識できた baseline の 2 回については、発信者の体感でおよそ 2 から 3 秒で応答が返り、「もう少し早いと人間らしい」という感想でした。flux 系の構成は認識自体が成立しなかったため、応答速度を比較する材料は得られませんでした。
実装: lang による分岐処理
prompt メッセージの lang を見れば、後続の応答文言や、有人オペレーターへのルーティング言語を分岐できます。今回の検証サーバーでの分岐は次のとおりです。
if (message.lang === 'ja') {
// 日本語向けの応答やルーティング
} else if (message.lang === 'en') {
// 英語向けの応答やルーティング
}
lang は en-US のような形式ではなく、ja や en という BCP-47 のプライマリ言語タグのみが入ります。判定の確信度を示すフィールドは、受信できた prompt のいずれにも含まれていませんでした。
考察
flux 系の構成で認識が成立しなかった原因は、サーバー側のログだけでは特定できません。Deepgram Flux のターン確定の閾値によるものか、電話網を経由した音声品質の影響かを切り分けるには、通話音声を録音した追加の検証が必要だと考えています。また、今回の検証は記事執筆者 1 名による少数回の結果であるため、何度も試行することで結果が変わることも予想されます。
なお、baseline の相槌の誤認識 (はい。 と Hi.) は、Flux の導入有無にかかわらず起こりうる問題でしょう。自動言語検出の精度は発話の長さによって左右されやすく、どの構成を選ぶにしても付きまとう問題だと考えられます。
まとめ
Twilio ConversationRelay の Deepgram Flux 対応を、実際の通話で検証しました。通常の長さの発話における日英の言語判定は安定して動作しました。一方で、相槌による誤割り込みの抑制や応答速度の改善は、今回の環境では確認できませんでした。それどころか、短い発話や通常の質問文が認識されないまま通話が終わる場面が複数回発生し、flux 系の構成の認識そのものが不安定だという結果になりました。
Deepgram Flux の導入を検討している場合、自分たちが実際に使う発話パターンと通話環境で試すことをおすすめします。本記事の検証方法と結果が、導入の判断材料になれば幸いです。




