200ms未満のリアルタイムスピーチtoテキスト:アーキテクチャガイド
- 公開日
- 最終更新日
リアルタイムスピーチtoテキスト(STT)は、人が話すと同時に音声をテキストへ変換し、数百ミリ秒以内にその内容を返します。しかし、STTの遅延を抑えるにはモデルだけでなく、アーキテクチャ設計も重要です。エンジニアは転送、チャンク分割、エンドポイント検出、キャプチャ経路など、各工程で発生する遅延を考慮する必要があります。どこか一つでも非効率だと、200ms以内という目標を達成できません。
このガイドでは、トランスポート層から構築できる実践的なリアルタイムスピーチtoテキストパイプラインのシステムを紹介します。基準となるのはScribe v2 リアルタイムです。これはモデル遅延約150msで部分的な文字起こしを生成し、90以上の言語に対応、PCM(8kHz〜48kHz)やμ-law音声を受け付け、ボイスアクティビティ検出(VAD)や手動コミット制御によるセグメント確定も可能です。
音声がサーバーに届くまでの流れ、仮説がどのように確定テキストへ進化するか、ストリーム内機能のコスト、音声の正しいキャプチャと転送方法について解説します。
要点まとめ
- リアルタイムスピーチtoテキストシステムの構築には、パイプライン全体で遅延を抑えるためのアーキテクチャ微調整が必要です。
- ほとんどのパイプラインではWebSocketが最適ですが、WebRTCはより多くの利点がある一方で複雑さも増します。
- ボイスアクティビティ検出(VAD)はハンズフリーなセグメント分割を行い、手動コミットでターン終了時にアプリ側から制御できます。
- 部分的なテキスト(パーシャル)は仮のもので、確定テキスト(ファイナル)は確定済みです。表示方法を分けましょう。
- 約100ms程度の小さなPCMチャンクで送ると、最初のパーシャルまでの遅延を最小化できます。
リアルタイムスピーチtoテキストにおけるWebSocketとWebRTCの比較
文字起こしを始める前に、音声はソースから認識器まで届く必要があります。どのチャネルを選ぶかで、その後の遅延の下限が決まります。音声を文字起こし層まで届ける方法は2つあります。
WebSocketは、TCP上で動作する長寿命・順序保証・信頼性の高い双方向チャネルです。接続を開き、バイナリ音声フレームを送信し、テキストイベントを受信します。クライアント・サーバー双方でシンプルに扱え、HTTPSを許可する企業プロキシやファイアウォールも通過でき、すべてのブラウザやサーバーランタイムでサポートされています。
WebSocketの制約はTCP上で動作する点です。パケットが失われるとTCPが再送し、ギャップが埋まるまで後続データを保留します。良好なネットワーク環境では問題ありませんが、パケットロス時にはヘッドオブラインブロッキングが発生し、一時的に音声が詰まってから一気に届くことがあります。
WebRTCはリアルタイムメディア向けに設計されています。UDP(SRTP経由)でメディアを送るため、パケットが失われてもストリームが止まらず、パイプラインは継続します。ジッターバッファでパケット到着のばらつきを吸収し、ICE/STUN/TURNでNAT越えも交渉、独自の音声キャプチャ・エンコード機能も備えています。
クライアントが直接接続できない場合は通常TURNサーバーが必要で、サーバー側はバイトストリームではなくメディアストリームを終端する必要があります。
主な違いをまとめると以下の通りです:
ほとんどの用途ではWebSocketが最適です。クライアントの接続性が良好でキャプチャ経路を制御できる場合(サーバー間パイプライン、デスクトップアプリ、ブロードバンド環境のブラウザアプリ、音声が既にサーバーに届いているコンタクトセンターのバックエンドなど)で使いましょう。
WebRTCは、信頼性の低いモバイルネットワーク上の一般ユーザー端末から直接キャプチャする場合や、双方向音声(例:話すボイスエージェント)で既にWebRTCスタックを使っている場合、または低損失なリアルタイム性が実装のシンプルさより重要な場合に選びます。
このガイドの残りは、認識器との接続にWebSocketトランスポートを使います。これにより構成要素が見えやすく、多くのチームにとって最適な出発点です。ただし内容はWebSocket専用ではないので、後からWebRTCメディア経路を追加し、サーバーでPCMにデコードして同じチャンクをパイプラインに流すこともできます。
パーシャルとファイナル:中間結果の仕組み
リアルタイム認識器は、文が完成するまで待たずに話し始めます。音声が届くたびに仮説を流し続け、情報が増えるごとに精度を高め、最終的に確定します。この2つの状態の違いを理解することが、自然な文字起こし体験と違和感のある体験を分けます。
パーシャル(中間仮説)は、現時点で受信した音声に基づくモデルの最善の推測です。パーシャルは設計上不安定で、音声が増えるとモデルが前の単語を修正します。例えば「I want to」が、後の文脈で「I want two tickets」に変わることも。パーシャルは高速(約150msの遅延)で届き、上書きされる前提です。
ファイナル(確定仮説)は、もう変更されない確定済みのセグメントです。セグメントが確定すると認識器は次に進み、以降の仮説は後続の音声を扱います。ファイナルは保存したり、LLMに送ったり、文字起こしとして記録するものです。
パーシャルとファイナルの違いを曖昧にすると、次の3点で問題が起こります:
- ユーザー体験: パーシャルを表示すると、話すと同時に文字が現れ、マイクが動作している・システムが聞いているとユーザーに伝わります。
- エンドポイント検出: パーシャルは音声活動の連続的なシグナルになります。VADと組み合わせることで、話者が本当に話し終えたタイミングを判断できます。
- 下流のタイミング: ボイスエージェントパイプライン 手順は、まずオーディオ入力、次にスピーチtoテキスト、そしてLLM、
パーシャルとファイナルは表示方法を分けましょう。シンプルで効果的なのは、最新のパーシャルを「現在の行」として保持し、ファイナルが届いたら追記専用の文字起こしにコミットする方法です:
見た目としては、確定済みテキストは通常表示、現在の行は薄い色やイタリックで表示し、まだ変わる可能性があることをユーザーに伝えます。
エンドポイント検出とボイスアクティビティ検出(VAD)
「何を話したか」だけでなく、「いつ話し終えたか」も認識器には重要です。この判断がセグメントの確定タイミングや、エージェントが応答を始めるタイミングを決めます。
エンドポイント検出は、発話が終了したと判断することです。早すぎる確定はユーザーの発話を途中で切り、遅すぎる確定はユーザーが話し終えた後にエージェントが沈黙してしまいます。
Scribe v2 Realtimeでは、2つの補完的な仕組みが使えます:
- ボイスアクティビティ検出は、無音を基準に音声を分割します: 認識器が音声から無音への切り替わりを検出し、その境界で自動的にセグメントを確定します。VADは会話型インターフェースのデフォルトに最適で、自然な話し方のリズムに自動で適応します。
- 手動コミット制御:手動コミット制御では、無音とは関係なくアプリ側でセグメント確定のタイミングを決められます。コミット信号を送ると、認識器が現在のセグメントを閉じてファイナルを出します。これは、ターン終了が既に分かっている場合(プッシュトゥトークボタンの離し、送信アクション、外部のターン制御ポリシーなど)に最適です。
この2つは組み合わせて使えます。一般的なボイスエージェントはVADでハンズフリー操作を実現し、手動コミットを上書き手段として提供します。考え込むユーザーは途中で切られず、ボタンを押すユーザーは即座に区切れます。
無音しきい値は、正解が一つではない本質的なトレードオフです:
- 短い発話終了タイムアウト(例:200〜400msの無音で確定)は、システムの応答性を高めますが、節の間で自然に間を取るユーザーを途中で切ってしまい、1つの発話が複数セグメントに分かれたり、エージェントが早く反応しすぎることがあります。
- 長いタイムアウト(例:800〜1200ms)は、自然な間を許容し発話を一つに保てますが、システムの反応が遅く感じられます。
ここに絶対的な値はありません。インタラクションに合わせてしきい値を調整しましょう:
- ディクテーションやメモ取りは途中で考えるため長めの間を許容できます。長めのタイムアウト+VAD推奨です。
- コマンド&コントロールや取引系エージェントは短いタイムアウト+手動コミットが有効です。ターンが短く明快なためです。
- 多言語話者や非ネイティブ話者は間が長くなりがちなので、確定までの無音時間を長めに設定しましょう。
これらのポイントを押さえることで、効果的なエンドポイント検出システムを構築し、リアルタイムスピーチtoテキストに近づけます。
ストリーム内機能:言語検出と話者分離
ストリーミング認識は単に単語を出すだけでなく、さまざまな追加情報も扱えます。ただし、追加するシグナルが多いほど遅延や安定性に影響します。基本ルールは「ライブ体験に必要なものだけオンにし、残りはバッチ処理に回す」です。
自動言語認識を使うと、Scribe v2 Realtimeが90以上の対応言語から話されている言語を自動判別できます。事前指定が不要になる一方、モデルが自信を持って判定するまで短い音声が必要なので、ストリーム最初のパーシャルはやや不安定になる場合があります。言語が分かっている場合は指定した方が、初期パーシャルが安定しやすくなります。
話者分離(スピーカーダイアリゼーション)は、誰が何を話したかを識別します。バッチ文字起こしでは全体を見られるので比較的簡単ですが、ストリーミングでは現時点までの音声だけで話者ラベルを付ける必要があり、初期ラベルは後で修正されることもあります。ストリーミングの話者ラベルは、パーシャルテキストと同じく「確定まで仮」として扱いましょう。
単語単位のタイミングやエンティティ情報も同様です。トークンごとのメタデータを多く要求するほど、モデルも通信も負荷が増します。ほとんどのリアルタイムUIではテキストとセグメント境界だけで十分で、細かいメタデータはScribe v2のバッチ処理で後から付与できます。
ストリーミング用音声フォーマット:PCMとμ-law
転送や認識ロジックが注目されがちですが、実際のバグの多くはその下層、音声のエンコードやチャンク分割に起因します。フォーマットとチャンクサイズを正しく設定することが、スピーチtoテキスト遅延を最も手軽に改善する方法です。
PCM(リニア、16ビット符号付きリトルエンディアン)は、キャプチャを制御できる場合の推奨フォーマットです。サンプルレートが高いほど音響情報が多くなります。16kHzは音声認識の標準下限で通常十分、8kHzは電話品質で高域が失われます。ソースに合わせたレートを使いましょう。8kHz音声を48kHzにアップサンプリングしても情報は増えません。
μ-law 8kHzは電話音声の標準フォーマットです。Twilioなどのプロバイダーから通話を受け取る場合、音声は8kHz μ-lawで届くので、そのまま転送しましょう。ソースフォーマットを維持することで、リサンプリングによる劣化や不要な変換を避けられます。
チャンクサイズは体感遅延を最も直接的に左右します。音声をチャンク単位で送り、認識器はチャンク到着ごとにパーシャルを生成します。小さいチャンクは更新頻度が高く最初のパーシャルまでの遅延が短縮、大きいチャンクはメッセージ数が減り推論時の文脈がやや増えます。実用的な範囲は20〜250ms/チャンクです。具体例として、16kHzモノラル16ビットPCMなら1秒=32,000バイト、100msチャンク=約3,200バイトです。
ブラウザでのマイク入力キャプチャ
ブラウザでは、Web Audio APIとAudioWorkletが最適です。ワークレットはオーディオレンダリングスレッド上で動作し、小さなフレーム単位で音声を受け取り、従来のScriptProcessorNodeのようなメインスレッドの遅延の影響を受けません。役割は、ブラウザのfloatサンプルを16ビットPCMに変換し、メインスレッドに渡してWebSocket経由で送信することです。
ワークレットプロセッサのコアはfloat→PCM変換です:
パイプラインのコード例
パイプラインは3つの要素で構成されます:マイクをキャプチャしてPCMをサーバーにストリーミングするブラウザクライアント、音声をScribe v2 Realtimeに中継し文字起こしを返すNodeサーバー、ファイルや電話ブリッジからPCMをストリーミングするスクリプト可能なクライアントです。
サーバーが認識器を直接ブラウザに公開しない理由は1つだけです:ElevenLabsのAPIキーは秘密情報であり、クライアント側コードに絶対に含めてはいけません。APIキーはサーバーで保持します。どうしてもブラウザから直接認識器に接続したい場合は、サーバー側で短命・使い捨てトークンを発行し、APIキーの代わりにクライアントへ渡してください。
ブラウザクライアント
クライアントはサーバーへWebSocket接続を開き、上記ワークレットでマイクをキャプチャし、生成されたPCMフレームを逐次転送します。サーバー側で正規化された{ type, text }イベントを受け取り、パーシャル/ファイナル状態を管理します:
サーバー中継
サーバーはクライアントごとに認識器接続を開き、APIキーをサーバー側で保持し、バイナリPCMをそのまま転送、認識器イベントをクライアントが扱いやすい{ type, text }形式に正規化します:
エンドポイント固有の処理は、下記2つのアダプタ関数に集約されています。フィールド名はSpeech to Textリファレンスのものに置き換えてください。それ以外のパイプライン部分は変更不要です:
スクリプト可能なバックエンドクライアント
バックエンドパイプラインや下記ベンチマーク用途では、同じ認識器接続がブラウザなしでも動作します。任意のソースからPCMを読み込み、リアルタイムのチャンク間隔で送信し、イベントを受信します。APIキーやURLはサーバー同様、環境変数から取得します。
スピーチtoテキスト遅延と単語誤り率のベンチマーク
遅延や単語誤り率(WER)は、話者・言語・音響条件・音声長・各プロバイダーの最寄りリージョンへのネットワーク経路・サービスの負荷状況などで変動します。
1都市のノートPCで測った結果は、他の環境や本番運用全体には当てはまりません。本番に近いインフラで、本番に近い音声を使い、単一値ではなく範囲や分布でレポートしましょう。
本当に重要なのは、自分の音声・本番に近いインフラで測定した遅延と精度だけです。ここではスピーチtoテキスト遅延のベンチマーク方法を紹介します。
スピーチtoテキスト遅延で測定すべき指標
リアルタイムスピーチtoテキスト遅延のベンチマークで測るべき主な指標は以下の通りです:
- 最初のパーシャルまでの時間: 最初の音声チャンク送信から、最初の非空パーシャル受信まで。
- パーシャル→ファイナルのラグ: 発話の最後の音声チャンク送信から、ファイナル仮説受信まで。
- 単語誤り率(WER):ファイナル文字起こしと人手参照とのWERを、全システムで同じ方法で計算します。
- 安定性の変動: ファイナル化前に何回パーシャルが書き換わったか。ライブUIがどれだけ変化するかの指標です。
コントロール項目
信頼性の低いデータを避けるため、実験にはいくつかのコントロールを導入し、一貫性を保ちましょう。
スピーチtoテキスト遅延ベンチマークで使うべき主なコントロールは以下の通りです:
- 同一音声: すべてのシステムに同じファイル・同じサンプルレート・同じエンコードで入力します。
- 同一ペース: すべてのシステムで同じリアルタイムチャンク間隔(例:100msチャンク)でストリーミングします。
- 繰り返しと分布のレポート: 各ファイルを1日に何度も実行し、中央値や上位値(p50/p95)を報告します。
- 同一参照・スコアリング: WER計算前にテキストの正規化(大文字小文字・句読点・数字)を全システム同じ方法で行います。
- リージョンとネットワークの開示: ハーネスの実行場所と各プロバイダーへの経路を明記します。
これらすべてを揃えることで、より精度の高い指標が得られます。
ハーネスの骨組み
測定のコアは、プロバイダーアダプタを受け取り、最初のパーシャルまでの時間・ファイナル化ラグ・パーシャル変動数を記録します:
単語誤り率は、正規化テキスト同士の標準的なトークン単位レーベンシュタイン距離です。計算前に参照・仮説とも小文字化・句読点除去を同じ方法で行いましょう。そうしないとモデルではなく正規化処理の差を測ることになります。この測定は各ファイルをプロバイダーごとに約10回ループし、最初のパーシャルまでの中央値・WERの中央値(p50/p95)を報告します。単一サンプルはネットワーク変動に左右されやすいためです。
実行には2つの準備が必要です。まず、システムごとに1つのStreamFnアダプタを書きます。上記スクリプトクライアントは既に1つで、他も同じ(audioPath, onEvent, result)契約で、final audio chunk送信時にresult.lastChunkSentAtをセットします。次に、音声ファイルと参照を読み込み、全体にmeasureを呼びます。本番環境に近いマシン・音声で実行すれば、再現性のある比較ができます。
リアルタイムスピーチtoテキストを実現するためのまとめ
この記事では多くのアーキテクチャ改善策を紹介しました。これによりシステムを段階的に改善し、リアルタイムスピーチtoテキストに近づけます。
本番用リアルタイムSTTシステムは、以下のような意思決定に集約されます:
- トランスポート:シンプルさと制御されたネットワークならWebSocket、損失耐性や一般端末からのキャプチャが必要ならWebRTCを選びます。
- パーシャルとファイナル:パーシャルは仮、ファイナルは確定として扱い、表示も分けてユーザーがライブテキストを信頼できるようにしましょう。
- エンドポイント検出:ハンズフリー分割にはVAD、上書きには手動コミットを使い、無音しきい値は一定値ではなくインタラクションに合わせて調整します。
- ストリーム内機能:ライブ体験に必要なものだけオンにし、残りはScribe v2のバッチ処理に回しましょう。
- 音声フォーマット:小さなPCMフレームでキャプチャし、約100msチャンクで送信、電話音声はソースフォーマットを維持します。
- ベンチマーク:自分の音声と目標指標で、精度と遅延のバランスを実測で調整しましょう。
- APIセキュリティ:APIキーはサーバーで管理し、クライアント直結時は使い捨てトークンを発行しましょう。
もしボイスエージェントで遅延を最適化する方法も知りたい場合は、別ガイドもご用意しています。
Scribe v2 Realtimeでリアルタイムスピーチtoテキストシステムを構築
Scribe v2 Realtimeは、モデル遅延約150msでパーシャルを生成します。ユーザーが実際に体感する遅延は、その周辺アーキテクチャ次第です。この記事で紹介した戦略を使えば、遅延を抑え顧客体験を向上させるパイプラインアーキテクチャを構築できます。
さらに詳しく知りたい方は、スピーチtoテキストの機能概要や、モデルリファレンスで全機能・対応言語リストをご覧いただき、リアルタイムプロダクトページ(リアルタイムスピーチtoテキストAPIやリアルタイムスピーチtoテキスト.
)もご確認ください。ElevenLabsの無料アカウントを作成して、今日から最初の文字起こしをストリーミングしましょう。


.webp&w=3840&q=80)
.webp&w=3840&q=80)
