On October 1, 2026, OpenAI told developers that tts-1, tts-1-hd and gpt-4o-mini-tts are deprecated and will be removed from the API on January 6, 2027. The recommended replacement, gpt-realtime-2.1-mini, isn't a supported model for the /v1/audio/speech endpoint at all. If your phone agent calls that endpoint, you're doing a migration this quarter whether you planned one or not.
The rest of the field moved too: Cartesia shipped Sonic 3.6, Deepgram put Flux TTS on a new /v2/speak endpoint, ElevenLabs has Eleven v4 and v4 Turbo, and on October 27 AssemblyAI launched AssemblyAI-TTS-1. It gets the same treatment as every other entry.
Here's the thing. Nearly every TTS comparison judges voices on full-bandwidth audio through good headphones. Your caller hears 8 kHz G.711 through a phone earpiece, often in a car. Some differences that sound huge in a demo vanish on that line, and other failures get much worse.
So this piece judges TTS APIs on the phone line.
What the phone line does to your TTS
Twilio's Media Streams docs are blunt about it: the audio you send back "must be encoded audio/x-mulaw with a sample rate of 8000." Carriers in North America and Japan use G.711 μ-law, and most of the rest of the world uses A-law. At 8,000 samples per second nothing above 4 kHz survives, and companding squeezes each sample into 8 bits.
That strips out much of what makes a premium voice sound premium, and two voices that differ clearly on studio monitors can be hard to tell apart. Other problems get worse:
- Entities. Sibilants and fricatives live largely above 4 kHz, so "S" and "F" get hard to tell apart when an email address is spelled out.
- Time to first audio. On a call, silence is a bug, and the caller fills it by talking over you.
- Transcoding. If the API only gives you 24 kHz PCM or MP3, you resample and encode μ-law yourself. Every hop is a chance for clipping, aliasing or a sample-rate mismatch.
- Barge-in. When the caller interrupts, you stop the TTS, flush the carrier's buffer (Twilio has a
clearmessage), and need to know how much of the sentence they heard.
How I grouped them
There's no single "best." The criterion I used is how each API is built for a live call:
- Streaming APIs built for voice agents. AssemblyAI, ElevenLabs, Cartesia, Deepgram and Rime. AssemblyAI comes first because it's the one built around the constraint most phone agents hit first: concurrency at call volume. The rest are ordered by language coverage, widest first, because language is the one constraint you can't engineer around.
- Cloud-platform TTS. Azure and Google. Huge language lists and enterprise quotas, but streaming and telephony take more plumbing.
- On the way out. OpenAI's speech endpoint.
Everything below was checked against each vendor's own docs or pricing page on October 28, 2026. Recheck before you commit.
The comparison
| API (model) | Native μ-law / A-law | Streaming transport | Pricing shape | Concurrency model | Voice cloning | Languages | On the phone, watch for |
|---|---|---|---|---|---|---|---|
| AssemblyAI (AssemblyAI-TTS-1) | Both (pcm_mulaw, pcm_alaw), any supported rate including 8 kHz | WebSocket, HTTP, and an OpenAI-compatible route | $15 per 1M input characters | Unlimited concurrency; only new sessions per minute are rate-limited | Instant, in the dashboard | 6 | Brand new (launched Oct 27, 2026); six languages; no SSML or custom lexicon |
| ElevenLabs (Eleven v4 Turbo, Flash v2.5) | Both, at 8 kHz (ulaw_8000, alaw_8000) | WebSocket (standard, multi-context, Text to Dialogue) | Per 1K characters by model; $0.04/1K for v4 Turbo and Flash | Plan-capped concurrent requests, queued past the cap; Enterprise "elevated" | Instant and Professional | 90+ (v4 family); 32 (Flash v2.5) | Plan caps on concurrency; v4 Turbo runs on the Text to Dialogue socket, where each open connection holds a session |
| Cartesia (Sonic 3.6) | Both (pcm_mulaw, pcm_alaw, 8 kHz) | WebSocket with contexts and continuations; also bytes and SSE | Subscription credits, about 1 credit per character | Plan-capped: 2 to 15 concurrent TTS requests on self-serve plans, custom on Enterprise | Instant and Pro (30+ min of audio) | 44 | Low self-serve concurrency; the sonic-3.6 alias moves, so pin a dated snapshot |
| Deepgram (Flux TTS) | Both, at 8 or 16 kHz on the streaming socket | WebSocket /v2/speak, plus batch REST | Per 1K characters; $0.045/1K pay-as-you-go | Per-region caps: up to 45 streaming in North America on pay-as-you-go, 5 in EU, AU and IN | Not in the Flux TTS docs | English plus 41 others, most in Early Access | Early Access languages read numbers and dates as written |
| Rime (Coda, Mist v3) | μ-law (audio/pcmu); no A-law in the Coda socket's format list | WebSocket v1 and streaming HTTP; on-prem engines | Per minute of audio (about 1K characters/min): Coda $0.050, Mist v3 $0.030 on Flex | Plan limits; "unlimited" TTS concurrency on Enterprise | Enterprise clones from 30 to 60+ min of recordings | Coda 10; Mist v3 4 | Omit modelId and you get Mist v3, not Coda |
| Azure AI Speech | Both (raw-8khz-8bit-mono-mulaw / alaw) | Speech SDK (WebSocket) or REST | Per 1M characters by voice class; 0.5M free per month | 30 transactions/sec by default on S0, adjustable to 1,000 | Professional and personal voice, limited access | 100+ languages and locales | Limits counted in transactions, not calls |
| Google Cloud TTS (Chirp 3: HD) | Both (MULAW, ALAW), streaming and batch | gRPC bidirectional streaming (Chirp 3: HD only); no WebSocket | Per character; $30/1M for Chirp 3: HD after 1M free per month | Per-project quotas: 100 concurrent streaming sessions, 200 Chirp 3 requests/min | Instant Custom Voice, allow-listed, $60/1M | 53 locales | You need a gRPC bridge from your carrier's WebSocket |
OpenAI (gpt-4o-mini-tts) | Neither: MP3, Opus, AAC, FLAC, WAV, or 24 kHz PCM | HTTP streaming on /v1/audio/speech | Tokens: $0.60/1M text in, $12/1M audio out | Account rate limits (not covered here) | Custom voices from a consent recording, with eligibility rules | Follows Whisper's list; voices optimized for English | Shuts down January 6, 2027; you transcode to μ-law yourself |
Look at the first column. Seven of the eight return G.711 natively, so "does it speak telephony" is no longer much of a filter. The concurrency column is where the real differences hide, and it's the one most comparisons leave out.
Streaming APIs built for voice agents
AssemblyAI
Good at: concurrency, and being built for this exact deployment. AssemblyAI-TTS-1 was trained on millions of hours of audio, including real conversational data. It returns pcm_mulaw or pcm_alaw at whatever rate you ask for, with the server resampling before it encodes. The WebSocket takes streamed LLM text, returns per-word timings, and has a cancel() for barge-in. There's also an HTTP API, an OpenAI-compatible route, US and EU data zones, LiveKit and Pipecat plugins, and instant cloning in the dashboard. Concurrency is unlimited: the rate limit counts new sessions per minute, not sessions open at once. We'd describe it as frontier-level quality, faster and cheaper than other production voice agent TTS models. It costs $15 per 1M input characters (pricing).
Where it breaks on the phone: it launched October 27, so there's no long track record. Six languages (English, Spanish, French, German, Italian, Portuguese) is the shortest list here, and there's no language detection. There's no SSML or custom lexicon either. Sessions last at most an hour and close after two minutes idle without a keep-alive. Pipecat's AssemblyAI TTS service shipped in pipecat-ai 1.15.0 (install pipecat-ai[assemblyai]).
Pick it when your languages are covered, call volume is spiky or large enough that concurrency caps would hurt, or you want STT and TTS on one API key.
ElevenLabs
Good at: voice range and cloning. The v4 family covers 90+ languages. Flash v2.5 is the fast, cheap option, and the docs quote a model latency of about 75 ms, excluding application and network latency. Instant and Professional cloning are both mature, and both G.711 formats are first-class outputs.
Where it breaks on the phone: concurrency is tied to your plan. The published table runs from 4 concurrent Flash requests on Free to 30 on Scale and Business, and requests past the limit queue. On the standard TTS WebSocket, only time spent generating counts against the limit, which helps. But Eleven v4 Turbo is served on the Text to Dialogue WebSocket, where each open connection reserves a session for as long as it stays open. On a phone agent that means one session per live call.
Pick it when you need many languages, a cloned brand voice, or the most expressive delivery, and you can size your plan to your peak call volume.
Cartesia
Good at: latency-focused engineering with the telephony details documented properly. The output-format docs pair pcm_mulaw and pcm_alaw at 8000 Hz with the regions that use them. The WebSocket supports contexts and continuations, so you can stream LLM tokens into one utterance. Sonic 3.6 covers 44 languages, and the docs say it handles confirmation codes and heteronyms without preprocessing.
Where it breaks on the phone: self-serve concurrency is low. The pricing page lists 2 to 15 concurrent TTS requests across self-serve plans: fine for a pilot, a hard ceiling for a contact center. Also, the sonic-3.6 ID moves to the newest snapshot, so pin sonic-3.6-2026-08-27 if you run evals.
Pick it when latency is your top constraint and your call volume fits a plan, or you're ready to negotiate Enterprise.
Deepgram (Flux TTS)
Good at: barge-in. Flux TTS treats synthesis as a turn-based conversation. When you send Interrupt, the server reports text_spoken and text_remaining, so your LLM context matches what the caller actually heard. That's the most explicit barge-in contract in this list. The streaming socket returns mulaw or alaw at 8 or 16 kHz.
Where it breaks on the phone: two things to read carefully. First, the docs say Early Access languages "do not have text normalization yet: numbers, dates and abbreviations are read as written." Ten languages have normalization; for the rest, write entities out in words yourself. Second, the rate-limit page caps Flux TTS streaming at 5 concurrent requests on the EU, Australia and India endpoints, versus 45 in North America, on pay-as-you-go. If you need EU data residency, plan around that.
Pick it when you already run Deepgram STT, your languages have normalization, and accurate barge-in bookkeeping matters more to you than voice cloning.
Rime
Good at: pronunciation control for entity-heavy calls. Coda takes a custom lexicon of X-SAMPA pronunciations in six languages, and both models support a spell() function for codes, IDs and acronyms. Rime also documents on-prem engines, which matters when your network hop is your latency budget. Pricing is per minute of generated audio, which maps neatly onto per-call economics.
Where it breaks on the phone: the Coda WebSocket's format table lists G.711 μ-law (audio/pcmu) but not A-law, so outside μ-law regions you'll transcode yourself. Language coverage is narrow: 10 languages for Coda and 4 for Mist v3, with most voices serving a single language. And the docs warn that a request without modelId, or with one the API doesn't recognize, gets Mist v3. "Coda is never served by default." Set it explicitly.
Pick it when your calls are full of brand names, SKUs and confirmation codes, you're in a μ-law region, or you need on-prem.
Cloud-platform TTS
Azure AI Speech
Good at: breadth and enterprise plumbing: 100+ languages and locales, native μ-law and A-law, SSML, and quotas that go from 30 to 1,000 transactions per second on request.
Where it breaks on the phone: limits are counted in transactions, not calls. A chatty agent that sends one request per sentence burns through TPS faster than you'd expect. Custom and personal voice are limited access, so budget time to apply.
Pick it when you need a language nobody else covers or you're already standardized on Azure.
Google Cloud TTS (Chirp 3: HD)
Good at: quality and locale coverage on a cloud you may already use. Chirp 3: HD covers 53 locales, returns MULAW or ALAW on both streaming and batch, and supports custom pronunciations in most locales. Default quota is 100 concurrent streaming sessions per project.
Where it breaks on the phone: streaming only works with Chirp 3: HD voices, and it runs over gRPC bidirectional streaming. Your carrier hands you a WebSocket, so you'll build a bridge. Instant Custom Voice is allow-listed and costs twice the Chirp 3: HD rate.
Pick it when you're on GCP, you need its locale list, and gRPC doesn't scare your team.
On the way out
OpenAI
Good at: simplicity. Send text, pick one of 11 voices, steer delivery with an instructions prompt, and get audio back.
Where it breaks on the phone: the speech endpoint returns no G.711, so you transcode 24 kHz PCM to μ-law yourself. More importantly, these models shut down on January 6, 2027. The replacement is a Realtime API session, which is a different architecture from a TTS endpoint you call after your own LLM.
Pick it when you're prototyping something that won't be running in January.
How to test what callers hear
Synthesize the sentences your agent actually says, push them through a phone codec, and see what a listener can still recover. The script below does that with one deliberately nasty sentence full of entities. It produces three versions: the vendor's native 24 kHz audio, that audio forced through 8 kHz μ-law by ffmpeg (what happens when you transcode), and the vendor's own native μ-law. Then it transcribes each one and counts which entities survived.
import os import re import subprocess import assemblyai as aai aai.settings.api_key = os.environ["ASSEMBLYAI_API_KEY"] TEXT = ( "Hi Siobhan, your order 4471-B ships Thursday, March 3rd, and the " "$1,249.50 refund goes to the card ending 0062. Your confirmation code " "is B7X-29Q. Questions? Email siobhan.nguyen@example.com or call " "1-800-555-0199." ) # What the caller must hear correctly, in the loosest form we'll accept. ENTITIES = ["Siobhan", "4471B", "March 3", "1249.50", "0062", "B7X29Q", "siobhan.nguyen@example.com", "18005550199"] def norm(s): return re.sub(r"[^a-z0-9]", "", s.lower()) def synthesize(path, **fmt): # Swap this function for any vendor's SDK call that writes a WAV file. tts = aai.TextToSpeech() audio = tts.synthesize(TEXT, aai.TTSConfig( voice_id="49c443a4-8a1d-5f7e-b70b-98bdbd9823c3", # Audrey container=aai.TTSContainer.wav, **fmt, )).audio with open(path, "wb") as f: f.write(audio) def phone_line(src, dst): # What a carrier does to studio audio: 8 kHz, mono, G.711 mu-law. subprocess.run(["ffmpeg", "-y", "-loglevel", "error", "-i", src, "-ar", "8000", "-ac", "1", "-c:a", "pcm_mulaw", dst], check=True) def score(path): # Keep the listener constant across vendors: same model, no keyterms. config = aai.TranscriptionConfig(speech_models=["universal-3-5-pro"]) text = aai.Transcriber(config=config).transcribe(path).text or "" heard = norm(text) missed = [e for e in ENTITIES if norm(e) not in heard] print(f"{path}: {len(ENTITIES) - len(missed)}/{len(ENTITIES)} entities") print(f" transcript: {text}") if missed: print(f" missed: {missed}") synthesize("studio.wav") # native 24 kHz PCM phone_line("studio.wav", "transcoded.wav") # your own transcode synthesize("native_ulaw.wav", # vendor-side 8 kHz mu-law encoding=aai.TTSEncoding.pcm_mulaw, sample_rate=8000) for f in ["studio.wav", "transcoded.wav", "native_ulaw.wav"]: score(f) You need pip install -U assemblyai (1.8.2 or later), ffmpeg on your path, and an API key. A few notes so the test means something:
- Swap the synthesizer and keep the listener. Replace
synthesize()with each vendor's call and keep the STT fixed. For a neutral judge, use an STT from a vendor whose TTS isn't in the test. - Leave the STT unprompted. A listener primed with "Siobhan" hears Siobhan whether the TTS said it or not.
- Use more than one sentence. Pull your 50 ugliest real prompts from logs. One sentence is a smoke test.
- Listen to every miss. The script tells you where to listen, not who's wrong.
- Compare the transcoded and native rows. If a vendor's native μ-law scores worse than your
ffmpegtranscode of their PCM, or the reverse, you've learned which path to ship.
Then measure time to first audio from your own region, at your real concurrency, over your production transport. Time to first byte at the API isn't time to first audio at the caller's ear.
What benchmarks and leaderboards miss
Leaderboards are useful, but they measure a different product from the one your caller uses.
- They listen at full bandwidth. Preference arenas play full-bandwidth clips on whatever the listener is wearing. A voice that wins on breathy realism can lose that edge entirely at 8 kHz, and the leaderboard can't tell you which ones do.
- They read clean prose. Benchmark sentences rarely contain "B7X-29Q" or an email address. Agent traffic is mostly entities, and normalization varies by vendor and even by language.
- Latency figures exclude what you'll pay. ElevenLabs, to its credit, footnotes that its model latencies exclude application and network latency. Rime's docs estimate 25 to 50 ms of network round trip from most of the continental US. Vendor numbers are typically measured at low concurrency in a good region. Yours won't be.
- Nobody benchmarks the cap. A model that's fast at concurrency 1 and queues your 16th call is slow at 4 p.m. on a Monday. Limits in this list run from single digits to unlimited, and that decides more production outcomes than a few points of preference score.
- Nobody benchmarks the interrupt. What happens when the caller cuts in? Deepgram's
text_spokenreport, word timings from AssemblyAI and Rime, and contexts in ElevenLabs and Cartesia all answer that differently. A leaderboard has no column for it.
Vendors are still working on this path, too. Deepgram's October 20 self-hosted release notes list "improved audio quality for 8 kHz output, including Flux TTS." So 8 kHz quality can change between releases. Retest when you upgrade.
The point
On a demo page, you'll struggle to pick a winner among these voices. On the phone, you won't. The differences that decide whether your agent finishes the call are boring ones: whether "Siobhan" survives μ-law, whether call 16 waits in a queue, whether the API knows where it was interrupted, and whether the model will still exist in January. Pick two vendors from the table, run the script on your own worst sentences, and trust what comes back over the phone line more than any list, including this one.
Editor's note: This article is paid content. HackerNoon’s editorial team has reviewed it for clarity and quality standards, but the views, claims, benchmarks, and comparisons expressed are solely those of the sponsor, and HackerNoon assumes no responsibility for third-party assertions contained in sponsored content.

