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

# Genera audio in tempo reale

Lo streaming WebSocket è un metodo per inviare e ricevere dati tramite un'unica connessione persistente. È utile per le applicazioni in tempo reale in cui devi trasmettere dati audio non appena diventano disponibili.

Se vuoi testare rapidamente la latenza (time to first byte) di una connessione WebSocket all'API Text to Speech di ElevenLabs, puoi installare `elevenlabs-latency` tramite `npm` e seguire le istruzioni [qui](https://www.npmjs.com/package/elevenlabs-latency?activeTab=readme).

> **Note**
>
> I WebSocket sono disponibili per Text to Speech e la piattaforma Agents. Questa guida tratta il WebSocket **Text
> to Speech** (`/v1/text-to-speech/{voice_id}/stream-input`). Questo endpoint **non** supporta i modelli
> `eleven_v3` o `eleven_v4`. Per dialoghi con **Eleven v3** o **Eleven v4** tramite WebSocket, consulta
> [Text to Dialogue in tempo reale](/docs/it/eleven-api/guides/how-to/websockets/realtime-tdd)
> e [WebSocket Text to Speech e Text to Dialogue a confronto](/docs/it/eleven-api/guides/how-to/websockets/tts-vs-ttd-websockets).

## Requisiti

* Un account ElevenLabs con una chiave API (ecco come [trovare la tua chiave API](/docs/it/api-reference/authentication)).
* Python o Node.js (o un altro runtime JavaScript) installato sul tuo computer

## Configurazione

Installa le dipendenze necessarie:

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

Poi, crea un file `.env` nella directory del progetto e aggiungi la tua chiave API:

**`.env`**

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

## Avvia la connessione WebSocket

Dopo aver scelto una voce dalla Voice Library e il modello Text to Speech che vuoi usare, avvia una connessione WebSocket all'API Text to Speech.

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

## Invia il testo di input

Una volta aperta la connessione WebSocket, configura prima le impostazioni della voce. Poi invia il messaggio di testo all'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: "" }));
});
```

## Salva l'audio in un file

Leggi il messaggio in arrivo dalla connessione WebSocket e scrivi i chunk audio in un file locale.

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

## Esegui lo script

Puoi eseguire lo script con il seguente comando nel terminale. Un file audio mp3 verrà salvato nella directory `output`.

**`Python`**

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

**`TypeScript`**

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

## Configurazione avanzata

L'uso dei WebSocket include alcune impostazioni avanzate che puoi usare per ottimizzare la generazione audio in tempo reale.

### Buffering

Quando generi audio in tempo reale, devi considerare due concetti importanti: Time To First Byte (TTFB) e buffering. Per produrre audio di alta qualità e dedurre il contesto, il modello richiede una certa soglia di testo di input. Più testo viene inviato tramite una connessione WebSocket, migliore sarà la qualità dell'audio. Se la soglia non viene raggiunta, il modello aggiunge il testo a un buffer e genera l'audio quando il buffer è pieno.

In termini di latenza, il TTFB è il tempo necessario per inviare il primo byte di audio al client. È importante perché influisce sulla latenza percepita dell'audio. Potresti quindi voler controllare la dimensione del buffer per bilanciare qualità e latenza.

Per gestirlo, puoi usare il parametro `chunk_length_schedule` quando inizializzi la connessione WebSocket o quando invii il testo. Questo parametro è un array di interi che rappresentano il numero di caratteri inviati al modello prima di generare l'audio. Ad esempio, se imposti `chunk_length_schedule` su `[120, 160, 250, 290]`, il modello genererà audio dopo l'invio rispettivamente di 120, 160, 250 e 290 caratteri.

Ecco un esempio di come funziona con le impostazioni predefinite di `chunk_length_schedule`:

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

Nel diagramma qui sopra, l'audio viene generato solo dopo l'invio del secondo messaggio al server. Questo perché il primo messaggio è sotto la soglia di 120 caratteri, mentre il secondo porta il numero totale di caratteri oltre la soglia. Il terzo messaggio supera la soglia di 160 caratteri, quindi l'audio viene generato immediatamente e restituito al client.

Puoi specificare un valore personalizzato per `chunk_length_schedule` quando inizializzi la connessione WebSocket o quando invii il testo.

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

Se vuoi forzare la restituzione immediata dell'audio, puoi usare `flush: true` per svuotare il buffer e forzare la generazione del testo memorizzato nel buffer. Questo può essere utile, ad esempio, quando hai raggiunto la fine di un documento e vuoi generare l'audio per la sezione finale.

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

Puoi specificarlo per ogni messaggio impostando `flush: true` nel messaggio.

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

Inoltre, chiudendo il WebSocket verrà automaticamente forzata la generazione del testo nel buffer.

### Impostazioni della voce

Quando inizializzi le connessioni WebSocket, puoi specificare le impostazioni della voce per le generazioni successive. Ciò ti consente di controllare la velocità, la stabilità e altre caratteristiche vocali dell'audio generato.

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

Puoi sostituirle per ogni messaggio specificando `voice_settings` diversi nel messaggio.

### Dizionari di pronuncia

Puoi usare i dizionari di pronuncia per controllare la pronuncia di parole o frasi specifiche. Questo può essere utile per assicurarti che determinate parole siano pronunciate correttamente o per aggiungere enfasi a parole o frasi specifiche.

A differenza di `voice_settings` e `generation_config`, i dizionari di pronuncia devono essere specificati nel messaggio "Initialize Connection". Per maggiori informazioni, consulta il [Riferimento API](/docs/it/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#send.Initialize%20Connection.pronunciation_dictionary_locators).

> **Tip**
>
> Quando usi dizionari di pronuncia basati su fonemi con i WebSocket, devi aggiungere `enable_ssml_parsing=true` come parametro query all'URI del WebSocket. Ad esempio:
>
> ```
> wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model_id}&enable_ssml_parsing=true
> ```

## Buone pratiche

* Ti consigliamo di usare l'impostazione predefinita per `chunk_length_schedule` in `generation_config`.
* Quando sviluppi un'applicazione di agente conversazionale in tempo reale, ti consigliamo di usare `flush: true` insieme al testo alla fine del turno di conversazione per garantire una generazione audio tempestiva.
* Se l'impostazione predefinita non offre una latenza ottimale per il tuo caso d'uso, puoi modificare `chunk_length_schedule`. Tieni però presente che ridurre la latenza con questa modifica può compromettere la qualità.

## Suggerimenti

* La connessione WebSocket si chiude automaticamente dopo 20 secondi di inattività. Per tenerla aperta, puoi inviare un singolo carattere spazio `" "`. Tieni presente che questa stringa deve includere uno spazio, poiché l'invio di una stringa completamente vuota, `""`, chiuderà il WebSocket.
* Invia una stringa vuota per chiudere la connessione WebSocket dopo aver inviato l'ultimo messaggio di testo.
* Puoi usare `alignment` per ottenere i timestamp a livello di parola per ogni parola nel testo. Può essere utile per allineare l'audio al testo in un video o per altre applicazioni che richiedono una temporizzazione precisa. Per maggiori informazioni, consulta il [Riferimento API](/docs/it/api-reference/text-to-speech/v-1-text-to-speech-voice-id-stream-input#receive.Audio%20Output.alignment).

## Passaggi successivi

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

Usa lo streaming HTTP quando il testo di input è disponibile in anticipo anziché generato in tempo reale.

#### [Ottimizzazione della latenza](/docs/it/eleven-api/guides/how-to/best-practices/latency-optimization)

Riduci il tempo al primo audio scegliendo il modello e la voce e usando il routing geografico.