Eleven v4を発表これまでで最も感情豊かなモデル、Eleven v4をご紹介します。

コンテンツへ移動

ボイスエージェントの遅延最適化:ステップバイステップガイド

公開日
最終更新日

聴くこの記事を聴く

音声エージェントの応答性は、ユーザーが話し終えてからエージェントが応答を開始するまでの総遅延によって決まります。この遅延が単一の遅いコンポーネントによって生じることはほとんどありません。数十〜数百ミリ秒ずつ寄与する複数の独立したステージで蓄積されるため、削減するには各ステージにどれだけ時間がかかっているかを把握する必要があります。

音声エージェントのレイテンシー最適化とは、時間がどこで費やされているかを見つけ、ステージごとに取り戻していく作業です。

この記事は、レイテンシーの概念的な概要の補足ガイドです。このページではレイテンシーとは何かを説明しますが、この記事ではアーキテクチャと測定を扱います。測定基準となるレイテンシーバジェットと、実行すべき具体的な施策を得られます。

概要

  • 初回オーディオ到達時間は、単一モデルの推論時間ではなく、パイプライン全体を表します。
  • LLMの初回トークン到達時間とエンドポインティングが、最も大きな要因です。
  • ステージを直列で実行せず重複させることで、バジェットの大半を取り戻せます。
  • ストリーミング、コーデックの選択、プレーヤーバッファの調整はいずれも、測定可能なミリ秒単位の短縮につながります。
  • 自社のデプロイ環境に対しリージョン別に測定し、P50とP95を報告してください。

音声エージェントのレイテンシーバジェットを定義する

レイテンシーバジェットとは、パイプラインの各ステージに配分する初回オーディオ到達時間の合計目標です。各ステージの許容時間の合計は、目標値を下回る必要があります。これを定義することが最初のステップですが、意味の異なる似た数値をエンジニアが混同しやすく、レイテンシー対策で最も失敗しやすいポイントでもあります。

1つ目はモデル推論レイテンシー、つまりモデルが出力を生成するのに費やす時間です。Flashモデルでは、ネットワークやアプリケーションのオーバーヘッドを除き、一般的な短い入力で約75msです。これは内部指標であり、モデル同士を比較する際に役立ちます。ユーザーが実際に体験する数値ではありません。

ユーザー視点では、初回オーディオ到達時間(TTFA)に注目します。これは、ユーザーが話し終えてからエージェントの応答の最初のサンプルを聞くまでの経過時間です。TTFAはパイプライン全体の合計であるため、常に単一モデルの推論レイテンシーより大きくなります。

カスケード型音声エージェントは、次の5ステージからなるチェーンです。

  • キャプチャ(マイク) -> STT -> LLM -> TTS -> 再生

オーディオはマイクからキャプチャされ、テキストに文字起こしされ、言語モデルに送信されます。モデルのテキストは音声に合成され、その音声がバッファリングされて再生されます。各ステージでレイテンシーが加わり、いくつかのステージでは最大のコストが想定どおりではありません。

ここでは、ユーザーから適度に近い場所にサーバーがある英語音声エージェントの例を示します。数値は保証ではなく、参考となる範囲です。

What it covers
Capture + endpointing
Mic capture, VAD/turn-detection delay before the turn is considered finished
STT finalization
Last partial to committed transcript after end-of-speech
Network (client to your server to our API)
Round-trips across the pipeline
LLM time-to-first-token
Prompt processing until the first usable token
TTS time-to-first-audio
First TTS request until first audio chunk leaves the model
Player buffering
Client-side buffer before playback begins
End-to-end TTFA
The total latency of the end-to-end pipeline
P50
Capture + endpointing
120 ms
STT finalization
60 ms
Network (client to your server to our API)
60 ms
LLM time-to-first-token
250 ms
TTS time-to-first-audio
110 ms
Player buffering
80 ms
End-to-end TTFA
~680 ms
P95
Capture + endpointing
280 ms
STT finalization
150 ms
Network (client to your server to our API)
160 ms
LLM time-to-first-token
600 ms
TTS time-to-first-audio
220 ms
Player buffering
150 ms
End-to-end TTFA
~1560 ms

