Streaming synthesis that starts before it finishes.
Streaming
audio starts before the render finishes, gap-free at any length
Streaming means the first chunk is in flight while the rest is still being synthesized. The same engine narrates an audiobook, times a dub, or carries a live conversation.
Consume the stream
The SSE surface is one POST whose response body is the stream, no socket state, so it runs anywhere an HTTP response streams, including serverless and edge. Each data: line carries a base64 PCM chunk.
listing 01
POST /v1/tts/sse, play chunks as they land
const res = await fetch("https://tts.gandr.ai/v1/tts/sse", {
method: "POST",
headers: { "x-api-key": "gnd_yourkey",
"content-type": "application/json" },
body: JSON.stringify({
transcript: "The first chunk is already in flight.",
voice: { mode: "clone", wav_b64: ref },
output_format: { container: "raw",
encoding: "pcm_s16le",
sample_rate: 24000 }
})
})
for await (const line of sseLines(res.body)) {
if (line.done) break // {"done": true, "ttfa_ms": <int>, …}
player.write(decode(line.data)) // raw PCM, no transcode
}
Two transports, one behavior
- SSE for request-scoped streams: one HTTP response per utterance, a done flag with timing metadata at the end.
- WebSocket for conversations: one socket per call, an utterance per turn, binary frames back, the session shape is on the voice-agent sheet.
- Raw PCM at whatever sample rate you ask for, a player’s, a mixer’s, a telephony trunk’s, on either transport, so no transcode sits in the hot path.
The number that matters
First audio byte in 146 ms over the open internet, 116 ms p50 first audio, server side warm.
Notes
Which output formats can a stream carry?
Raw PCM (pcm_s16le) at the sample rate you request, 24000 in the examples, or WAV on the one-shot surface. Telephony stacks usually want raw PCM so nothing re-encodes in the hot path.
How do I know when an utterance is finished?
The stream ends with an explicit receipt: {"done": true, "ttfa_ms": …, "audio_ms": …}. Log ttfa_ms per utterance and you have a per-call latency audit for free.
A key, one stream, your own script, nothing on it counted while you build.
Get a key, run your own script