0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【9月28日公開】Eleven v4の「100ms」は会話の待ち時間ではない。音声AIの3つの罠と、今日測るべき応答時間

0
Posted at

ゲームのNPCや音声案内を「100msの音声AI」で作ろうとしているなら、その時計がどこから動き始めるのかを確認してほしい。

90以上の言語。ブラインド比較で約75%の選好。推論時間は中央値で約100ms。

  • 90以上の言語は、Eleven v4とv4 Turboの対応範囲。
  • **約75%**は、通常版v4の自然さ・表現力を尋ねた比較で、同点を半勝として扱った選好の数字。
  • 約100msは、Turbo版の推論時間の中央値。

それがElevenLabsが2026年9月28日に発表した音声モデル、Eleven v4ファミリーだ。吹き替え、ゲームのキャラクター、読み上げと対話の両方を狙っている。

だが、同じ発表にはもう一つの数字がある。Turboの「最初の発声まで」は約150ms。そして脚注には、こうある。

network latency measured and removed for all systems.

ネットワークを除いた150msを、ユーザーが話し終えてから返事が聞こえるまでの150msに変換してはいけない。

結論から言うと

1. 測るべきなのは、発話終了から返答の音が出るまでの時間だ。
TTSへ送信してから音声データが届くまでの計測も残し、どの区間で待ったかを分けること。

2. 公式の100msと150msは、同じ指標ではない。
前者は推論、後者はネットワーク遅延を取り除いた発声開始までの測定である。

3. Turboへ差し替えても、入力待ちと接続枠の問題は消えない。
v4系の対話用WebSocketは、従来のTTS用WebSocketとバッファ処理も同時接続の数え方も異なる。

舞台袖にたまる会話のリボンと、舞台上で即座に音を出す赤い口型スピーカー
発声処理の速さと、その前にたまる待ち時間を舞台に見立てた生成イラスト。実機や測定結果を描いたものではない。

情報確認日は2026年10月6日。発表は9月28日、参照した発表ページの最終更新は10月5日。性能・対応言語・仕様の数値はElevenLabsの一次資料による。本記事で音声生成APIや日本語の品質・遅延を実測したわけではない。後述の1000msの例は架空の計算例で、接続コードは未実行である。

数字で見るEleven v4。まず主語をそろえる

リリース案内、モデル一覧、WebSocketの比較仕様を突き合わせた。以下は筆者が2026年10月6日の公開情報から編成した表だ。

項目 公開値・仕様 読み落とすと困る条件
公開日 2026年9月28日 v4とv4 Turboの2系統
Turboの推論時間 中央値 約100ms 会話全体の時間ではない
Turboの発声開始 中央値 約150ms 発表の比較ではネットワーク遅延を除去
通常版v4の選好 約75% 音の自然さ・表現力の比較。内容の正答率ではない
対応言語 90以上 日本語を含む。全言語で同じ遅延とは書かれていない
Turboの登録音声 1接続につき1音声 複数キャラクターをそのまま同居させない
通常版v4の登録音声 最大10音声 対話用WebSocketの上限
対話ストリーミングの入力待ち 目安は約40文字かつ8語 flushで短いバッファの生成を促せる
無通信タイムアウト 20秒 クライアントメッセージ基準。keep_aliveで延長
対話用WebSocketの枠 開いている接続ごとに1セッション 無音でも接続中は占有

ここまでは「速くて表情のある声」の話。面白いのはその先だ。

声が速く出せることと、返事が速いことの間には、まだ仕事が残っている。

100msの時計は、返答待ちの全体を測っていない

たとえば、プレイヤーがNPCに「次はどこへ行けばいい?」と話しかける。

システムは発話が終わったと判断し、言葉を認識し、ゲームの状態から返答を作り、話せる単位のテキストをそろえ、音声を生成し、端末で再生する。先読みや並列化は可能だが、TTSだけを交換して全工程を交換したことにはならない。

公式の遅延の解説も、推論時間とユーザー側で最初の音が鳴るまでの時間を分け、ネットワーク、サーバー処理、再生バッファ、LLMを含むアプリの処理を挙げている。

時計 始点と終点 分かること
公表の推論時間 モデル内部の音声生成処理 モデルの処理速度
発表のtime to first speech リクエストから発声まで、ネットワーク分を除外 その比較条件下の音声生成経路
手元の初回音声受信時間 テキスト送信直前から、空でない音声チャンクを受信するまで 入力待ち・通信・生成を含む一部分
ユーザーの返答待ち時間 ユーザーの発話終了から、端末で返答が聞こえるまで 対話体験としての待ち時間