通常、レイテンシーの要因として最も大きいのは、LLMの初回トークン到達時間と、チェーンの最初にあるエンドポインティング遅延です。 

この表はパイプラインを可視化するのに便利ですが、ステージが厳密に直列で実行されるように見えます。実際はそうではありません。重要な音声エージェントのレイテンシー最適化の多くはステージを重複させることで実現し、以下のバジェットの大半もこの重複で取り戻せます。

スピーチtoテキスト:文字起こしとエンドポインティングのレイテンシー最適化

文字起こしはパイプラインの第2ステージです。その本当のコストは文字起こし自体ではなく、ユーザーがいつ話し終えたかを判断することにあります。このセクションでは、音声エージェントのレイテンシーを最適化するため、この両面を解説します。

文字起こしはLLMに届く前に行われます。Scribe v2 Realtime(scribe_v2_realtime)は約150msで部分的な文字起こし結果を返し、オーディオチャンクをストリーミングで受信します。そのため、ユーザーがまだ話している間に文字起こしが作成されます。8kHz〜48kHzのPCMとmu-lawエンコードに対応しており、これは後述のコーデックのセクションで重要になります。150msの部分結果は低コストです。

より大きなレイテンシーコストはエンドポインティング、つまりシステムがユーザーのターンが実際に終わったと判断する瞬間にあります。

音声アクティビティ検出(VAD)は無音に基づいて音声を区切るため、ここで時間が蓄積されます。たとえば、ターンの終了を宣言するまで700msの無音を待つ場合、文字起こし自体に加えて、すべてのターンに700msが追加されます。この遅延は文字起こし精度のベンチマークでは見えませんが、実際の会話では明確に現れます。パイプライン全体で制御可能なレイテンシーとして最大になることも多く、制御できるため、着手しやすいポイントです。

エンドポインティングは、応答性と割り込みのトレードオフです。無音しきい値を短くするとエージェントは素早く応答しますが、自然な間でユーザーの発話を文の途中で切ってしまうリスクがあります。しきい値が長ければ安全ですが、反応は鈍くなります。実際に、スピーチtoテキストのレイテンシーを最適化する変更は、次の3つです。

  1. 無音しきい値を微調整する:ユーザーの自然な間を切り捨てない最小値まで無音しきい値を下げ、推測するのではなく本番環境で割り込み率を測定します。
  2. 物理的な制御イベントを組み込む:アプリケーションが別のシグナル(プッシュツートークのリリース、UIイベントなど)からターンの終了を認識できる場合は、VADタイマーを待たずに手動コミット制御を使用します。
  3. LLM処理と重複させる:部分結果を早い段階で下流に流します。安定した部分結果をLLMに渡し、最終文字起こしが異なる場合は修正します。これは、LLMのプロンプト処理の裏でエンドポインティング遅延を隠す投機的実行の一種です。

詳しくは、Scribe v2 Realtimeについてスピーチtoテキストの機能ページとリアルタイムスピーチtoテキストのプロダクトページで詳しく説明しています。

LLMがレイテンシーに与える影響

言語モデルは通常、TTFAに対する最大の単一要因です。そのため、音声エージェントのレイテンシー最適化では、重複処理の効果が最も大きい箇所でもあります。重要なのは、エージェントは話し始める前に回答全体を必要としないことです。

最も多くのレイテンシーバジェットを取り戻すパターンは、LLMからトークンをストリーミングし、到着次第、文または節の境界でチャンク化してTTSに渡すことです。文の境界までトークンをバッファリングし、次の文がまだ生成されている間にその文を合成します。

const SENTENCE_END = /(?<=[.!?])\s+/;

async function* speakLlmStream(tokens: AsyncIterable<string>) {
  let buffer = "";
  for await (const token of tokens) {
    buffer += token;
    const parts = buffer.split(SENTENCE_END);
    buffer = parts.pop() ?? ""; // keep the incomplete fragment
    for (const sentence of parts) {
      if (sentence.trim()) yield* synthesize(sentence.trim());
    }
  }
  if (buffer.trim()) yield* synthesize(buffer.trim());
}

