Skip to navigation

Latency

Simba 3.2 reached first audible audio in a median of 47 ms over the WebSocket input stream and 64 ms over the HTTP stream from US East on 9 Oct 2026, the lowest of the 13 endpoints we timed there. What adds to it on your side, and how to measure your own.

On 9 Oct 2026, timed from a client in US East over warm connections, SpeechifyAI’s simba-3.2 reached first audible audio in a median (p50) of 47 ms over the WebSocket input stream and 64 ms over the HTTP stream, the lowest of the 13 endpoints we timed from US East that day. From Zurich it was not the lowest: ElevenLabs Flash v2.5 over HTTP reached first audible audio in 142 ms, against 145 ms for our WebSocket input stream and 153 ms for our HTTP stream. First audible audio is the wait a listener hears, timed by our own open script to the first audible sound in the decoded audio. Our server-side first byte on the HTTP stream, 56 ms p50 and 102 ms p90 on production traffic on 15 Sep 2026, is lower than that stream’s 64 ms because it stops inside our API, before the network between you and US East and before any silence at the start of the audio. The method, every endpoint’s numbers, where other providers were faster, every request and the script are in the round’s write-up. This page explains what each number counts, what adds to the wait on your side, and how to measure it from where your code runs.

Measured numbers

Metricp50p90Measured fromDatePath
First audible audio47 ms58 msA client in US East, warm connection9 Oct 2026WebSocket input stream, GET /v1/audio/stream/ws
First audible audio64 ms77 msA client in US East, warm connection9 Oct 2026HTTP stream, POST /v1/audio/stream
First audible audio145 ms160 msA client in Zurich, warm connection9 Oct 2026WebSocket input stream, GET /v1/audio/stream/ws
First audible audio153 ms168 msA client in Zurich, warm connection9 Oct 2026HTTP stream, POST /v1/audio/stream
First byte, server-side56 ms102 msInside our API, production traffic in US East15 Sep 2026POST /v1/audio/stream

Every row is simba-3.2, and every value is a measured percentile, not a guarantee. The first-audible rows come from our 9 Oct 2026 round, which timed 13 streaming endpoints from six providers with one open script; the first-byte row comes from production customer traffic.

First byte, first audible audio, total generation time

TermDefinition
Time to first byteFrom sending the request to receiving the first byte of audio. Our server-side first byte above is the part of it spent inside our API.
Time to first audible audioTime to first byte, plus any silence at the start of the audio: when the first sound a listener can hear arrives. Your decoder and player add their own start-up time before it plays.
Total generation timeFrom sending the request to receiving the last byte of audio. It grows with the length of the text.

Generated speech can begin with a short silence, and its length varies with the voice and the text. In the 9 Oct 2026 round, simba-3.2 opened with a median of 10 ms of silence, and no endpoint we timed opened with less, from either place. On POST /v1/audio/speech, time to first byte and total generation time are the same, because the response is sent once the whole clip exists.

How we measure

Both measurements report percentiles, not averages: p50 is the median request, and p90 is the request slower than 9 in 10. A few slow outliers move an average, not a median.

First audible audio: our 9 Oct 2026 round

  • Where from. Two Google Cloud VMs at the same time, one in us-east4-a in Ashburn, Virginia, and one in europe-west6-a in Zurich.
  • What was timed. 13 streaming endpoints from six providers, each reading the same 12 sentences of 76 to 102 characters as 24 kHz 16-bit mono PCM, from one Python client, in a shuffled order so every provider shared each minute. simba-3.2 spoke with the voice geffen_32.
  • When the clock stops. At the first 10 ms window of decoded audio whose RMS level passes -45 dBFS: the first audio chunk’s arrival plus the silence before that window, or the arrival of the chunk carrying it if that is later.
  • Warm and cold. The figures above come from 60 requests per endpoint over one kept-open connection, after 2 discarded warm-up requests. With a new connection opened inside the clock, 12 requests per endpoint, simba-3.2 read 74 ms over the WebSocket input stream and 75 ms over the HTTP stream from US East.
  • Everything else. Every endpoint’s tables, warm and cold, every column where another provider was faster, every request and the script to rerun it are in the round’s write-up.

