> 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.

# Diffusez des dialogues en temps réel

Le WebSocket Text to Dialogue (`/v1/text-to-dialogue/stream-input`) maintient une connexion unique ouverte pendant que vous envoyez des lignes de dialogue et recevez des segments audio encodés en base64. Il est destiné uniquement aux modèles de dialogue **Eleven v3** et **Eleven v4** (`model_id` doit commencer par `eleven_v3` ou `eleven_v4`).

> **Note**
>
> Ce guide couvre le WebSocket **Text to Dialogue**. Pour les modèles TTS **Flash**, **Multilingual v2** ou autres
> modèles non v3, utilisez le [WebSocket TTS en temps réel ](/docs/fr/eleven-api/guides/how-to/websockets/realtime-tts). Pour un résumé comparatif des
> deux protocoles, consultez [WebSockets Text to Speech et Text to Dialogue ](/docs/fr/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets).

## Prérequis

* Un compte ElevenLabs avec une clé API ([authentification](/docs/fr/api-reference/authentication)).
* La clé API doit disposer des autorisations `Text to Speech`.
* Python ou Node.js installé sur votre machine.

## Configuration

**`Python`**

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

**`TypeScript`**

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

Créez un fichier `.env` :

**`.env`**

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

Choisissez un **ID de voix** dans la [Voice Library](https://elevenlabs.io/voice-library). Les exemples ci-dessous utilisent `eleven_v4_turbo`, qui autorise **une** voix enregistrée par connexion.

## Ouvrir le WebSocket

Connectez-vous à `wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input` avec des paramètres de requête tels que `model_id` et `output_format`. Vous pouvez envoyer la clé API dans l'en-tête `xi-api-key` ou dans le premier message JSON (présenté ici dans le corps afin d'utiliser un modèle unique dans toutes les langues).

**`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" });
```

## Enregistrer des voix et diffuser du texte

Envoyez un **premier message** incluant `voices` (obligatoire) et `xi_api_key` si vous n'avez pas défini l'en-tête `xi-api-key`. Envoyez ensuite une ou plusieurs trames avec `inputs` : chaque élément contient `text`, `voice_id` et, éventuellement, `new_turn`.

Le serveur met le texte en mémoire tampon jusqu'à disposer d'un contexte suffisant (environ **40 caractères** et **8 mots**), puis émet des segments `audio`. Les champs de réponse utilisent le **snake_case** (par exemple, `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` envoie tout texte en mémoire tampon, les données audio restantes, puis une trame finale avec `is_final: true` avant la fermeture de la connexion. Pour **maintenir la connexion ouverte** entre les lignes, omettez `close_socket` jusqu'à la fin de la session ; utilisez `flush` pour forcer l'audio pour des mémoires tampons plus courtes sans fermer la connexion.

## Exécuter le script

**`Python`**

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

**`TypeScript`**

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

Vous devriez obtenir un fichier MP3 dans `output/` (avec le nom de fichier indiqué dans l'exemple ci-dessus).

## Notes sur le comportement

### Mise en mémoire tampon

Contrairement à `chunk_length_schedule` du WebSocket TTS, le streaming de dialogue utilise un **seuil serveur fixe** (nombre de caractères et de mots) avant le premier audio partiel. Si vous envoyez des lignes courtes et constatez des délais, regroupez un peu plus de texte par trame `inputs` ou envoyez `flush: true` pour forcer la génération sans fermer le socket.

### Tours de parole et voix

Définissez `new_turn: true` lorsqu'un interlocuteur termine son tour de parole afin de réinitialiser correctement la prosodie. Modifier `voice_id` entre des entrées `inputs` démarre également un nouveau tour. Avec `eleven_v4_turbo`, enregistrez **exactement une** voix dans `voices` ; `eleven_v4` prend en charge jusqu'à **10** voix enregistrées.

### Inactivité

Si le serveur ne reçoit **aucun message client pendant 20 secondes**, la connexion prend fin. Envoyez `{"keep_alive": true}` pour réinitialiser le minuteur sans synthétiser d'audio.

### Requêtes simultanées

Chaque connexion ouverte conserve une session de dialogue tant qu'elle reste ouverte. Elle est issue d'un pool dédié, distinct de la limite standard de requêtes simultanées de votre forfait. L'audio généré via la connexion n'est pas comptabilisé dans les requêtes simultanées standard. Consultez [Requêtes simultanées pour Text to Dialogue](/docs/fr/overview/models#text-to-dialogue-concurrency).

### Alignement

Ajoutez `sync_alignment=true` à la chaîne de requête pour recevoir des objets `alignment` (tableaux de minutage en snake_case) dans les segments lorsqu'ils sont disponibles. Consultez le [Guide de l'API](/docs/fr/api-reference/text-to-dialogue/ttd-websocket).

## Étapes suivantes

#### [WebSockets TTS et TTD](/docs/fr/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets)

Choisissez le WebSocket adapté et comparez les formats de message.

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

Paramètres de requête, schémas de messages et exemples.

#### [Diffuser un dialogue (HTTP)](/docs/fr/api-reference/text-to-dialogue/stream)

Lorsque le texte complet de la requête est disponible sans WebSocket.

#### [WebSocket TTS en temps réel](/docs/fr/eleven-api/guides/how-to/websockets/realtime-tts)

Streaming non v3 à voix unique via WebSocket.