async function* synthesize(text: string) {
  const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
    text,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  yield* stream;
}

長時間の会話には、TTS WebSocketを推奨します。接続を開いたままにすれば、文ごとに接続設定のコストを再び支払うことなく、テキストを段階的に受け取れます。同時実行数の上限にカウントされるのは、モデルが実際にオーディオを生成している時間だけなので、アイドル状態で開いたWebSocketはほぼコストがかかりません。

テキスト読み上げ:ストリーミングと音声の選択

テキスト読み上げは、レイテンシーを最も正確に制御できるステージです。主なレバーは2つあります。オーディオをどのようにストリーミング出力するか、そしてどの音声を選ぶかです。

Flash v2.5(eleven_flash_v2_5)は、エージェントで使用するモデルです。短い入力では約75msのモデル推論を実現し、32言語に対応、リクエストあたり最大40,000文字を受け付けます。

75msという数値は推論のみを示します。上記のバジェットにおけるTTSのTTFAは、推論にネットワークの往復時間とサーバースケジューリングが加わるため、より大きくなります。

ここで最大のレバーとなるのはストリーミングです。完全なオーディオをリクエストして待つ場合、ユーザーはクリップ全体の合成が終わるまで何も聞けません。ストリーミングなら、最初のチャンクが生成されるとすぐにユーザーに届き、残りはすでに聞いている間に到着します。ストリーミングによってモデル自体が高速になるわけではありません。モデルが生成中でもユーザーへの出力を開始するだけです。

ストリーミングのハウツーガイドではHTTPストリーミングを扱い、リアルタイムWebSocketガイドでは、LLMからトークンを渡す際に使用するWebSocketの方法を扱っています。

クライアントは一度だけ初期化し、以下のすべての呼び出しで再利用します。

import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const elevenlabs = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_API_KEY });

次に、ストリームを設定し、到着したデータをそのまま転送します。

const stream = await elevenlabs.textToSpeech.stream("JBFqnCBsd6RMkjVDRZzb", {
  text: "Your call is connected. How can I help today?",
  modelId: "eleven_flash_v2_5",
  outputFormat: "mp3_44100_128",
});

for await (const chunk of stream) {
  // forward each chunk to your audio sink as it arrives
}

もう1つのレバーは音声の選択で、これにもレイテンシーコストがあります。デフォルト音声、合成音声、Instant Voice Clone(IVC)は、Professional Voice Clone(PVC)より高速に合成されます。PVCには生成ごとのオーバーヘッドを増やす追加のモデル複雑性があるためです。厳しいレイテンシー要件を持つエージェントでは、FlashとIVCまたはデフォルト音声の組み合わせが最も低レイテンシーな選択肢です。

ストリーミングチャンクサイズの選び方

TTSにトークンが流れ込み、オーディオが返ってくる中で、次に決めるのは各部分のサイズと、再生開始前にプレーヤーがどれだけバッファリングするかです。

小さなチャンクはより早くプレーヤーに届くため、メッセージ数とチャンクごとのオーバーヘッドがわずかに増える代わりに、初回バイトのレイテンシーを下げられます。大きなチャンクは転送効率が高い一方、ユーザーは最初のチャンクをより長く待つことになります。インタラクティブなエージェントでは、発話の早い段階では小さなチャンクを優先してください。ユーザーが待っているのは最初のチャンクであり、後続チャンクはオーディオがすでに再生されている間に到着するため、サイズの影響は小さくなります。

プレーヤーは、残りのレイテンシーのかなりの部分を占めます。多くのオーディオプレーヤーは、最初のバイトで再生を始めません。ストリームが一時的に遅くなっても音が途切れないよう、少量をバッファリングします。デフォルトで500msのバッファは一般的で、知覚されるレイテンシーに直接加算されます。これを減らすと、音切れリスクがわずかに高まる代わりにTTFAを下げられます。適切な値は、サーバーとクライアント間のネットワークジッターによって決まります。

  • 安定した接続(サーバー側再生、同一拠点のクライアント)では、50〜150msのバッファで通常は安全であり、TTFAを目に見えて短縮できます。
  • ジッターの大きいモバイル接続やリージョン間接続では、より大きなバッファにより、レイテンシーより悪影響の大きい音声の途切れを防げます。