First byte: production traffic

  • What is timed. Every production request to POST /v1/audio/stream records, inside our API, the time from admitting the request (after authentication and rate limits) to writing the first audio byte to the response.
  • Which requests. Successful streaming requests from real customer traffic, not a synthetic test, split by model. The figures above were read from that traffic on 15 Sep 2026. They cover every text and voice our customers sent, so they do not compare one to one with the round’s 12 sentences.
  • Where. Our US East serving path, which served every request to api.speechify.ai in September 2026. The clock stops when the first byte leaves our API, so the network between you and US East, the handshakes of a new connection, silence at the start of the audio and your player’s buffer are all outside it.

Independent measurements

Two benchmarks we do not run also time simba-3.2, from their own runners to the first audible sample. Coval measured a 109 ms median time to first audio over the 24 hours to 9 Oct 2026 11:00 UTC, and Voice Arena read 123 ms p50 for its “Simba 3.2 Real-time” row on its US English board on 16 Oct 2026. Both sit above the 56 ms first byte because they include the network between their runner and US East and any silence at the start of the audio, which our first byte does not count. Each is that benchmark’s own reading on that date, not our measurement, and the boards change as they re-run. Our low-latency TTS guide links the reviewed, dated snapshot behind each figure.

What adds latency on your side, and how to cut it

FactorEffectWhat to do
Batch instead of streamingPOST /v1/audio/speech responds once the whole clip is generated, so the first audio waits for the last.Use POST /v1/audio/stream for anything played while it generates. Keep the speech endpoint for files you store.
ModelMedian server-side first byte was 56 ms on simba-3.2 and 161 ms on simba-3.0, on the same production path on 15 Sep 2026.Set model: "simba-3.2" for English. The API uses simba-3.0 when model is omitted. See Models.
Distance to US EastEvery request pays at least one network round trip to US East. In our September 2026 measurements that round trip was about 35 ms from the central US and about 100 ms from central Europe. From Zurich on 9 Oct 2026, our server’s share of the HTTP stream’s 143 ms median first byte was 39 ms, by its Server-Timing header, and the rest was the network.If the code that calls the API runs in a cloud, run it in or near US East.
A new connection per requestA DNS lookup and the TCP and TLS handshakes run before the request is sent. In our 9 Oct 2026 round from US East, a new connection per request moved simba-3.2’s median first audible audio over HTTP from 64 ms to 75 ms.Create one HTTP client and reuse it. Open the connection at startup so a user’s first request does not pay for it. HTTP/2 lets concurrent streams share one connection.
Compressed outputMP3, Ogg/Opus and AAC are encoded as the audio is generated and decoded by your player, and decoded MP3 starts with a short encoder delay. audio/pcm at 24 kHz is the model’s native output and needs no encoding step.Use Accept: audio/pcm when you play or process raw samples. Use a compressed format when bandwidth or file size matters more. See Audio formats.
Waiting for the full textSynthesis cannot start before the text arrives. An LLM reply sent in one request waits for the LLM’s last token.Send the text as it arrives over the WebSocket input stream, which speaks each sentence once the next one starts, and send input.flush at the end of a reply so its last sentence is spoken too. Over HTTP, send each complete sentence as soon as it exists and play the streams in order. Split only at sentence ends: splitting inside a sentence changes how it sounds. Text you already have goes in one request, up to 20,000 characters.
Player start-upA player that fills a buffer before it starts adds that buffer to time to first audible audio.Start playback on the first chunk. With PCM, write samples to the audio device as they arrive.

Measure it yourself

Time the first chunk of a streaming response from where your code runs, and read the Server-Timing header on the same response. Its ttfb is our share of that request’s wait, from the request reaching our API to the first audio byte, and model is the model’s own time to first audio. Your first-chunk time minus ttfb is the network and your own stack. ttfb starts slightly earlier than the published server-side first byte, so it also counts authentication and rate limiting. The first chunk is the first byte, so the examples below stop the clock before any silence at the start of the audio. To count that silence, find the first audible 10 ms window in the decoded PCM. The loop in the round’s write-up does that at 1% of full scale (-40 dBFS); to match the round’s -45 dBFS threshold, use its script.

