> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# リアルタイムで対話をストリーミング

Text to Dialogue WebSocket（`/v1/text-to-dialogue/stream-input`）では、1つの接続を開いたまま対話行を送信し、base64エンコードされたオーディオチャンクを受信できます。**Eleven v3** および **Eleven v4** の対話モデル専用です（`model_id`は`eleven_v3`または`eleven_v4`で始まる必要があります）。

> **Note**
>
> このガイドでは、**Text to Dialogue** WebSocketについて説明します。**Flash**、**Multilingual v2**、またはその他の
> v3以外のTTSモデルでは、[Realtime TTS WebSocket](/docs/ja/eleven-api/guides/how-to/websockets/realtime-tts)を使用してください。両方のプロトコルの
> 比較については、[Text to SpeechとText to Dialogueの WebSocket](/docs/ja/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets)をご覧ください。

## 要件

* APIキーを持つElevenLabsアカウント（[認証](/docs/ja/api-reference/authentication)）。
* APIキーには`Text to Speech`権限が必要です。
* マシンにPythonまたはNode.jsがインストールされていること。

## セットアップ

**`Python`**

```python Python
pip install python-dotenv websockets
```

**`TypeScript`**

```typescript TypeScript
npm install dotenv ws
npm install @types/dotenv @types/ws --save-dev
```

`.env`ファイルを作成します。

**`.env`**

```bash .env
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
```