発表の英語表記も、100msには “median inference latency”、150msには “median time to first speech” と使い分けている。

ここで150 - 100 = 50msを計算し、「通信以外のオーバーヘッドは50ms」と確定したくなる。本当にそうか?

測定対象と集計方法をそろえた同一試行の内訳が必要だ。そもそも、別々に集計した中央値の差は、各試行の差の中央値とは限らない。公表値から見えるのは指標が違うというところまでである。

合成を2倍速にしても、返事は5%しか縮まらない例

次は仕組みを理解するための架空の1リクエストだ。各工程が重ならずに進み、単位をmsでそろえる。製品のベンチマークではない。

# 架空値による計算例。計算のみ実行確認済み。
parts = {
    "発話終了判定と認識の残り": 300,
    "最初の返答テキストを用意": 250,
    "合成開始までの入力待ち": 120,
    "音声合成": 100,
    "通信など": 80,
    "再生開始まで": 150,
}
before = sum(parts.values())
after = before - parts["音声合成"] + 50
print(before, after, (before - after) / before * 100)
# 1000 950 5.0

合成は2倍速。ユーザーの待ち時間は1000msから950ms。短縮は5%だ。

逆に、この例で入力待ち120msを減らせるなら、合成を50ms削るより大きい。どちらに投資すべきかは、モデルの宣伝値ではなく、自分の処理の内訳で決まる。

実システムでは音声認識・テキスト生成・合成が重なるので、上の足し算を各工程の中央値に適用せず、同じリクエストの時刻を記録すること。初回音声受信のログを取るなら、考え方はこうなる。

# 計測位置を示す擬似コード。未実行。
t0 = ユーザーの音声が終わった時刻
t1 = 最初の返答テキストをTTSへ送る直前
t2 = 空でない音声チャンクを初めて受信した時刻
t3 = 端末の音声出力で返答が実際に始まった時刻

返答待ち = t3 - t0
TTS受信待ち = t2 - t1

同じ時計で測るか、機器間の時計を同期する必要がある。play()を呼んだ時刻は、スピーカーから音が出た時刻と同じとは限らない。さらに、送る文・声・地域・出力形式をそろえ、成功件数とエラー件数を残したうえで、中央値とp95を別々に見る。p95は95%の試行がその時間以内に収まる境界だ。

あなたのアプリで一番長いのは、返答文を作る時間、入力待ち、再生バッファのどれだと思う? あなたの予想もコメントで教えてほしい。

公開資料だけでは、日本語の特定の声・回線・端末での返答待ち時間は確定できない。

今すぐ試すべき2つの使い方

完成済みの台本と、生成途中の返答を分けて試す。この違いだけでも、音声作品と対話アプリで欲しい性質が変わる。

以下は公式のリクエスト形式を基にした未実行例だ。自分のAPIキーと利用可能な音声IDを使うこと。実行すると契約に応じたクレジットを消費する。

1. 台本があるなら、通常版v4で短い掛け合いを作る

ゲームのイベント会話や学習教材なら、まず声の演技を確認したい。Create dialogueの例を基に、モデルを明示してファイルへ保存する。

# 未実行。ELEVENLABS_API_KEYを設定済みの端末で使う。
# voice_idは自分のアカウントで使える音声へ置き換えること。
curl --fail-with-body --silent --show-error \
  'https://api.elevenlabs.io/v1/text-to-dialogue?output_format=mp3_44100_128' \
  -H "xi-api-key: ${ELEVENLABS_API_KEY:?APIキーを設定すること}" \
  -H 'Content-Type: application/json' \
  --data '{
    "model_id": "eleven_v4",
    "inputs": [
      {"text": "[giggling] Knock knock", "voice_id": "JBFqnCBsd6RMkjVDRZzb"},
      {"text": "[curious] Who is there?", "voice_id": "Aw4FAjKCGjjNkVhN1Xmq"}
    ]
  }' \
  --output dialogue.mp3

公式例と同じ短い英語の掛け合いを出発点にし、自作の日本語台本へ置き換えて、固有名詞と演技指示を聞き比べる。これは音声制作の試聴であり、対話の遅延測定ではない。

2. 対話なら、Turboで「最初の音声受信」を記録する

リアルタイム対話の公式ガイドの接続・登録・送信手順に、受信時刻の記録を加える。下をprobe.pyとして保存すること。

なお、TTDのAPIリファレンスにはv3のみとする記述も残るため、v4 Turboの対応経路は、それを明記するモデル一覧と実装ガイドで照合した。

