geko.tts.stream() and play each WAV chunk the moment it arrives. The caller hears speech roughly one sentence after the model starts talking, not after the whole reply is written and rendered.
Keep it low-latency
Two settings and one habit do most of the work:nfe: 16. Half the diffusion steps of the default32, noticeably faster, still very usable for a conversation. Save32for narration you’ll ship. See Latency & quality.- Stream, don’t wait. Use
tts.stream()so playback starts on the first sentence instead of the full reply. - Stay warm. The GPU backend scales to zero when idle, so the first call after a lull can cold-start for tens of seconds. On a live line that’s a dead pause. Keep a container hot with predictable traffic or a pre-warm call before a session — see cold starts.
Choosing a voice
Pick one that fits the role.Aigerim (warm, professional) reads well for reception and support; there are male and female alternatives (Arman, Ainur, Aruzhan, Sanzhar, Yerlan). Audition them on the voices page and set voice once for the whole session.
Wiring the LLM into Geko
Here’s the Geko half of the loop: take an async iterable of text as the model produces it, batch it into sentences, and stream each sentence throughtts.stream() — yielding WAV chunks you feed straight to the caller’s audio channel.
llmTextStream — are yours to wire up; Geko slots in as the voice at the end. Batching on sentence boundaries keeps latency low without chopping words: each unit is big enough to sound natural and small enough to start fast.
Streams aren’t retried, so on a live call bound each turn with a per-call
timeout and use signal to cancel on barge-in or hang-up. See Errors & retries.Next steps
Streaming audio
The full streaming API and the raw wav-frames protocol.
Latency & quality
nfe, cold starts, and keeping the backend warm.Pick a voice
Audition Aigerim, Arman, and the rest of the catalog.
Errors & retries
Timeouts, cancellation, and why streams don’t retry.