ここで選ぶ正確な構成は、実際のユースケースと優先事項によって決まります。

コーデックの選択

オーディオの送信先に応じて、リクエストするコーデックを決めるべきです。mp3_44100_128、mp3_22050_32、pcm_16000、pcm_24000、ulaw_8000などのフォーマットを返します。転送先のネイティブフォーマットに合わせることでトランスコード処理を省き、音声エージェントのレイテンシー最適化に役立ちます。

Twilioなどの電話サービスには、ulaw_8000を使用してください。電話ネットワークはエンドツーエンドで8kHzのmu-lawを使用するため、直接リクエストすればパイプライン内のトランスコード処理を回避でき、キャリアが期待する形式にも一致します。電話ネットワークがすぐにダウンサンプリングする高忠実度オーディオを合成しても利点はありません。レイテンシーが増えるだけで、聞こえる品質は変わりません。

WebRTCやブラウザーでの再生には、PCM(pcm_24000またはpcm_16000)かMP3形式を使用してください。PCMは非圧縮なので、クライアント側でデコードする必要がなく、チャンクごとのレイテンシーをわずかに削減できます。また、Web Audioパイプラインに直接渡す場合にも便利です。MP3は転送時によりコンパクトで、軽量なクライアント側デコードを必要とする代わりに、制約のある接続で役立ちます。

地理的な距離とネットワーク距離

上記のすべての最適化は、バイトの移動距離が短いことを前提としています。地理的な位置がレイテンシーバジェットの下限を決めるため、他の設定を調整する前に確認する価値があります。

北米、欧州、東南アジアのクラスターからリクエストを処理し、各リクエストを最寄りのクラスターへ自動的にルーティングします。パブリックインターネット上のネットワーク往復時間は、地理的な近さに応じて通常20〜200msであり、インフラの稼働場所を変えない限り削減できません。

北米クラスターから近いサンフランシスコでは即座に反応するように感じるエージェントでも、ターンごとにトラフィックが海を2回横断する南アジアのユーザーには、遅く感じられることがあります。

解決策は、アプリケーションサーバーをElevenLabsだけでなくユーザーにも近い場所に配置することです。ユーザーが欧州にいる場合は、ユーザーからサーバーまでの経路を短くするため、エージェントのバックエンドを欧州で稼働させます。サーバーからモデルまでの経路は、近くのクラスターからのルーティングで処理されます。

音声エージェントのレイテンシーを自分で測定する

上記のレイテンシーバジェット表の数値は、計画の参考となる範囲です。実際にリリースする際に基準とすべき数値は、自身のデプロイ環境に対して以下のようなスクリプトを実行して取得してください。

以下の計測では、TTSステージ単体のTTFA、つまりリクエストから最初のオーディオチャンクまでの時間を多数回の試行で測定し、パーセンタイルを報告します。開発マシンではなく、サーバーを稼働させているリージョンから実行してください。先ほどのelevenlabsクライアントを使用することを前提としています。

const VOICE_ID = "JBFqnCBsd6RMkjVDRZzb";
const TEXT = "Thanks for waiting. I have pulled up your account and I can help with that now.";
const TRIALS = 50;

async function measureTtfa(): Promise<number | null> {
  const start = performance.now();
  const stream = await elevenlabs.textToSpeech.stream(VOICE_ID, {
    text: TEXT,
    modelId: "eleven_flash_v2_5",
    outputFormat: "mp3_44100_128",
  });
  for await (const _chunk of stream) {
    return performance.now() - start; // first chunk -> stop the clock
  }
  return null;
}

function percentile(values: number[], p: number): number {
  const v = [...values].sort((a, b) => a - b);
  const k = (v.length - 1) * (p / 100);
  const lo = Math.floor(k);
  const hi = Math.min(lo + 1, v.length - 1);
  return v[lo] + (v[hi] - v[lo]) * (k - lo);
}

