Stream dialogue in real-time
Stream dialogue in real-time
The Text to Dialogue WebSocket API is rolling out to customers gradually over the coming weeks. You may not have access immediately.
This feature is currently offered as a Beta Service. By enabling access, you agree to the Beta Services Addendum and acknowledge that usage will be billed at $70/1M chars starting on your next billing date, unless otherwise agreed with your account owner.
The Text to Dialogue WebSocket (/v1/text-to-dialogue/stream-input) keeps a single connection open while you send dialogue lines and receive base64-encoded audio chunks. It is intended for Eleven v3 dialogue models only (model_id must start with eleven_v3).
This guide covers the Text to Dialogue WebSocket. For Flash, Multilingual v2, or other non-v3 TTS models, use the Realtime TTS WebSocket. For a side-by-side summary of both protocols, see Text to Speech vs Text to Dialogue WebSockets.
Requirements
- An ElevenLabs account with an API key (authentication).
- The API key must have
Text to Speechpermissions. - Workspace level access to the Text to Dialogue WebSocket (product feature)
- Python or Node.js installed on your machine.
Setup
Create a .env file:
Pick a voice ID from the Voice Library. The examples below use eleven_v3_conversational, which allows one registered voice per connection.
Open the WebSocket
Connect to wss://api.elevenlabs.io/v1/text-to-dialogue/stream-input with query parameters such as model_id and output_format. You can send the API key in the xi-api-key header or in the first JSON message (shown here in the body for a single pattern across languages).
Register voices and stream text
Send a first message that includes voices (required) and xi_api_key if you did not set the xi-api-key header. Then send one or more frames with inputs: each item has text, voice_id, and optional new_turn.
The server buffers text until it has enough context (about 40 characters and 8 words), then emits audio chunks. Response fields use snake_case (for example is_final).
close_socket flushes any buffered text, sends remaining audio, then a final frame with is_final: true before the connection closes. To keep the connection open between lines, omit close_socket until the session ends; use flush to force audio for shorter buffers without closing.
Run the script
You should get an MP3 file under output/ (filename as in the example above).
Behaviour notes
Buffering
Unlike the TTS WebSocket chunk_length_schedule, dialogue streaming uses a fixed server threshold (character and word count) before the first partial audio. If you send short lines and hear delays, batch slightly more text per inputs frame or send flush: true to force generation without closing the socket.
Turns and voices
Set new_turn: true when a speaker finishes a turn so prosody resets cleanly. Changing voice_id between inputs entries also starts a new turn. With eleven_v3_conversational, register exactly one voice in voices; eleven_v3 supports up to 10 registered voices.
Inactivity
If the server receives no client message for 20 seconds, the connection ends. Send {"keep_alive": true} to reset the timer without synthesizing audio.
Alignment
Add sync_alignment=true to the query string to receive alignment objects (snake_case timing arrays) on chunks when available. See the API reference.
Next steps
Choose the right WebSocket and compare message shapes.
Query parameters, message schemas, and examples.
When full request text is available without a WebSocket.
Single-voice non-v3 streaming over WebSockets.