For a fair number:

  • Discard the first request or two. They include opening the connection.
  • Vary the text between requests, as your real traffic does.
  • Send requests one after another. A request beyond your plan’s concurrency limit returns 429, not a slower response.
  • Take at least 20 requests and report p50 and p90, not the average or the single best run.
  • Measure with PCM. With Ogg, the first bytes are header pages, not audio.
# pip install httpx
import os
import re
import statistics
import time
import httpx
# One client for every request, so the connection is reused.
client = httpx.Client(
base_url="https://api.speechify.ai",
headers={"Authorization": f"Bearer {os.environ['SPEECHIFY_API_KEY']}"},
timeout=30.0,
)
def measure(text: str) -> tuple[float, float, str]:
start = time.perf_counter()
first_chunk_ms = None
with client.stream(
"POST",
"/v1/audio/stream",
headers={"Accept": "audio/pcm"},
json={"input": text, "voice_id": "geffen_32", "model": "simba-3.2"},
) as response:
response.raise_for_status()
for _ in response.iter_raw():
if first_chunk_ms is None:
first_chunk_ms = (time.perf_counter() - start) * 1000
total_ms = (time.perf_counter() - start) * 1000
match = re.search(r"ttfb;dur=([\d.]+)", response.headers.get("server-timing", ""))
if first_chunk_ms is None:
first_chunk_ms = total_ms
return first_chunk_ms, total_ms, match.group(1) if match else "n/a"
for n in range(2):
measure(f"Opening the connection, request {n}.") # not counted
first_chunks = []
for n in range(20):
first_chunk_ms, total_ms, server_ttfb = measure(
f"Your order {1000 + n} shipped this morning and arrives on Thursday."
)
first_chunks.append(first_chunk_ms)
print(f"first chunk {first_chunk_ms:.0f} ms, server ttfb {server_ttfb} ms, total {total_ms:.0f} ms")
deciles = statistics.quantiles(first_chunks, n=10)
print(f"first chunk p50 {deciles[4]:.0f} ms, p90 {deciles[8]:.0f} ms")

FAQ

No. They are the median first audible audio our open script measured from a client in US East on 9 Oct 2026, over the WebSocket input stream and the HTTP stream, with p90 at 58 ms and 77 ms. The 56 ms server-side first byte, measured on production traffic on 15 Sep 2026, is not a service-level commitment either. The Server-Timing header on each of your own responses reports our server’s share of that request’s wait.

Those figures were timed from a machine in US East, where the API is served, over a connection kept open between requests. Your measurement adds the network between you and US East, the handshakes of any new connection, and, depending on the tool, decoding and playback. From Zurich on the same morning, the same two endpoints read 145 ms and 153 ms, and most of the difference was the network: our server’s share of the HTTP stream’s 143 ms median first byte there was 39 ms, by its Server-Timing header. Compare your first-chunk time with ttfb in the Server-Timing header: the difference is everything outside our API.

model: "simba-3.2" with PCM output, from a client that keeps its connection open and runs near US East. Over an open connection, the WebSocket input stream, GET /v1/audio/stream/ws with output_format=pcm_24000, was the quicker of our two endpoints even for whole sentences: 47 ms against 64 ms for POST /v1/audio/stream at the median, from US East on 9 Oct 2026. It is also the endpoint for text that arrives in pieces, such as an LLM’s reply. With a new connection for each request the two were level from US East, 74 ms and 75 ms, so for a one-off request with text you already have, POST /v1/audio/stream with Accept: audio/pcm is the simpler choice. simba-3.2 is English only; use simba-3.5 for any of its 48 languages.

On POST /v1/audio/stream, audio starts arriving before the whole input has been synthesized, so send text you already have in one request; total generation time grows with length. On POST /v1/audio/speech, the response waits for the whole clip, so the first audio grows with length.

Every stream to api.speechify.ai is served from US East; from 17 October 2026 its non-streaming speech requests go to the region nearest the caller, US East or Europe. The server-side first byte on this page is measured in US East, and first audible audio from a client in US East and one in Zurich. eu.api.speechify.ai runs synthesis in Europe instead; see Regions for what it changes and what it does not.