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

# Generera ljud i realtid

WebSocket-streaming är en metod för att skicka och ta emot data över en enda, långvarig anslutning. Metoden är användbar för realtidsapplikationer där du behöver streama ljuddata så snart den blir tillgänglig.

Om du snabbt vill testa latensen (tid till första byte) för en WebSocket-anslutning till ElevenLabs Text to Speech API kan du installera `elevenlabs-latency` via `npm` och följa instruktionerna [här](https://www.npmjs.com/package/elevenlabs-latency?activeTab=readme).

> **Note**
>
> WebSockets är tillgängliga för Text to Speech och Agents Platform. Den här guiden handlar om Text
> to Speech-WebSocketen (`/v1/text-to-speech/{voice_id}/stream-input`). Den slutpunkten stöder **inte**
> modellerna `eleven_v3` eller `eleven_v4`. För dialog med **Eleven v3** eller **Eleven v4** över en
> WebSocket, se [Text till dialog i realtid](/docs/sv/eleven-api/guides/how-to/websockets/realtime-tdd)
> och [Text to Speech- kontra Text to Dialogue- WebSockets](/docs/sv/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets).

## Krav

* Ett ElevenLabs-konto med en API-nyckel (så här [hittar du din API-nyckel](/docs/sv/api-reference/authentication)).
* Python eller Node.js (eller en annan JavaScript-runtime) installerat på din dator

## Konfiguration

Installera nödvändiga beroenden:

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

Skapa sedan en `.env`-fil i projektkatalogen och lägg till din API-nyckel:

**`.env`**

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

## Upprätta WebSocket-anslutningen

När du har valt en röst från Voice Library och den text till tal-modell du vill använda, upprättar du en WebSocket-anslutning till text till tal-API:et.

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

## Skicka indatatexten

När WebSocket-anslutningen är öppen ska du först ange röstinställningar. Skicka sedan textmeddelandet till API:et.

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

## Spara ljudet till en fil

Läs det inkommande meddelandet från WebSocket-anslutningen och skriv ljudsegmenten till en lokal fil.

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

## Kör skriptet

Du kan köra skriptet genom att köra följande kommando i terminalen. En mp3-ljudfil sparas i katalogen `output`.

**`Python`**

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

**`TypeScript`**

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

## Avancerad konfiguration

WebSockets har några avancerade inställningar som du kan använda för att finjustera ljudgenerering i realtid.

### Buffring

Vid ljudgenerering i realtid bör du ta hänsyn till två viktiga begrepp: Time To First Byte (TTFB) och buffring. För att skapa ljud av hög kvalitet och förstå sammanhang behöver modellen en viss mängd indatatext. Ju mer text som skickas i en WebSocket-anslutning, desto bättre blir ljudkvaliteten. Om tröskelvärdet inte uppnås lägger modellen texten i en buffert och genererar ljud när bufferten är full.

När det gäller latens är TTFB tiden det tar innan den första ljudbyten skickas till klienten. Detta är viktigt eftersom det påverkar den upplevda ljudlatensen. Därför kan du vilja styra buffertstorleken för att balansera kvalitet och latens.

För att hantera detta kan du använda parametern `chunk_length_schedule` när du antingen initierar WebSocket-anslutningen eller skickar text. Parametern är en matris med heltal som representerar antalet tecken som skickas till modellen innan ljud genereras. Om du till exempel anger `chunk_length_schedule` till `[120, 160, 250, 290]` genererar modellen ljud efter att 120, 160, 250 respektive 290 tecken har skickats.

Så här fungerar det med standardinställningarna för `chunk_length_schedule`:

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

I diagrammet ovan genereras ljud först efter att det andra meddelandet har skickats till servern. Det beror på att det första meddelandet är under tröskelvärdet på 120 tecken, medan det andra meddelandet gör att det totala antalet tecken hamnar över tröskelvärdet. Det tredje meddelandet är över tröskelvärdet på 160 tecken, så ljud genereras direkt och returneras till klienten.

Du kan ange ett anpassat värde för `chunk_length_schedule` när du initierar WebSocket-anslutningen eller skickar text.

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

Om du vill tvinga fram omedelbar returnering av ljudet kan du använda `flush: true` för att tömma bufferten och tvinga fram generering av buffrad text. Det kan till exempel vara användbart när du har nått slutet av ett dokument och vill generera ljud för den sista delen.

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

Du kan ange detta för varje enskilt meddelande genom att ställa in `flush: true` i meddelandet.

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

Dessutom kommer WebSocketen automatiskt att tvinga fram generering av buffrad text när den stängs.

### Röstinställningar

När du initierar WebSocket-anslutningar kan du ange röstinställningar för efterföljande genereringar. På så sätt kan du styra hastighet, stabilitet och andra röstegenskaper för det genererade ljudet.

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

Detta kan åsidosättas för varje enskilt meddelande genom att ange andra `voice_settings` i meddelandet.

### Uttalslexikon

Du kan använda uttalslexikon för att styra uttalet av specifika ord eller fraser. Det kan vara användbart för att säkerställa att vissa ord uttalas korrekt eller för att betona vissa ord eller fraser.

Till skillnad från `voice_settings` och `generation_config` måste uttalslexikon anges i meddelandet "Initialize Connection". Mer information finns i [API-referensen](/docs/sv/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#send.Initialize%20Connection.pronunciation_dictionary_locators).

> **Tip**
>
> När du använder fonემბaserade uttalslexikon med WebSockets måste du lägga till `enable_ssml_parsing=true` som en frågeparameter i WebSocket-URI:n. Till exempel:
>
> ```
> wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}&enable_ssml_parsing=true
> ```

## Bästa praxis

* Vi rekommenderar att du använder standardinställningen för `chunk_length_schedule` i `generation_config`.
* När du utvecklar en applikation för en konversationsagent i realtid rekommenderar vi att du använder `flush: true` tillsammans med texten i slutet av en samtalstur för att säkerställa ljudgenerering i rätt tid.
* Om standardinställningen inte ger optimal latens för ditt användningsfall kan du ändra `chunk_length_schedule`. Tänk dock på att lägre latens genom denna justering kan ske på bekostnad av kvaliteten.

## Tips

* WebSocket-anslutningen stängs automatiskt efter 20 sekunders inaktivitet. För att hålla anslutningen öppen kan du skicka ett enskilt blankstegstecken `" "`. Observera att strängen måste innehålla ett blanksteg, eftersom en helt tom sträng, `""`, stänger WebSocketen.
* Skicka en tom sträng för att stänga WebSocket-anslutningen efter att du har skickat det sista textmeddelandet.
* Du kan använda `alignment` för att få tidsstämplar på ordnivå för varje ord i texten. Det kan vara användbart för att synkronisera ljudet med texten i en video eller för andra applikationer som kräver exakt tidsangivelse. Mer information finns i [API-referensen](/docs/sv/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#receive.Audio%20Output.alignment).

## Nästa steg

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

Använd HTTP-streaming när indatatexten är tillgänglig på förhand i stället för att genereras i realtid.

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

Minska tiden till första ljudet genom modellval, röstval och geografisk routning.