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

# Genereer audio realtime

WebSocket-streaming is een methode om gegevens te verzenden en te ontvangen via één enkele, langdurige verbinding. Deze methode is handig voor realtime-applicaties waarbij je audiogegevens moet streamen zodra deze beschikbaar zijn.

Als je snel de latency (tijd tot de eerste byte) van een WebSocket-verbinding met de ElevenLabs Text to Speech-API wilt testen, kun je `elevenlabs-latency` installeren via `npm` en de instructies [hier](https://www.npmjs.com/package/elevenlabs-latency?activeTab=readme) volgen.

> **Note**
>
> WebSockets zijn beschikbaar voor Text to Speech en het Agents Platform. Deze handleiding behandelt de
> **Text to Speech**-WebSocket (`/v1/text-to-speech/{voice_id}/stream-input`). Dat endpoint ondersteunt
> de modellen `eleven_v3` en `eleven_v4` **niet**. Zie voor **Eleven v3**- of **Eleven v4**-dialoog via een
> WebSocket [Realtime Text to Dialogue](/docs/nl/eleven-api/guides/how-to/websockets/realtime-tdd)
> en [Text to Speech- en Text to Dialogue- WebSockets](/docs/nl/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets).

## Vereisten

* Een ElevenLabs-account met een API-sleutel (zo [vind je je API-sleutel](/docs/nl/api-reference/authentication)).
* Python of Node.js (of een andere JavaScript-runtime) geïnstalleerd op je apparaat

## Instellen

Installeer de vereiste afhankelijkheden:

**`Python`**

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

**`TypeScript`**

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

Maak vervolgens een `.env`-bestand in je projectmap en voeg je API-sleutel toe:

**`.env`**

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

## De WebSocket-verbinding starten

Kies een stem uit de Voice Library en het Text to Speech-model dat je wilt gebruiken. Start vervolgens een WebSocket-verbinding met de Text to Speech-API.

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

```python text-to-speech-websocket.py
import os
from dotenv import load_dotenv
import websockets

# Load the API key from the .env file
load_dotenv()
ELEVENLABS_API_KEY = os.getenv("ELEVENLABS_API_KEY")

voice_id = 'Xb7hH8MSUJpSbSDYk0k2'

# For use cases where latency is important, we recommend using the 'eleven_flash_v2_5' model.
model_id = 'eleven_flash_v2_5'

async def text_to_speech_ws_streaming(voice_id, model_id):
    uri = f"wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}"

    async with websockets.connect(uri) as websocket:
       ...
```

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

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

// Load the API key from the .env file
dotenv.config();
const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;

const voiceId = "Xb7hH8MSUJpSbSDYk0k2";

// For use cases where latency is important, we recommend using the 'eleven_flash_v2_5' model.
const model = "eleven_flash_v2_5";

const uri = `wss://api.elevenlabs.io/v1/text-to-speech/${voiceId}/stream-input?model_id=${model}`;
const websocket = new WebSocket(uri, {
  headers: { "xi-api-key": `${ELEVENLABS_API_KEY}` },
});

// Create a directory for saving the audio
const outputDir = "./output";

try {
  fs.accessSync(outputDir, fs.constants.R_OK | fs.constants.W_OK);
} catch (err) {
  fs.mkdirSync(outputDir);
}

// Create a write stream for saving the audio into mp3
const writeStream = fs.createWriteStream(outputDir + "/test.mp3", {
  flags: "a",
});
```

## De invoertekst versturen

Stel eerst de steminstellingen in zodra de WebSocket-verbinding is geopend. Stuur daarna het tekstbericht naar de API.

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

```python text-to-speech-websocket.py
async def text_to_speech_ws_streaming(voice_id, model_id):
    async with websockets.connect(uri) as websocket:
        await websocket.send(json.dumps({
            "text": " ",
            "voice_settings": {"stability": 0.5, "similarity_boost": 0.8, "use_speaker_boost": False},
            "generation_config": {
                "chunk_length_schedule": [120, 160, 250, 290]
            },
            "xi_api_key": ELEVENLABS_API_KEY,
        }))

        text = "The twilight sun cast its warm golden hues upon the vast rolling fields, saturating the landscape with an ethereal glow. Silently, the meandering brook continued its ceaseless journey, whispering secrets only the trees seemed privy to."
        await websocket.send(json.dumps({"text": text}))

        # Send empty string to indicate the end of the text sequence which will close the WebSocket connection
        await websocket.send(json.dumps({"text": ""}))
```

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

```typescript text-to-speech-websocket.ts
const text =
  "The twilight sun cast its warm golden hues upon the vast rolling fields, saturating the landscape with an ethereal glow. Silently, the meandering brook continued its ceaseless journey, whispering secrets only the trees seemed privy to.";

websocket.on("open", async () => {
  websocket.send(
    JSON.stringify({
      text: " ",
      voice_settings: {
        stability: 0.5,
        similarity_boost: 0.8,
        use_speaker_boost: false,
      },
      generation_config: { chunk_length_schedule: [120, 160, 250, 290] },
    })
  );

  websocket.send(JSON.stringify({ text: text }));

  // Send empty string to indicate the end of the text sequence which will close the websocket connection
  websocket.send(JSON.stringify({ text: "" }));
});
```

## De audio opslaan in een bestand

Lees het binnenkomende bericht van de WebSocket-verbinding en schrijf de audiochunks naar een lokaal bestand.

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

```python text-to-speech-websocket.py
import asyncio

async def write_to_local(audio_stream):
    """Write the audio encoded in base64 string to a local mp3 file."""

    with open(f'./output/test.mp3', "wb") as f:
        async for chunk in audio_stream:
            if chunk:
                f.write(chunk)

async def listen(websocket):
    """Listen to the websocket for audio data and stream it."""

    while True:
        try:
            message = await websocket.recv()
            data = json.loads(message)
            if data.get("audio"):
                yield base64.b64decode(data["audio"])
            elif data.get('isFinal'):
                break

        except websockets.exceptions.ConnectionClosed:
            print("Connection closed")
            break

async def text_to_speech_ws_streaming(voice_id, model_id):
    async with websockets.connect(uri) as websocket:
          ...
          # Add listen task to submit the audio chunks to the write_to_local function
          listen_task = asyncio.create_task(write_to_local(listen(websocket)))

          await listen_task

asyncio.run(text_to_speech_ws_streaming(voice_id, model_id))
```

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

```typescript text-to-speech-websocket.ts
// Helper function to write the audio encoded in base64 string into local file
function writeToLocal(base64str: any, writeStream: fs.WriteStream) {
  const audioBuffer: Buffer = Buffer.from(base64str, "base64");
  writeStream.write(audioBuffer, (err) => {
    if (err) {
      console.error("Error writing to file:", err);
    }
  });
}

// Listen to the incoming message from the websocket connection
websocket.on("message", function incoming(event) {
  const data = JSON.parse(event.toString());
  if (data["audio"]) {
    writeToLocal(data["audio"], writeStream);
  }
});

// Close the writeStream when the websocket connection closes
websocket.on("close", () => {
  writeStream.end();
});
```

## Het script uitvoeren

Voer het script uit met de volgende opdracht in je terminal. Een mp3-audiobestand wordt opgeslagen in de map `output`.

**`Python`**

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

**`TypeScript`**

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

## Geavanceerde configuratie

WebSockets bieden enkele geavanceerde instellingen waarmee je je realtime-audiogeneratie nauwkeurig kunt afstemmen.

### Buffering

Bij het genereren van realtime-audio moet je rekening houden met twee belangrijke begrippen: Time To First Byte (TTFB) en buffering. Om audio van hoge kwaliteit te produceren en context af te leiden, heeft het model een bepaalde hoeveelheid invoertekst nodig. Hoe meer tekst er via een WebSocket-verbinding wordt verzonden, hoe beter de audiokwaliteit. Als deze drempel niet wordt bereikt, voegt het model de tekst toe aan een buffer en genereert het audio zodra de buffer vol is.

Wat latency betreft, is TTFB de tijd die nodig is om de eerste audiobyte naar de client te sturen. Dit is belangrijk omdat het de waargenomen latency van de audio beïnvloedt. Daarom wil je mogelijk de buffergrootte bepalen om een balans te vinden tussen kwaliteit en latency.

Hiervoor kun je de parameter `chunk_length_schedule` gebruiken wanneer je de WebSocket-verbinding initialiseert of tekst verstuurt. Deze parameter is een array met gehele getallen die het aantal tekens aangeven dat naar het model wordt gestuurd voordat audio wordt gegenereerd. Als je `chunk_length_schedule` bijvoorbeeld instelt op `[120, 160, 250, 290]`, genereert het model audio nadat respectievelijk 120, 160, 250 en 290 tekens zijn verzonden.

Hier zie je hoe dit werkt met de standaardinstellingen voor `chunk_length_schedule`:

![](/docs/_fern-img/077efc232570b0f92355aed2d6766b66bba815e335466e81cd64f8dfcce10ada.webp)

In het bovenstaande diagram wordt audio pas gegenereerd nadat het tweede bericht naar de server is gestuurd. Dit komt doordat het eerste bericht onder de drempel van 120 tekens blijft, terwijl het tweede bericht het totale aantal tekens boven die drempel brengt. Het derde bericht komt boven de drempel van 160 tekens, dus de audio wordt meteen gegenereerd en naar de client teruggestuurd.

Je kunt een aangepaste waarde voor `chunk_length_schedule` opgeven wanneer je de WebSocket-verbinding initialiseert of tekst verstuurt.

```python
await websocket.send(json.dumps({
    "text": text,
    "generation_config": {
        # Generate audio after 50, 120, 160, and 290 characters have been sent
        "chunk_length_schedule": [50, 120, 160, 290]
    },
    "xi_api_key": ELEVENLABS_API_KEY,
}))
```

```typescript
websocket.send(
  JSON.stringify({
    text: text,
    // Generate audio after 50, 120, 160, and 290 characters have been sent
    generation_config: { chunk_length_schedule: [50, 120, 160, 290] },
    xi_api_key: ELEVENLABS_API_KEY,
  })
);
```

Als je audio onmiddellijk wilt laten terugsturen, kun je `flush: true` gebruiken om de buffer te wissen en alle gebufferde tekst te laten genereren. Dit kan bijvoorbeeld handig zijn wanneer je het einde van een document hebt bereikt en audio wilt genereren voor het laatste gedeelte.

![](/docs/_fern-img/84011e01024effe1bba1556f0007c7947165a0101bce3a41f8b955d1a9788a9c.webp)

Je kunt dit per bericht instellen door `flush: true` in het bericht op te nemen.

```python
await websocket.send(json.dumps({"text": "Generate this audio immediately.", "flush": True}))
```

```typescript
websocket.send(JSON.stringify({ text: "Generate this audio immediately.", flush: true }));
```

Daarnaast zorgt het sluiten van de WebSocket er automatisch voor dat alle gebufferde tekst wordt gegenereerd.

### Steminstellingen

Wanneer je de WebSocket-verbinding initialiseert, kun je de steminstellingen voor de volgende generaties opgeven. Hiermee bepaal je de snelheid, stabiliteit en andere stemkenmerken van de gegenereerde audio.

```python
await websocket.send(json.dumps({
    "text": text,
    "voice_settings": {"stability": 0.5, "similarity_boost": 0.8, "use_speaker_boost": False},
}))
```

```typescript
websocket.send(
  JSON.stringify({
    text: text,
    voice_settings: { stability: 0.5, similarity_boost: 0.8, use_speaker_boost: false },
  })
);
```

Je kunt dit per bericht overschrijven door andere `voice_settings` in het bericht op te geven.

### Uitspraakwoordenboeken

Je kunt uitspraakwoordenboeken gebruiken om de uitspraak van specifieke woorden of zinnen te bepalen. Dit kan handig zijn om ervoor te zorgen dat bepaalde woorden correct worden uitgesproken of om nadruk op bepaalde woorden of zinnen te leggen.

In tegenstelling tot `voice_settings` en `generation_config` moet je uitspraakwoordenboeken opgeven in het bericht "Initialize Connection". Zie de [API-referentie](/docs/nl/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#send.Initialize%20Connection.pronunciation_dictionary_locators) voor meer informatie.

> **Tip**
>
> Wanneer je fonemen gebaseerde uitspraakwoordenboeken met WebSockets gebruikt, moet je `enable_ssml_parsing=true` als queryparameter aan de WebSocket-URI toevoegen. Bijvoorbeeld:
>
> ```
> wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}&enable_ssml_parsing=true
> ```

## Best practice

* We raden aan de standaardinstelling voor `chunk_length_schedule` in `generation_config` te gebruiken.
* Bij het ontwikkelen van een realtime-applicatie voor een conversationele agent raden we aan `flush: true` samen met de tekst aan het einde van een gespreksbeurt te gebruiken, zodat audio tijdig wordt gegenereerd.
* Als de standaardinstelling geen optimale latency biedt voor je use case, kun je `chunk_length_schedule` aanpassen. Houd er wel rekening mee dat het verminderen van latency met deze aanpassing ten koste kan gaan van de kwaliteit.

## Tips

* De WebSocket-verbinding wordt na 20 seconden inactiviteit automatisch gesloten. Om de verbinding open te houden, kun je één spatieteken `" "` versturen. Deze string moet een spatie bevatten, want een volledig lege string, `""`, sluit de WebSocket.
* Stuur een lege string om de WebSocket-verbinding te sluiten nadat je het laatste tekstbericht hebt verstuurd.
* Je kunt `alignment` gebruiken om tijdstempels op woordniveau voor elk woord in de tekst op te halen. Dit kan handig zijn om de audio met de tekst in een video uit te lijnen of voor andere toepassingen die nauwkeurige timing vereisen. Zie de [API-referentie](/docs/nl/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#receive.Audio%20Output.alignment) voor meer informatie.

## Volgende stappen

#### [TTS-streaming](/docs/nl/eleven-api/guides/how-to/text-to-speech/streaming)

Gebruik HTTP-streaming wanneer de invoertekst vooraf beschikbaar is in plaats van realtime te worden gegenereerd.

#### [Latency optimaliseren](/docs/nl/eleven-api/guides/how-to/best-practices/latency-optimization)

Verkort de tijd tot de eerste audio met de modelkeuze, stemkeuze en geografische routing.