Table of Contents
TL;DR: Flux TTS is generally available today on/v2/speak, over a streaming WebSocket and a batch REST endpoint. It's turn-based, and that one change moves real work off your side of the line. Your/v1/speakAura code is untouched.
Flux TTS is our text-to-speech API for developers building voice agents. It went generally available on a new endpoint, /v2/speak . This post is the orientation: what it is, what changes in your code, where it plugs in, and what it costs to run.
To start with the why, /v1/speak is request-shaped. You hand it text, and it hands you audio. That model is correct for a lot of things and it's the wrong shape for a conversation because a conversation has turns, and a turn is the unit that actually matters. A turn is what gets interrupted. A turn is what carries tone into the next one.
So /v2/speak is turn-based, and almost everything else follows from that. In practice a turn looks like this:
with client.speak.v2.connect(model="flux-alexis-en") as connection:
for token in llm_stream:
connection.send_speak(SpeakV2Speak(text=token))
connection.send_flush() # this is what ends the turnThere is no sentence detection or buffering, and audio comes back while you're still sending.
Best of all, your existing Aura code keeps working exactly as it does today. Every Aura voice is still there. You can move when you have a reason to.
Two transports, one Flux TTS contract
Flux TTS ships on both a streaming WebSocket and a batch REST call at the same /v2/speak path.
The WebSocket is the one built for agents. You open a connection, stream tokens in as your LLM produces them, and audio starts coming back before you've sent the last one. The batch endpoint is a single request that returns a finished audio file, and it's the right call for anything that is not happening live: voicemail, notifications, pre-rendered prompts.
They deliberately share a contract. model and the media settings behave the same on both, so moving a voice between your real-time path and your batch path doesn't mean re-learning anything. The conversational pieces, Flush and Interrupt and the turn lifecycle, only exist on the socket because they only mean something there. Compressed formats work the other way: mp3, opus, flac, and aac are batch-only, since the streaming socket sends raw samples with no container.
If you’re interested in learning more, take a look at the docs' batch versus streaming page if you're genuinely unsure which side a workload belongs on.
Thirty-six Flux TTS voices today, more languages later
Voices are model strings shaped flux-{voice}-{language}, like flux-alexis-en. The launch catalog is thirty-six English voices across seven accents: American, British, Irish, Australian, Indian, Singaporean, and Filipino. Twelve featured all-rounders out of a catalog of thirty-six is the subset you'll see surfaced first.
That English-only catalog matters for one thing beyond accent choice: a couple of the runtime controls are language-dependent. So today they work everywhere and that stops being automatically true when more languages arrive. The voice catalog has the full list with descriptions.
What Flux TTS lets you delete
This is the part I'd lead with if someone gave me thirty seconds. Adopting Flux TTS is mostly a subtraction.
Your text chunker. Flux TTS never needs you to find sentence boundaries or hold text back. It streams a turn's audio as tokens arrive. If you built sentence detection to feed another TTS API, it comes out.
Your reconnect-between-turns hack. The model carries its sense of how it has been speaking across the whole connection. So turn twenty sounds like turn one without you doing anything. Plenty of people reconnect between turns to stop voices drifting. There's nothing left for that code to do, and only a new connection resets it.
Your character counting. Every turn reports billable_character_count, and SessionMetadata totals the session when it ends. The server already knows whatever you were tallying locally to predict a bill.
Your own guess at what the caller heard. When somebody talks over your agent, sending Interrupt with a playback_offset gets you back text_spoken and text_remaining, so the history you hand your LLM matches what actually reached the caller's ears. That's a whole class of bug, the agent referencing a sentence nobody heard, that stops being your problem. You still track one playback counter, but what you delete is the timestamp bisection and string slicing that used to turn that counter into a cut point.
If you've solved this before, you solved it with timestamps. The standard toolkit is word or character-level timings: you bisect them against your own playback clock to find the cut point, slice the string, and hope the two stay in agreement when your audio path changes. It works and it's yours to maintain. Flux TTS does the slice server-side and hands you both halves as plain strings, which is the difference between a feature you own and a field you read.
This is the big one, so big that it will have its own post.
What's changed in Deepgram Flux TTS since Early Access
If you were on Early Access, the surface just grew considerably. At EA, /v2/speak understood three messages: Speak, Flush, and Close. Everything below landed today.
Interrupt, with the spoken-text split described above.
Configure, so you can change speaking rate mid-call without dropping the connection. speed takes seven values from 0.85 to 1.15, and the change lands at the next natural break so it doesn't sound abrupt. speed arrives on the batch endpoint at the same time.
Markup stripping. If your prompt template still emits SSML, or audio tags from ElevenLabs or Cartesia, Flux TTS strips them, speaks the clean text, and warns. It's a closed list, so your Markdown and HTML still pass through and get read aloud.
expressivity, in beta. A whole number from -2 to 2 that moves a voice off the delivery we tuned it to, set at connect time on either transport, and fixed for the life of the session. 0, the default, is the only value validated for production; moving off it can introduce hallucinations and pronunciation errors, more so the further you push it. Audition non-default values through the API or at talk.deepgram.com before you ship them.
Where Deepgram Flux TTS plugs in
The Voice Agent API. Flux TTS is now the default speak provider. Omit agent.speak from your Settings message and you get Flux TTS on flux-kit-en, where you used to get Aura's aura-asteria-en. That default flip comes with a breaking change: a session that omits agent.speak while requesting mp3, opus, flac, or aac now gets INVALID_SETTINGS instead of audio, because Flux TTS streams raw samples and has no container. Name an aura-* model explicitly if you need that config to keep working as-is. To opt into Flux TTS on purpose, set version to v2 and use a flux-* model. Mid-call, UpdateSpeak switches voices, and a turn already in flight finishes in the voice it started with. If you want a voice agent without assembling the pipeline yourself, this is the shortest path there is.
Your own pipeline. The Python, JavaScript, and Java SDKs all ship a speak.v2 client. Pair it with a streaming STT and your LLM and you have the standard three-box agent.
Frameworks. LiveKit and Pipecat both ship Flux TTS support today. LiveKit's TTSv2 class covers streaming and batch, documented at the LiveKit integration guide. Pipecat's DeepgramFluxTTSService tracks the playback position Interrupt wants, documented at the Pipecat integration guide.
Starter apps for Node, Flask, FastAPI, Django, and Java, if you'd rather read something that runs.
What Flux TTS costs you to run
Two operational facts to plan around, and the first one surprises people.
Concurrency is per plan and per region, and the regional gap is wide. On streaming, pay-as-you-go runs up to 45 concurrent connections in North America and 5 in the EU and Australia, Growth moves North America to 60 and leaves the EU and Australia at 5, and Enterprise starts at 100 in North America and 50 in each of the others. Batch REST has its own, smaller ceiling: 15 in North America on both pay-as-you-go and Growth, 5 in the EU and Australia on both, and Enterprise starts at 25 across every region. If you're deploying into Europe, check that ceiling before you size anything, because it's the number most likely to bite you in week one.
Sessions have two clocks. A connection closes after 60 seconds with no inbound client message, and any session closes at the one-hour mark. Send a WebSocket Ping between turns if your agent might sit quiet, and treat the hour as a reconnect you schedule.
Billing is per character on the text that actually gets synthesized, reported per turn and totaled per session. Markup that gets stripped is never billed, since stripping runs before the count.
How Flux TTS fails
Flux TTS is deliberately hard for developers to knock over. Most problems arrive as a Warning on a connection that stays open, which is the right design for something carrying a phone call and also means the failures you hit are quiet ones. Error always closes the connection, Warning never does, and that distinction is most of what you need.
One error worth naming here since it's new at GA: INVALID_SETTINGS fires when a Voice Agent session omits agent.speak while asking for a compressed format like mp3, opus, flac, or aac. Flux TTS is now the default and it only streams raw samples, so that combination fails instead of falling back to Aura the way it used to. Name an aura-* model explicitly if you need the old behavior (more in "Where Deepgram Flux TTS plugs in").
The ten that matter, with what each looks like in your logs, are in a future post coming soon.
Start building with Deepgram Flux TTS
Create a Deepgram account for an API key and $200 in free credit, point a WebSocket at /v2/speak, and use flux-alexis-en. The streaming quickstart is about fifteen lines.
If you’re coming from Aura, migrating from /v1/speak is mostly deleting things, which is the best kind of migration.
And if you build something with this, I'd genuinely like to see it. Flux TTS is new enough today that nobody has built the interesting things yet, and we have a way in for developers who want to go deeper than the docs. Join the community and share what you’ve built.






