Skip to main content
← AI Engine

Text-to-speech and speech-to-text

On-device TTS with Kokoro and Atelico TTS, STT with Whisper, and Audio2Face for ARKit-52 lip-sync at 60 fps. Up to 18x realtime synthesis, up to 90x realtime transcription, sub-3 ms per face frame. All running locally, all streaming.

Text-to-Speech

Two TTS engines, each built for different needs. Both run entirely on-device with no cloud dependency.

Kokoro TTS

High-quality neural TTS with 54 built-in voices across 9 languages (English, Italian, Spanish, French, German, Portuguese, Japanese, Chinese, Hindi). Natural prosody and expression suitable for cinematic dialogue and narrative. Supports evolutionary voice cloning: provide a reference audio clip and Kokoro adapts to match the voice over multiple iterations.

Atelico TTS

Lightweight, fast TTS designed for high-throughput scenarios. Supports instant voice cloning from a single audio sample with no training step. Ideal for ambient NPC barks, item descriptions, and any situation where you need many different voices quickly.

Atelico TTS on an M1 Max: a narrator voice (Ian) reads a line and then a whole paragraph, then an innkeeper (Morgan) speaks. Switching voices is instant.

TTS Performance

Synthesis speed is measured as realtime factor (RTF): how many seconds of audio are produced per wall-clock second of compute. 5× means 1 s of audio in 200 ms; 18× means 1 s in 55 ms. Higher is better.

Engine Hardware Realtime factor Synthesis time per 1 s of audio
Kokoro 82M M1 Max (Metal) 5.5× 182 ms
Kokoro 82M RTX 3090 (CUDA) 10.3× 97 ms
Atelico TTS M1 Max (Metal) 18.6× 54 ms
Atelico TTS RTX 3090 (CUDA) 13.0× 77 ms

Fast enough for real-time dialogue without pre-rendering, and well below the per-frame budget at 30 FPS (33 ms) once combined with per-sentence streaming.

Per-Sentence Streaming

For longer text, the engine streams audio sentence by sentence. The first sentence starts playing while subsequent sentences are still being synthesized. This keeps latency low for narrative sequences, quest log readouts, or any multi-sentence output.

A four-sentence paragraph is added in one go: audio starts with the first chunk, while the rest is still being synthesized.
// Synthesize speech from text
byte[] audio = await AtelicoAudio.Synthesize(
    "Welcome to the tavern, traveler.",
    voice: "kokoro-en-heart"
);

// Stream sentence by sentence
AtelicoAudio.SynthesizeStream(
    "A long tale of adventure. With many sentences. Each streamed as audio.",
    voice: "kokoro-en-heart",
    onChunk: (byte[] chunk) => { PlayAudioChunk(chunk); },
    onComplete: () => { Debug.Log("Done"); }
);

Audio2Face: Lip-sync & Facial Animation

Feed any audio (TTS output, recorded VO, live mic) and Audio2Face emits a stream of ARKit-52 blendshape weights at 60 fps. The same blendshape stream drives both 3D rigs (MetaHuman, Apple ARKit avatars, Live Link face capture, any morph-target rig named after the ARKit standard) and 2D animation (sprite mouth/eye atlases, Live2D / Spine rigs mapped to the ARKit channels) — same data, two rendering paths.

Animation streams alongside synthesis: the first frames are available within tens of milliseconds, so the face can start moving the instant TTS produces its first sentence (no pre-rendering, no waiting for the full audio buffer).

Audio2Face driving the ARKit-52 weights from a voice line: first on the 3D point-cloud face, then on a MetaHuman head.

Audio2Face Performance

Streamed wall-clock latency at 60 fps. The per-frame budget for 60 fps is 16.7 ms; both backends sit comfortably under it in steady state.

Backend First frame (cold) First frame (warm) Steady-state per frame
M1 Max (Metal) 122 ms 62 ms 2.6 ms (~6× realtime)
RTX 3090 (CUDA) 31 ms 16 ms 0.95 ms (~17× realtime)

Steady-state cost is small enough to run alongside LLM inference, TTS, and the renderer in the same frame budget: the whole voice-to-face pipeline (mic → STT → LLM → TTS → face) fits in a single device, no cloud round-trips.

Speech-to-Text

Whisper-based speech recognition runs on-device. Supports multiple model sizes (tiny, base, small, medium, large) so you can choose the tradeoff between accuracy and speed for your target hardware. Useful for voice commands, player speech input to NPCs, and accessibility features.

Whisper on an M1 Max: the transcript streams in while a voice speaks into the microphone, and Stop gives the polished transcript of the whole recording.

STT Performance

How fast each Whisper size transcribes audio on the two reference platforms. Realtime factor is seconds of audio transcribed per wall-clock second of compute (a 22× RTF means 10 s of speech is transcribed in 450 ms). Time per minute of audio is the same number expressed as wall-clock: how long the model takes to process one minute of speech.

Model RTF
M1 Max
Time per 1 min audio
M1 Max
RTF
RTX 3090
Time per 1 min audio
RTX 3090
Whisper tiny.en 33× 1.8 s 100× 0.6 s
Whisper base.en 20× 3.0 s 100× 0.6 s
Whisper small.en 9.1× 6.6 s 33× 1.8 s
Whisper large-v3 2.2× 28 s 11× 5.4 s
Whisper large-v3-turbo 6.3× 9.6 s 33× 1.8 s
distil-large-v3 7.1× 8.4 s 33× 1.8 s

For most game-engine use cases (short voice commands and NPC dialogue prompts), the .en small variants run well above realtime on both backends. When the player can speak any language, large-v3-turbo and distil-large-v3 are the sweet spot: full multilingual quality at 6–7× realtime on a laptop GPU and 33× on a desktop NVIDIA card.

// Transcribe audio to text
string text = await AtelicoAudio.Transcribe(audioBytes);

Voice-to-Voice NPC Pipeline

Combine STT, LLM, and TTS into a single voice-to-voice NPC interaction: the player speaks, Whisper transcribes, the LLM generates a response, and Kokoro or Atelico TTS speaks it back. The entire pipeline runs on-device with no network round-trip.

Voice-to-voice NPC pipeline: mic → Whisper → LLM → Kokoro/Atelico TTS → speaker.
Talking to Gandalf: Whisper transcribes the question, lore retrieval and the LLM write the reply, and Atelico TTS speaks it. The Details panel shows each stage's timing.

Related