[ボイスライブラリ](https://elevenlabs.io/voice-library)から**ボイスID**を選択します。以下の例では、接続ごとに登録できるボイスが**1つ**の`eleven_v4_turbo`を使用しています。

## WebSocketを開く

`model_id`や`output_format`などのクエリパラメーターを指定して、`wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input`に接続します。APIキーは`xi-api-key`ヘッダーで送信するか、最初のJSONメッセージで送信できます（ここでは、言語間で同じパターンにするため本文で送信しています）。

**`text-to-dialogue-websocket.py`**

```python text-to-dialogue-websocket.py
import asyncio
import base64
import json
import os

from dotenv import load_dotenv
import websockets

load_dotenv()
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")
VOICE_ID = "21m00Tcm4TlvDq8ikWAM"
MODEL_ID = "eleven_v4_turbo"

URI = (
    "wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input"
    f"?model_id={MODEL_ID}&output_format=mp3_44100_128"
)
```

**`text-to-dialogue-websocket.ts`**

```typescript text-to-dialogue-websocket.ts
import * as dotenv from "dotenv";
import * as fs from "node:fs";
import WebSocket from "ws";

dotenv.config();
const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;
const voiceId = "21m00Tcm4TlvDq8ikWAM";
const modelId = "eleven_v4_turbo";

const uri = `wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input?model_id=${modelId}&output_format=mp3_44100_128`;
const websocket = new WebSocket(uri);

const outputDir = "./output";
try {
  fs.accessSync(outputDir, fs.constants.R_OK | fs.constants.W_OK);
} catch {
  fs.mkdirSync(outputDir);
}
const writeStream = fs.createWriteStream(`${outputDir}/dialogue-ws.mp3`, { flags: "a" });
```

## ボイスを登録してテキストをストリーミングする

まず、`voices`（必須）と、`xi-api-key`ヘッダーを設定していない場合は`xi_api_key`を含む**最初のメッセージ**を送信します。続いて、`inputs`を含むフレームを1つ以上送信します。各項目には`text`、`voice_id`、任意の`new_turn`を指定します。

サーバーは十分なコンテキスト（約**40文字**かつ**8語**）がたまるまでテキストをバッファリングし、その後`audio`チャンクを送信します。レスポンスフィールドは**スネークケース**です（例：`is_final`）。

**`text-to-dialogue-websocket.py`**

```python text-to-dialogue-websocket.py
async def stream_dialogue():
    async with websockets.connect(URI) as websocket:
        await websocket.send(
            json.dumps(
                {
                    "voices": [VOICE_ID],
                    "xi_api_key": ELEVENLABS_API_KEY,
                }
            )
        )

        line = (
            "This is a longer line of dialogue used to exceed the minimum buffer so the model "
            "starts generating streamed audio for the registered voice. "
        )
        await websocket.send(
            json.dumps(
                {
                    "inputs": [
                        {"text": line, "voice_id": VOICE_ID, "new_turn": False},
                    ],
                }
            )
        )

        await websocket.send(json.dumps({"close_socket": True}))

        os.makedirs("output", exist_ok=True)
        out_path = "output/dialogue-ws.mp3"
        with open(out_path, "wb") as audio_file:
            while True:
                raw = await websocket.recv()
                msg = json.loads(raw)
                if msg.get("error"):
                    raise RuntimeError(msg)
                if msg.get("audio"):
                    audio_file.write(base64.b64decode(msg["audio"]))
                if msg.get("is_final"):
                    break
        print(f"Wrote {out_path}")


asyncio.run(stream_dialogue())
```

**`text-to-dialogue-websocket.ts`**

```typescript text-to-dialogue-websocket.ts
websocket.on("open", () => {
  websocket.send(
    JSON.stringify({
      voices: [voiceId],
      xi_api_key: ELEVENLABS_API_KEY,
    })
  );

  const line =
    "This is a longer line of dialogue used to exceed the minimum buffer so the model starts generating streamed audio for the registered voice. ";

  websocket.send(
    JSON.stringify({
      inputs: [{ text: line, voice_id: voiceId, new_turn: false }],
    })
  );

  websocket.send(JSON.stringify({ close_socket: true }));
});

websocket.on("message", (data) => {
  const msg = JSON.parse(data.toString());
  if (msg.error) {
    console.error(msg);
    return;
  }
  if (msg.audio) {
    writeToLocal(msg.audio, writeStream);
  }
});

function writeToLocal(base64str: string, stream: fs.WriteStream) {
  stream.write(Buffer.from(base64str, "base64"));
}

websocket.on("close", () => {
  writeStream.end();
});
```

`close_socket`は、バッファリングされたテキストをすべて送信し、残りのオーディオを送信した後、接続を閉じる前に`is_final: true`を含む最終フレームを送信します。行と行の間も**接続を開いたままにする**には、セッション終了時まで`close_socket`を省略してください。閉じずに短いバッファのオーディオ生成を強制するには、`flush`を使用します。

## スクリプトを実行する

**`Python`**

```python Python
python text-to-dialogue-websocket.py
```

**`TypeScript`**

```typescript TypeScript
npx tsx text-to-dialogue-websocket.ts
```

`output/`配下にMP3ファイルが作成されます（ファイル名は上記の例と同じです）。

## 動作に関する注意事項

### バッファリング

TTS WebSocketの`chunk_length_schedule`とは異なり、対話ストリーミングでは最初の部分オーディオを生成する前に**固定のサーバーしきい値**（文字数と単語数）が適用されます。短い行を送信して遅延が発生する場合は、`inputs`フレームごとに少し多めのテキストをまとめて送信するか、`flush: true`を送信してソケットを閉じずに生成を強制してください。

### ターンとボイス

話者のターンが終わったら、韻律を適切にリセットするため`new_turn: true`を設定します。`inputs`エントリ間で`voice_id`を変更した場合も、新しいターンが開始されます。`eleven_v4_turbo`では、`voices`に**ちょうど1つ**のボイスを登録します。`eleven_v4`では最大**10**個のボイスを登録できます。

### 非アクティブ状態

サーバーが**20秒間クライアントメッセージを受信しない**場合、接続は終了します。オーディオを合成せずにタイマーをリセットするには、`{"keep_alive": true}`を送信します。

### 同時実行

各オープン接続は、開いている間、1つの対話セッションを維持します。これはプランの標準同時実行数とは別の専用プールから割り当てられます。接続経由で生成されたオーディオは、標準同時実行数にはカウントされません。詳しくは、[Text to Dialogueの同時実行数](/docs/ja/overview/models#text-to-dialogue-concurrency)をご覧ください。

### アラインメント

利用可能な場合にチャンクで`alignment`オブジェクト（スネークケースのタイミング配列）を受信するには、クエリ文字列に`sync_alignment=true`を追加します。[APIリファレンス](/docs/ja/api-reference/text-to-dialogue/ttd-websocket)をご覧ください。

## 次のステップ

#### [TTSとTTDのWebSocket](/docs/ja/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets)

適切なWebSocketを選び、メッセージ形式を比較します。

#### [Text to Dialogue WebSocket（API）](/docs/ja/api-reference/text-to-dialogue/ttd-websocket)

クエリパラメーター、メッセージスキーマ、例。

#### [対話をストリーミングする（HTTP）](/docs/ja/api-reference/text-to-dialogue/stream)

WebSocketを使わず、リクエストテキスト全体を利用できる場合。

#### [Realtime TTS WebSocket](/docs/ja/eleven-api/guides/how-to/websockets/realtime-tts)

WebSocket経由の、単一ボイスによるv3以外のストリーミング。