# 未実行。公式ガイドの依存パッケージ。
python -m pip install python-dotenv websockets
# 公式ガイドを基にした計測用の改変例。API接続は未実行。
import asyncio
import base64
import json
import os
import time
from pathlib import Path

import websockets
from dotenv import load_dotenv

load_dotenv()
VOICE = os.environ["ELEVENLABS_VOICE_ID"]
URI = (
    "wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input"
    "?model_id=eleven_v4_turbo&output_format=mp3_44100_128"
)

async def main():
    async with websockets.connect(URI) as ws:
        await ws.send(json.dumps({
            "voices": [VOICE],
            "xi_api_key": os.environ["ELEVENLABS_API_KEY"],
        }))
        started = time.perf_counter()
        await ws.send(json.dumps({"inputs": [{
            "text": "Hello!",
            "voice_id": VOICE,
            "new_turn": False,
        }]}))
        # 短い文を確定させる。これは単発プローブで、接続を終了する。
        await ws.send(json.dumps({"close_socket": True}))

        first_ms = None
        chunks = []
        while True:
            raw = await asyncio.wait_for(ws.recv(), timeout=30)
            received_at = time.perf_counter()
            msg = json.loads(raw)
            if msg.get("error"):
                raise RuntimeError(msg["error"])
            if msg.get("audio"):
                chunk = base64.b64decode(msg["audio"])
                if chunk:
                    if first_ms is None:
                        first_ms = (received_at - started) * 1000
                    chunks.append(chunk)
            if msg.get("is_final"):
                break

        if first_ms is None:
            raise RuntimeError("音声を受信できなかった")
        Path("probe.mp3").write_bytes(b"".join(chunks))
        print(f"送信開始から初回音声受信まで: {first_ms:.1f} ms")

asyncio.run(main())
# 未実行。APIキーと、自分の音声IDを環境変数または.envに設定して使う。
python probe.py

この計測は接続確立後から始まる。通信を含み、再生を含まない。ファイルを最後に保存するので、表示値を「耳に届くまでの時間」と名付けないこと。 初期化後の最初の送信でもあり、長時間接続を使い回したときの定常値とも分ける。

知らないと損する3つの罠

罠1:短く送れば送るほど速い、とは限らない

ゲームの返答を一語ずつ流せば最速になる。本当にそうか?

対話用WebSocketのバッファ仕様では、一定の文字数と語数に達するまで入力を蓄える。目安は約40文字かつ8語だ。短い返答を送ったあとに何もしなければ、モデルの計算以前に待ちが生じうる。

しかも、従来のTTS用のchunk_length_scheduleを調整する方式ではない。日本語で「8語」をどう区切るかも、この説明からは断定できない。

対策:意味が確定した短い返答は、{"flush": true}を送って生成を促すこと。

接続を終えるなら、上の単発例のようにclose_socketで残りを流す。継続対話で毎回切断する必要はない。一方、途中で確定させる単位を細かくしすぎると、抑揚に使える先の文脈を減らす。短文・長文の両方を聞いて決めること。

罠2:モデル名だけ変えれば、同じWebSocketが動く

公式のプロトコル比較には、接続先の違いが明示されている。

Flash系: /v1/text-to-speech/{voice_id}/stream-input
v4系:    /v1/text-to-dialogue/stream-input

前者はURLで声を固定してtextを送る。後者は最初にvoicesを登録し、その後はinputs配列で送る。返答の終端フィールドも含め、同じ通信契約ではない。

対策:モデル名・URL・初期メッセージ・本文の形を一緒に切り替えること。

さらにHTTP版のAPI仕様では、model_idの既定値は参照時点でeleven_v3だ。「最新モデルを呼んだつもり」を避けるため、v4は明示する。

罠3:しゃべっていない接続は、同時接続枠を使わない

従来のTTS用WebSocketの感覚で、ゲームに登場するNPC全員の接続を開いておくと、別の制約に当たる。

Text to Dialogueの同時実行仕様では、接続が開いている間、別プールの対話セッションを1つ保持する。生成していない時間も対象だ。枠を使い切った状態での新規接続はtoo_many_concurrent_requestsで拒否される。

対策:実際に会話する単位で接続を管理し、不要な接続を閉じること。

20秒の無通信切断を防ぐkeep_aliveは、枠を解放する命令ではない。生かす接続と閉じる接続を分ける必要がある。

比較3選。台本、対話、既存の低遅延経路で選ぶ

他社の「最速」数値を混ぜたランキングは作れない。始点も終点も違うと、数字の大小だけが独り歩きする。

ここでは、10月6日に読んだモデルの説明、遅延最適化ガイド、プロトコル仕様から、同じサービス内の3経路を比較する。

