Vai alla navigazione

Trasmetti dialoghi in tempo reale

Questa guida mostra come trasmettere l'audio dei dialoghi di Eleven v3 tramite il WebSocket Text to Dialogue.

Il WebSocket Text to Dialogue (/v1/text-to-dialogue/stream-input) mantiene aperta una singola connessione mentre invii battute di dialogo e ricevi chunk audio codificati in base64. È pensato solo per i modelli di dialogo Eleven v3 e Eleven v4 (model_id deve iniziare con eleven_v3 o eleven_v4).

Questa guida tratta il WebSocket Text to Dialogue. Per Flash, Multilingual v2 o altri modelli TTS non v3, usa il WebSocket TTS in tempo reale . Per un riepilogo affiancato di entrambi i protocolli, consulta WebSocket Text to Speech e Text to Dialogue .

Requisiti

  • Un account ElevenLabs con una chiave API (autenticazione).
  • La chiave API deve disporre delle autorizzazioni Text to Speech.
  • Python o Node.js installato sul tuo computer.

Configurazione

pip install python-dotenv websockets

Crea un file .env:

.env
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here

Scegli un ID voce dalla Voice Library. Gli esempi seguenti usano eleven_v4_turbo, che consente una voce registrata per connessione.

Apri il WebSocket

Connettiti a wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input con parametri query quali model_id e output_format. Puoi inviare la chiave API nell’header xi-api-key oppure nel primo messaggio JSON (mostrata qui nel body per usare lo stesso schema in tutte le lingue).

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"
)

Registra le voci e trasmetti il testo

Invia un primo messaggio che includa voices (obbligatorio) e xi_api_key se non hai impostato l’header xi-api-key. Quindi invia uno o più frame con inputs: ogni elemento contiene text, voice_id e, facoltativamente, new_turn.

Il server memorizza il testo nel buffer finché non ha abbastanza contesto (circa 40 caratteri e 8 parole), quindi invia chunk audio. I campi di risposta usano lo stile snake_case (ad esempio is_final).

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())

close_socket invia il testo rimasto nel buffer, invia l’audio rimanente e poi un frame finale con is_final: true prima della chiusura della connessione. Per mantenere aperta la connessione tra una battuta e l’altra, ometti close_socket finché la sessione non termina; usa flush per forzare l’audio per buffer più brevi senza chiudere.

Esegui lo script

python text-to-dialogue-websocket.py

Dovresti ottenere un file MP3 in output/ (con il nome file dell’esempio precedente).

Note sul comportamento

Buffering

A differenza di chunk_length_schedule del WebSocket TTS, lo streaming dei dialoghi usa una soglia fissa del server (conteggio di caratteri e parole) prima del primo audio parziale. Se invii battute brevi e senti ritardi, raggruppa un po’ più testo per ogni frame inputs oppure invia flush: true per forzare la generazione senza chiudere il socket.

Turni e voci

Imposta new_turn: true quando un interlocutore termina il proprio turno, così la prosodia viene reimpostata correttamente. Anche modificare voice_id tra le voci inputs avvia un nuovo turno. Con eleven_v4_turbo, registra esattamente una voce in voices; eleven_v4 supporta fino a 10 voci registrate.

Inattività

Se il server non riceve nessun messaggio dal client per 20 secondi, la connessione termina. Invia {"keep_alive": true} per reimpostare il timer senza sintetizzare audio.

Concorrenza

Ogni connessione aperta mantiene una sessione di dialogo finché resta aperta, attinta da un pool dedicato separato dal limite di concorrenza standard del tuo piano. L’audio generato tramite la connessione non viene conteggiato nella concorrenza standard. Consulta Concorrenza di Text to Dialogue.

Allineamento

Aggiungi sync_alignment=true alla query string per ricevere oggetti alignment (array di temporizzazione in snake_case) nei chunk quando disponibili. Consulta il Riferimento API.

Passaggi successivi