Transmita diálogos em tempo real

Este guia mostra como transmitir áudio de diálogo do Eleven v3 em tempo real pelo WebSocket de Text to Dialogue.

O WebSocket de Text to Dialogue (/v1/text-to-dialogue/stream-input) mantém uma única conexão aberta enquanto você envia linhas de diálogo e recebe trechos de áudio codificados em base64. Ele é destinado apenas aos modelos de diálogo Eleven v3 e Eleven v4 (model_id precisa começar com eleven_v3 ou eleven_v4).

Este guia aborda o WebSocket de Text to Dialogue. Para modelos de TTS Flash, Multilingual v2 ou outros que não sejam v3, use o WebSocket de TTS em tempo real. Para ver um resumo comparativo dos dois protocolos, consulte WebSockets de Text to Speech vs. Text to Dialogue.

Requisitos

  • Uma conta da ElevenLabs com uma chave de API (autenticação).
  • A chave de API precisa ter permissões de Text to Speech.
  • Python ou Node.js instalado na sua máquina.

Configuração

pip install python-dotenv websockets

Crie um arquivo .env:

.env
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here

Escolha um ID de voz na Voice Library. Os exemplos abaixo usam eleven_v4_turbo, que permite uma voz registrada por conexão.

Abra o WebSocket

Conecte-se a wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input com parâmetros de consulta como model_id e output_format. Você pode enviar a chave de API no cabeçalho xi-api-key ou na primeira mensagem JSON (mostrada aqui no corpo para manter um único padrão entre linguagens).

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

Registre vozes e transmita texto

Envie uma primeira mensagem que inclua voices (obrigatório) e xi_api_key caso você não tenha definido o cabeçalho xi-api-key. Depois, envie um ou mais frames com inputs: cada item tem text, voice_id e new_turn opcional.

O servidor armazena o texto em buffer até ter contexto suficiente (cerca de 40 caracteres e 8 palavras) e então envia trechos de audio. Os campos de resposta usam snake_case (por exemplo, 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 envia qualquer texto armazenado em buffer, transmite o áudio restante e, em seguida, um frame final com is_final: true antes de a conexão ser fechada. Para manter a conexão aberta entre as linhas, omita close_socket até o fim da sessão; use flush para forçar o áudio de buffers menores sem fechar.

Execute o script

python text-to-dialogue-websocket.py

Você deve obter um arquivo MP3 em output/ (com o nome de arquivo do exemplo acima).

Observações sobre o comportamento

Buffering

Ao contrário de chunk_length_schedule do WebSocket de TTS, a transmissão de diálogos usa um limite fixo do servidor (contagem de caracteres e palavras) antes do primeiro áudio parcial. Se você enviar linhas curtas e notar atrasos, agrupe um pouco mais de texto por frame de inputs ou envie flush: true para forçar a geração sem fechar o socket.

Turnos e vozes

Defina new_turn: true quando um locutor terminar um turno para que a prosódia seja redefinida corretamente. Alterar voice_id entre entradas de inputs também inicia um novo turno. Com eleven_v4_turbo, registre exatamente uma voz em voices; eleven_v4 oferece suporte a até 10 vozes registradas.

Inatividade

Se o servidor não receber nenhuma mensagem do cliente por 20 segundos, a conexão será encerrada. Envie {"keep_alive": true} para redefinir o temporizador sem sintetizar áudio.

Concorrência

Cada conexão aberta mantém uma sessão de diálogo enquanto permanecer aberta, extraída de um conjunto dedicado separado do limite padrão de concorrência do seu plano. O áudio gerado pela conexão não conta para a concorrência padrão. Consulte concorrência de Text to Dialogue.

Alinhamento

Adicione sync_alignment=true à string de consulta para receber objetos alignment (arrays de tempo em snake_case) nos trechos quando disponíveis. Consulte a referência da API.

Próximas etapas