Skip to content

Text-to-Speech in 2026: Latency, Voices and Cost

6 min read · updated August 3, 2026

Every vendor publishes a latency figure and none of them are measuring the same thing from the same place. Rather than repeat numbers that cannot be reproduced, this page explains what sets time-to-first-audio architecturally and gives you a script that gets the number for your region, your text and your network.

Time to first audio is the only latency number

Total synthesis time barely matters if you are streaming, because playback starts as soon as the first chunk arrives and the rest is generated while the listener is still hearing the beginning. What matters is the delay before sound starts, and the guarantee that generation stays ahead of playback.

The second condition has a name: the real-time factor, generation time divided by audio duration. An RTF of 0.3 means one second of speech takes 300 ms to synthesise, so the buffer fills three times faster than it drains and you will never stutter. An RTF above 1.0 means audio arrives slower than it plays and the listener hears gaps, no matter how quick the first chunk was.

What sets it

  • Autoregressive versus not. The current generation of expressive TTS is largely an autoregressive model over neural audio codec tokens — the same next-token loop as text, over sound. That buys naturalness and prosody and it inherits the sequential constraint, so the first chunk waits for a first forward pass over the whole input text. Non-autoregressive and older concatenative systems start faster and sound flatter.
  • Input length. The prefill is over your text. Sending a 400-word paragraph and waiting delays the first phoneme by the time it takes to read all 400 words in.
  • Whether the endpoint streams at all. A non-streaming endpoint returns a complete file; time-to-first-audio equals total synthesis time plus transfer. This is the single biggest difference between two otherwise similar products.
  • Container format. An MP3 or a WAV with a header that declares length is awkward to stream progressively. Raw PCM and Opus in an Ogg stream start playing immediately. Some APIs expose this as a format parameter and it changes the number materially.
  • Geography. A round trip from Sydney to a us-east-1 endpoint is a fixed floor of well over 200 ms that no model improvement touches.

Measuring it yourself

Time from the moment the request is written to the moment the first audio byte lands — not the last, and not the first response byte, which may be a header.

import time, statistics, httpx

TEXT = "Your booking is confirmed for Thursday at half past two."

def ttfa(url, headers, payload, n=20):
    samples = []
    with httpx.Client(timeout=30) as c:
        for _ in range(n):
            t0 = time.perf_counter()
            with c.stream("POST", url, headers=headers, json=payload) as r:
                for chunk in r.iter_bytes():
                    if chunk:                       # first audio bytes
                        samples.append((time.perf_counter() - t0) * 1000)
                        break
    samples.sort()
    return {"p50": statistics.median(samples),
            "p95": samples[int(len(samples) * 0.95) - 1]}

Report p50 and p95, never a mean — one cold start drags a mean past every request anyone experienced. Run it from where your server actually runs, use a sentence of the length your product really sends, and discard the first two calls so connection setup does not contaminate the sample. Then check the RTF separately: total elapsed time divided by the duration of the audio you got back.

For the audio side of the arithmetic, the useful constants are that uncompressed 24 kHz 16-bit mono PCM is 48 kB per second, and Opus at a speech-appropriate 24 kbps is about 3 kB per second. On a constrained mobile connection that difference is itself a latency term.

The chunking trick that beats model choice

In a pipeline where an LLM writes the text and TTS speaks it, the largest available win is not a faster synthesiser. It is not waiting for the LLM to finish. Stream the model’s output, cut it at the first sentence boundary, and send that sentence to TTS while the model is still writing the second one.

buf = ""
for delta in llm_stream:
    buf += delta
    while (cut := find_sentence_end(buf)) is not None:
        speak(buf[:cut + 1])          # queue for synthesis now
        buf = buf[cut + 1:].lstrip()
speak(buf)                            # whatever is left at the end

This converts “LLM total time plus TTS time” into “LLM time-to-first-sentence plus TTS time-to-first-audio”, which for a paragraph-length answer is commonly a saving of seconds rather than milliseconds. Two cautions: cut on sentence boundaries, not fixed character counts, or the prosody breaks audibly mid-clause; and keep the queue ordered, because two overlapping synthesis requests will return out of order under load.

The axes that are not latency

AxisDescription
voice cloning termsWhat consent and retention rules apply to a cloned voice, and whether the vendor watermarks output. This is a legal question before a technical one.
pronunciation controlWhether SSML, phoneme tags or a custom lexicon is supported. Product names and drug names are the usual reason you need it.
language and accent coverageNot the same as language coverage. A voice that speaks your language with a wrong regional accent is often worse than a plain one.
billing unitPer character, per second of output, or per token. Character billing punishes verbose text; second billing punishes slow speech rates.
determinismWhether the same text yields the same audio, which decides whether you can cache aggressively.
on-prem optionWhether the voice can run where the data is, which is often the whole decision in regulated settings.

The billing unit deserves a moment. If you are charged per character, a cache keyed on the exact string is unusually valuable, because production speech is repetitive — confirmations, error messages, menu prompts. Synthesise those once, store the audio, and your bill becomes proportional to the novel sentences only.

The other axis worth budgeting time for is text normalisation, which is where most embarrassing TTS output originates. Before anything is spoken, something must decide that “Dr Wong lives on Sunset Dr” contains two different words spelled identically, that “1/2” is a half rather than the first of February, that “£1.5m” is one and a half million pounds, and that “SQL” is either three letters or one word depending on the listener. Modern systems do most of this well and fail on exactly the strings your product cares about: order numbers, postcodes, product codes, currency in an unusual position. Test with your real data, and where a system supports SSML or a lexicon, spell out the handful of strings that matter rather than hoping — <say-as interpret-as="characters"> around an order reference is a one-line fix for a complaint that would otherwise recur forever.

Text-to-Speech in 2026: Latency, Voices and Cost · Multigrid