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

# Audio in Echtzeit generieren

WebSocket-Streaming ist eine Methode zum Senden und Empfangen von Daten über eine einzelne, langlebige Verbindung. Diese Methode eignet sich für Echtzeitanwendungen, bei denen Sie Audiodaten streamen müssen, sobald sie verfügbar sind.

Wenn Sie die Latenz (Zeit bis zum ersten Byte) einer WebSocket-Verbindung zur ElevenLabs-Text-to-Speech-API schnell testen möchten, können Sie `elevenlabs-latency` über `npm` installieren und den Anweisungen [hier](https://www.npmjs.com/package/elevenlabs-latency?activeTab=readme) folgen.

> **Note**
>
> WebSockets sind für Text to Speech und die Agents Platform verfügbar. Dieser Leitfaden behandelt den
> **Text to Speech**-WebSocket (`/v1/text-to-speech/{voice_id}/stream-input`). Dieser Endpunkt
> unterstützt die Modelle `eleven_v3` und `eleven_v4` **nicht**. Informationen zu **Eleven v3**-
> oder **Eleven v4**-Dialogen über einen WebSocket finden Sie unter [Realtime Text to Dialogue](/docs/de/eleven-api/guides/how-to/websockets/realtime-tdd)
> und [Text to Speech vs. Text to Dialogue WebSockets](/docs/de/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets).

## Voraussetzungen

* Ein ElevenLabs-Konto mit API-Schlüssel (so [finden Sie Ihren API-Schlüssel](/docs/de/api-reference/authentication)).
* Python oder Node.js (oder eine andere JavaScript-Laufzeit) auf Ihrem Computer installiert

## Einrichtung

Installieren Sie die erforderlichen Abhängigkeiten:

**`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
```

Erstellen Sie anschließend eine `.env`-Datei in Ihrem Projektverzeichnis und fügen Sie Ihren API-Schlüssel hinzu:

**`.env`**

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

## WebSocket-Verbindung herstellen

Nachdem Sie eine Stimme aus der Stimmbibliothek und das gewünschte Text-to-Speech-Modell ausgewählt haben, stellen Sie eine WebSocket-Verbindung zur Text-to-Speech-API her.

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

## Eingabetext senden

Sobald die WebSocket-Verbindung geöffnet ist, richten Sie zuerst die Stimmeinstellungen ein. Senden Sie anschließend die Textnachricht an die 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: "" }));
});
```

## Audio in Datei speichern

Lesen Sie die eingehende Nachricht aus der WebSocket-Verbindung und schreiben Sie die Audio-Chunks in eine lokale Datei.

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

## Skript ausführen

Sie können das Skript ausführen, indem Sie den folgenden Befehl im Terminal eingeben. Eine MP3-Audiodatei wird im Verzeichnis `output` gespeichert.

**`Python`**

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

**`TypeScript`**

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

## Erweiterte Konfiguration

WebSockets bieten einige erweiterte Einstellungen, mit denen Sie Ihre Audioerzeugung in Echtzeit fein abstimmen können.

### Pufferung

Bei der Audioerzeugung in Echtzeit sollten zwei wichtige Konzepte berücksichtigt werden: Time To First Byte (TTFB) und Pufferung. Um hochwertige Audiodaten zu erzeugen und Kontext abzuleiten, benötigt das Modell eine bestimmte Menge an Eingabetext. Je mehr Text über eine WebSocket-Verbindung gesendet wird, desto besser ist die Audioqualität. Wird dieser Schwellenwert nicht erreicht, fügt das Modell den Text einem Puffer hinzu und erzeugt Audio, sobald der Puffer gefüllt ist.

Bei der Latenz bezeichnet TTFB die Zeit, bis das erste Audio-Byte an den Client gesendet wird. Das ist wichtig, weil es die wahrgenommene Latenz des Audios beeinflusst. Daher sollten Sie die Puffergröße steuern, um Qualität und Latenz auszubalancieren.

Dafür können Sie den Parameter `chunk_length_schedule` verwenden, entweder beim Initialisieren der WebSocket-Verbindung oder beim Senden von Text. Dieser Parameter ist ein Array von Ganzzahlen, die die Anzahl der Zeichen darstellen, die an das Modell gesendet werden, bevor Audio erzeugt wird. Wenn Sie `chunk_length_schedule` beispielsweise auf `[120, 160, 250, 290]` setzen, erzeugt das Modell Audio, nachdem jeweils 120, 160, 250 und 290 Zeichen gesendet wurden.

So funktioniert dies mit den Standardeinstellungen für `chunk_length_schedule`:

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

Im obigen Diagramm wird Audio erst erzeugt, nachdem die zweite Nachricht an den Server gesendet wurde. Das liegt daran, dass die erste Nachricht unter dem Schwellenwert von 120 Zeichen liegt, während die zweite Nachricht die Gesamtzahl der Zeichen über diesen Schwellenwert erhöht. Die dritte Nachricht liegt über dem Schwellenwert von 160 Zeichen, daher wird Audio sofort erzeugt und an den Client zurückgegeben.

Sie können beim Initialisieren der WebSocket-Verbindung oder beim Senden von Text einen benutzerdefinierten Wert für `chunk_length_schedule` festlegen.

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

Wenn Sie die sofortige Rückgabe des Audios erzwingen möchten, können Sie mit `flush: true` den Puffer leeren und die Erzeugung aller gepufferten Texte erzwingen. Das kann beispielsweise nützlich sein, wenn Sie das Ende eines Dokuments erreicht haben und Audio für den letzten Abschnitt erzeugen möchten.

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

Dies kann pro Nachricht festgelegt werden, indem Sie in der Nachricht `flush: true` setzen.

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

Darüber hinaus erzwingt das Schließen des WebSockets automatisch die Erzeugung aller gepufferten Texte.

### Stimmeinstellungen

Beim Initialisieren der WebSocket-Verbindungen können Sie die Stimmeinstellungen für nachfolgende Generierungen festlegen. So steuern Sie Geschwindigkeit, Stabilität und weitere Stimmmerkmale des erzeugten Audios.

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

Dies kann pro Nachricht überschrieben werden, indem Sie in der Nachricht andere `voice_settings` angeben.

### Aussprachewörterbücher

Mit Aussprachewörterbüchern können Sie die Aussprache bestimmter Wörter oder Ausdrücke steuern. Das kann nützlich sein, um sicherzustellen, dass bestimmte Wörter korrekt ausgesprochen werden, oder um bestimmte Wörter oder Ausdrücke zu betonen.

Im Gegensatz zu `voice_settings` und `generation_config` müssen Aussprachewörterbücher in der Nachricht „Verbindung initialisieren“ angegeben werden. Weitere Informationen finden Sie in der [API-Referenz](/docs/de/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#send.Initialize%20Connection.pronunciation_dictionary_locators).

> **Tip**
>
> Wenn Sie phonembasierte Aussprachewörterbücher mit WebSockets verwenden, müssen Sie `enable_ssml_parsing=true` als Abfrageparameter zur WebSocket-URI hinzufügen. Beispiel:
>
> ```
> wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}&enable_ssml_parsing=true
> ```

## Best Practice

* Wir empfehlen die Standardeinstellung für `chunk_length_schedule` in `generation_config`.
* Bei der Entwicklung einer Anwendung für Echtzeit-Konversationsagenten empfehlen wir, `flush: true` zusammen mit dem Text am Ende eines Gesprächszugs zu verwenden, um eine zeitnahe Audioerzeugung sicherzustellen.
* Wenn die Standardeinstellung für Ihren Anwendungsfall keine optimale Latenz bietet, können Sie `chunk_length_schedule` anpassen. Beachten Sie jedoch, dass eine Latenzreduzierung durch diese Anpassung die Qualität beeinträchtigen kann.

## Tipps

* Die WebSocket-Verbindung wird nach 20 Sekunden Inaktivität automatisch geschlossen. Um die Verbindung offen zu halten, können Sie ein einzelnes Leerzeichen `" "` senden. Beachten Sie, dass diese Zeichenfolge ein Leerzeichen enthalten muss, da eine vollständig leere Zeichenfolge, `""`, den WebSocket schließt.
* Senden Sie nach der letzten Textnachricht eine leere Zeichenfolge, um die WebSocket-Verbindung zu schließen.
* Mit `alignment` können Sie Zeitstempel auf Wortebene für jedes Wort im Text abrufen. Das kann nützlich sein, um Audio und Text in einem Video abzugleichen oder für andere Anwendungen, die präzises Timing erfordern. Weitere Informationen finden Sie in der [API-Referenz](/docs/de/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#receive.Audio%20Output.alignment).

## Nächste Schritte

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

Verwenden Sie HTTP-Streaming, wenn der Eingabetext vorab verfügbar ist, statt in Echtzeit generiert zu werden.

#### [Latenzoptimierung](/docs/de/eleven-api/guides/how-to/best-practices/latency-optimization)

Reduzieren Sie die Zeit bis zum ersten Audio mit Modellauswahl, Stimmenauswahl und geografischem Routing.