Getting Started with Flux TTS

Flux TTS is Deepgram’s streaming-first, voice-agent-first text-to-speech API. The /v2/speak WebSocket treats synthesis as a conversation — turn-based, interruptible, and context-aware — instead of a one-shot text-to-audio pipe.

Flux TTS brings the Flux promise to speech synthesis. Where /v1/speak renders a buffer of text into audio and discards everything else, /v2/speak is built for the realities of a voice agent pipeline: streaming text in from an LLM, speaking it to a user, getting interrupted, resuming, and doing it across dozens of turns without losing conversational coherence.

Flux TTS is perfect for: turn-based voice agents, customer service bots, phone assistants, and any application that streams LLM output to a speaker in real time.

Key benefits:

  • Streaming-first — Stream LLM tokens straight into the socket; the server handles flush placement at sentence and clause boundaries internally.
  • Turn-based lifecycle — Each agent response is a turn with a clean lifecycle (SpeechStarted → audio → SpeechMetadata), reported per turn.
  • Cross-turn voice consistency — The model persists conversational state across turns, so short responses like “Of course” keep the tone established earlier.

Planned for GA: interruption feedback (Interrupttext_spoken / text_remaining) and mid-stream Configure (speed).

New endpoint, not a replacement. /v2/speak ships alongside /v1/speak. The v1 endpoint and all Aura model strings stay available and unchanged. See When to use /v2/speak vs /v1/speak and the Migration guide.

Connection requirements

Flux TTS requires the /v2/speak endpoint. The /v1/speak endpoint does not serve Flux voices. A model is required on every connection — connections without it are rejected.

When connecting to Flux TTS, you must use:

  • Endpoint: /v2/speak (not /v1/speak)
  • Model: a Flux TTS model string, e.g. flux-alexis-en
  • Authentication: Authorization: Token YOUR_DEEPGRAM_API_KEY

WebSocket URL format:

wss://api.deepgram.com/v2/speak?model=flux-alexis-en

Connection query parameters

The streaming WebSocket produces raw audio (no container), so it accepts only the parameters below. Unknown or misspelled parameters are rejected, as are batch-only parameters (container, bit_rate, callback, callback_method, priority).

ParameterTypeDefaultDescription
modelstringRequired. The Flux TTS model to use (e.g. flux-alexis-en). Must be a flux-* model; an Aura model returns an endpoint-specific error.
encodingenumlinear16Raw audio encoding: linear16, mulaw, or alaw.
sample_rateintegermodel nativeOutput sample rate. With linear16: 8000, 16000, 24000, 32000, 44100, 48000. With mulaw/alaw: 8000 or 16000.
mip_opt_outbooleanfalseOpt out of the Model Improvement Program.
tagstringCustom tag(s) for request tracking. Repeatable.

Compressed and containerized encodings are batch-only. opus, mp3, flac, and aac (and the container / bit_rate parameters) are available on the batch REST transport, not on the streaming WebSocket, which emits raw linear16/mulaw/alaw.

Streaming happens on its own. You don’t chunk text or place flush points — the server starts generating and streaming a turn’s audio as soon as it has enough text, and prosody carries across turns automatically. You own turn boundaries (Flush); everything else is handled for you.

Model naming

Flux TTS model strings follow the format flux-{voice}-{language}, mirroring Flux STT:

flux-alexis-en # English voice

English voices ship first; multilingual voices (flux-{voice}-multi) come later. See Voices & Languages for the current catalog. As with Flux STT, model generations roll forward behind a stable model string — there is no version segment in the customer-facing name.

The conversation loop

A Flux TTS session is a sequence of turns. You stream text into a turn with Speak messages, then end the turn with Flush when the agent’s response is complete. The server assigns a speech_id to each turn and reports lifecycle events around it.

Build a basic agent loop

The core pattern is: stream LLM tokens in as they arrive, then flush at the end of the turn.

SDK support is live. The Python (deepgram-sdk) and JavaScript (@deepgram/sdk) SDKs expose a speak.v2 client for /v2/speak. For a full runnable integration, start from the template apps. The Direct WebSocket path is available for languages without SDK support yet.

1import threading
2
3from deepgram import DeepgramClient
4from deepgram.core.events import EventType
5from deepgram.speak.v2.types import SpeakV2Speak
6
7# Reads DEEPGRAM_API_KEY from the environment.
8client = DeepgramClient()
9
10with client.speak.v2.connect(model="flux-alexis-en") as connection:
11 # Audio arrives as binary frames; control messages (SpeechStarted,
12 # SpeechMetadata, ...) arrive as JSON.
13 connection.on(EventType.MESSAGE, handle_message)
14 connection.on(EventType.ERROR, handle_error)
15
16 # start_listening() blocks, so run it on a background thread.
17 threading.Thread(target=connection.start_listening, daemon=True).start()
18
19 # Stream LLM tokens into the active turn as they arrive.
20 for token in llm.stream(prompt):
21 connection.send_speak(SpeakV2Speak(text=token))
22
23 # Flush ends the turn: the server generates the remaining audio
24 # and emits SpeechMetadata.
25 connection.send_flush()
26 connection.send_close()

A note on streaming text

Send plain text. The server applies text normalization (e.g. number and date expansion) before synthesis, but it does not reorder your content or insert or strip whitespace between successive Speak messages — so you can stream raw LLM tokens without coordinating chunk boundaries.

Insert a space between distinct generations. Because text is concatenated verbatim, sending "Hello world." immediately followed by "How are you?" is synthesized as "Hello world.How are you?", which can trigger sentence-boundary artifacts. When you stitch together separate LLM responses (for example, a reply, then a tool-call result, then another reply), insert a single space — or the appropriate separator for non-whitespace languages — between them.

When to use /v2/speak vs /v1/speak

/v1/speak (Aura)/v2/speak (Flux TTS)
Mental modelText buffer → audio streamStreaming-first, turn-based conversation
FlushingManual + customer-facing togglesServer-managed; manual Flush ends the turn
InterruptionClear discards the buffer, no feedbackInterrupt with spoken-text feedback (planned for GA)
Cross-turn contextNoneModel state persists across turns
Mid-stream controlFixed at connectionConfigure speed mid-session (planned for GA)
VoicesAura 1 / Aura 2Flux TTS voice portfolio

Build new voice-agent integrations on /v2/speak. Stay on /v1/speak if you depend on the legacy manual-flush toggles, or if you are using Aura voices and don’t yet need the conversational surface. See the Migration guide for a step-by-step path.

Streaming vs. batch

/v2/speak is exposed over two transports against the same Flux voices:

  • Streaming (WebSocket)wss://api.deepgram.com/v2/speak. The conversational path covered throughout these docs: text streams in, audio streams back, turns are interruptible. Use it for live voice agents that need low time-to-first-byte and barge-in.
  • Batch (REST)POST https://api.deepgram.com/v2/speak. Submit a complete block of text, receive the full audio in one response. Use it for pre-generating fixed audio (IVR prompts, notifications, audiobook lines) where the whole text is known up front and interruption isn’t needed.
Batch request
$curl "https://api.deepgram.com/v2/speak?model=flux-alexis-en" \
> -H "Authorization: Token YOUR_DEEPGRAM_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{ "text": "Your appointment is confirmed for 3pm tomorrow." }' \
> --output audio.mp3

The batch path shares model, media-output settings, and inline pronunciations with the streaming surface, and adds containerized/compressed encodings (mp3 default, plus opus/flac/aac with container/bit_rate). Conversational constructs (Flush, speech_id, lifecycle events) do not apply to batch; per-request telemetry is returned as response headers, mirroring Aura’s REST conventions.

What’s next?