選択肢 最初に試す用途 公開されている速さの指標 実装で分かれる点
Eleven v4 台本付きの掛け合い、教材、吹き替え この比較ではTurboの100msを流用しない HTTPのText to Dialogue。対話WSでは最大10音声
Eleven v4 Turbo NPCの即時返答、音声案内 推論中央値約100ms/発声開始約150msは別指標 Text to Dialogue WS、登録は1音声、接続ごとのセッション
Eleven Flash v2.5 既存の単一話者ストリーミングの比較基準 約75msはモデル推論のみ TTS用WS。チャンク制御と同時実行の数え方が異なる

表から読み取れること:

  • 75ms対100msだけで、会話の勝者は決まらない。 同じ台詞を同じ端末で鳴らしたときの待ち時間が必要だ。
  • 複数人の台本と、1人の即時応答は別の選択になる。 Turboの「Dialogue」という名前から、1接続で何人でも話せると読まないこと。
  • リアルタイム生成が不要な台詞は、先に制作しておける。 固定のイベント会話なら、再生時の合成待ち自体を外せるという設計上の選択肢がある。

接続数が選択を左右するため、公開されている対話WSの枠も抜き出す。これは料金表ではなく、ワークスペースのセッション上限だ。

プラン 対話WebSocketセッション
Free 14
Starter 21
Creator 35
Pro 70
Scale / Business 105
Enterprise 個別の増枠

アプリ側には、モデルと通信方式を対にした設定を持たせると取り違えを防ぎやすい。以下はアプリ独自の設定例であり、ElevenLabsへそのまま送るJSONではない。

{
  "interactive_voice": {
    "model_id": "eleven_v4_turbo",
    "transport": "ttd_websocket",
    "output_format": "mp3_44100_128"
  },
  "scripted_dialogue": {
    "model_id": "eleven_v4",
    "transport": "ttd_http",
    "output_format": "mp3_44100_128"
  }
}

教訓:速いモデルを、遅い会話に閉じ込めない

✗ "100msなら返事も100ms" → 発話終了判定、返答生成、通信、再生は別に残る
✗ "150msとの差50msが固定費" → 指標と試行がそろわず、中央値の引き算でも決まらない
✗ "一語ずつ送れば最速" → 対話用WebSocketは入力をバッファする
✗ "model_idだけ差し替える" → 接続先とメッセージ形式も違う
✗ "無音の接続は無料の枠" → 対話セッションは接続している間ずっと占有する

Eleven v4の面白さは、音の表情と低遅延を同時に狙い、台本制作とリアルタイム対話を別のモデル・経路で提供している点にある。ゲームの台詞や音声教材を作るなら、数字を眺めるだけでなく、自分の一文で声を確かめる価値がある。

そのとき、速さの主語を間違えないこと。ユーザーが待つのはモデル内部の推論ではなく、次の声だ。今日、いつもの返答を1つ選び、「送信から受信」と「発話終了から聞こえるまで」の2つの時計を置いてほしい。

参考資料

Introducing Eleven v4, our most emotive model
https://elevenlabs.io/blog/eleven-v4

ElevenLabs Changelog: September 28, 2026
https://elevenlabs.io/docs/changelog/2026/9/28

Eleven v4: Capabilities and model variants
https://elevenlabs.io/docs/overview/capabilities/text-to-speech/eleven-v4

Models and Text to Dialogue concurrency
https://elevenlabs.io/docs/overview/models

Understanding latency
https://elevenlabs.io/docs/eleven-api/concepts/latency

Latency optimization
https://elevenlabs.io/docs/eleven-api/guides/how-to/best-practices/latency-optimization

Create dialogue
https://elevenlabs.io/docs/api-reference/text-to-dialogue/convert

Stream dialogue in real-time
https://elevenlabs.io/docs/eleven-api/guides/how-to/websockets/realtime-tdd

Text to Speech vs Text to Dialogue WebSockets
https://elevenlabs.io/docs/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets

Text to Dialogue WebSocket API reference
https://elevenlabs.io/docs/api-reference/text-to-dialogue/ttd-websocket


音声AIの選定で使えそうなら、いいねと保存を。ゲーム・音声案内・教材を作っているチームにも、100msの脚注ごとシェアしてほしい。

コメントで教えてほしい。

  • 声の演技と返答速度、あなたの用途ではどちらを優先する?
  • 今測っているのは、音声データの到着? それとも実際に音が鳴る瞬間?
  • 固定の台詞は事前生成する? すべてリアルタイムで作る?
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?