const samples: number[] = [];
for (let i = 0; i < TRIALS; i++) {
  const ttfa = await measureTtfa();
  if (ttfa !== null) samples.push(ttfa);
  await new Promise((r) => setTimeout(r, 300)); // space requests, don't measure your own queueing
}

console.log(`trials: ${samples.length}`);
console.log(`P50:    ${percentile(samples, 50).toFixed(0)} ms`);
console.log(`P95:    ${percentile(samples, 95).toFixed(0)} ms`);

覚えておくべき点をいくつか紹介します。

  • P50とP95を報告する:平均値ではなく、これらに注目してください。平均値はテールを隠しますが、エージェントが信頼できないと感じられる原因はテールです。P95は、20ターンに1回の体験を表します。 
  • 場所に基づくテスト:サービスを提供する各リージョンから同じスクリプトを実行し、結果は分けて保持してください。
  • 精度のために間隔を空ける:リクエストの間隔を空けます(上記のsetTimeout)。一度にすべて送信すると、サービスではなく自分のキューイングを測定することになります。同時実行数の上限を超えると、リクエストは優先度順にキューイングされ、通常は約50ms追加されます。さらに容量を超えるとHTTP 429を受け取ります。
  • レイテンシーチェーン全体を測定する:同じ計測パターンを他のステージにも拡張します。STTの確定処理、LLMの初回トークン、プレーヤーの起動を同じperformance.now()の範囲で計測すれば、自分の数値で完全なバジェット表を埋め、最初に対策すべきステージを確認できます。

これらのヒントに従えば、音声エージェントのレイテンシーを自分で測定できます。そこから、最初に取り組むべき優先事項が明確になります。

音声エージェントのレイテンシーを最も削減するものは?

すぐに取り組める施策を探しているなら、以下が最も効果の大きい変更です。

おおよその効果順に、エージェントのレイテンシーを減らすには次の方法を使えます。

  • 安定したSTT部分結果でLLM処理を開始し、エンドポインティング遅延を隠します。
  • 文の境界でLLMトークンをTTSにストリーミングし、1文目の合成と2文目の生成を重複させます。
  • TTSオーディオをプレーヤーにストリーミングし、プレーヤーバッファをネットワークジッターが許容する最小値まで減らします。
  • 最も低レイテンシーなTTSにはFlashとデフォルト音声またはIVCを使用し、コーデックを転送先に合わせます(電話にはulaw_8000、ブラウザー/WebRTCにはPCMまたはMP3)。
  • ネットワーク経路には実際に差があるため、サーバーをユーザーの近くに配置し、リージョンごとに測定します。

より深い具体的な手法については、レイテンシー最適化の開発者向けハウツーガイドを参照してください。すぐに実行できる完全な出発点として、APIクイックスタートとストリーミングのハウツーに完全な例があります。 

微調整済みのエージェントカスケードをより早く利用したいですか?ElevenAgentsには、重複処理の最適化がすでに実装されたこのパイプラインが備わっています。

ElevenAgentsで低レイテンシー音声エージェントを構築

音声エージェントのレイテンシー最適化では、各ステージを測定したうえで、遅いステージがすでに進行している処理の裏で動くように重複させる必要があります。上記のパターンを利用して、数回の反復でこのカスケードを手作業で構築・調整することも、レイテンシー最適化済みのパイプラインから始めることもできます。

ElevenAgentsは、ストリーミングSTTからトークン単位のLLMハンドオフ、Flash TTSまで、この完全なカスケードを実装しています。重複処理の手法もすでに組み込まれています。ゼロから始める代わりに、最も重視するパフォーマンスに合わせてしきい値を調整できます。

ElevenAgentsで今すぐエージェントを作成するか、詳細については営業担当にお問い合わせください。

音声エージェントのレイテンシー最適化に関するよくある質問 

執筆者

Tadas Petraは、ElevenLabsのプロダクトスイートを使った開発をサポートするデベロッパーリレーションズエンジニアです。また、デベロッパー向け教育プラットフォーム「Hungrimind」の創設者でもあります。以前はAgoraでリードデベロッパーアドボケイト、Zero To Masteryでインストラクターを務めていました。

関連記事

最高品質のAIオーディオで創造する