narration
wren, cove
Long-form app text with deep lookahead, pacing you drive with ramps or a callback, and gapless seams.
In development: phases 0 to 4 built, phase 5 in progress
One Rust core for speaking, listening, and conversation. The work runs on the phone, on a computer nearby, or in the cloud, and your app never has to know which.
let voice = VoiceModel(
appId: "com.example.calm",
profiles: [.wren]) // a calm narrator
// in your settings screen
Form { VoiceSettingsSection(model: voice) }
let session = try await voice.client
.session(consumer: "guide", profile: .wren)
try await session.start()
session.speak(SpeechChunk("Let your eyes close.",
pauseAfter: .seconds(2)))
session.ramp(to: .slow, over: .seconds(90))
val voice = VoiceModel(context,
profiles = listOf(VoiceProfile.WREN))
// in your settings screen
Column { VoiceSettings(voice) }
val session = voice.client
.session("guide", VoiceProfile.WREN)
session.start()
session.speak(SpeechChunk("Let your eyes close.",
pauseAfter = 2.seconds))
session.ramp(Pace.SLOW, 90.seconds)
A role is the behavior your app needs. It fixes the audio mode, who writes the words, how deep the buffers run, and what happens when a tier fails mid-session. A profile plays one role and carries its engines per tier; the stock profiles are named like actors so you can swap one for another.
wren, cove
Long-form app text with deep lookahead, pacing you drive with ramps or a callback, and gapless seams.
atlas
Short lines with the fastest first audio, for cues and announcements.
sage
Partial and final transcripts with Silero VAD endpointing.
juniper
Your turn handler answers each final transcript; the user can talk over the reply.
ember
A speech-to-speech model writes its own words from a character prompt.
Each role has a default order across the tiers. At session start VoiceLib takes the first rung whose models are downloaded, whose device test passed, and, for a nearby computer, that answers within half a second. Users can turn tiers off; your policy decides which exist.
voicelib-relayd on Windows, Linux, or macOS: larger engines over an encrypted QUIC link, paired once by code.phase 5Licenses are a per-app choice. An engine's weights terms apply only to apps whose profiles list it, and copyleft code sits behind build features that are off by default and produce separately named artifacts.
| Engine | Does | Runs | License | Status |
|---|---|---|---|---|
| Pocket TTS | Speaks, streaming, seven languages | Phone, computer | Code MIT, weights CC-BY-4.0 | built |
| Kokoro-82M | Speaks, English-first | Phone, computer | Apache 2.0 | built |
| Kitten TTS | Speaks, tiny and fast | Phone | Apache 2.0 | built |
| Moonshine Streaming | Listens, streaming, English | Phone, computer | MIT | built |
| Whisper | Listens, about 99 languages | Phone, computer | MIT | built |
| System | Speaks and listens | Phone | OS | built |
| Kyutai TTS and STT | Streaming pair with end-of-turn detection | Computer, CUDA | CC-BY-4.0 (STT) | planned |
| Nemotron ASR, Magpie TTS | The NVIDIA pair, 40 languages in | Computer | NVIDIA Open Model License, OpenMDW-1.1 | planned |
| PersonaPlex | Speech-to-speech persona | Computer, Linux | NVIDIA Open Model License | planned |
Every number below comes from a phase exit test on an iPhone 16 Pro (iOS 26.7.1) or a Samsung Galaxy SM-S731U1 (Exynos 2400, Android 17), with the configuration the device probe chose.
| Measure | iPhone 16 Pro | Galaxy SM-S731U1 |
|---|---|---|
| Kokoro FP32, first audio | 588 ms | not in the exit test |
| Kitten TTS nano, first audio | 174 ms on Core ML | not in the exit test |
| Moonshine tiny, real-time factor | 0.08 | 0.07 |
| Whisper tiny.en, final after the endpoint | 65 ms | 473 ms |
| Conversation, barge-in after the user's first word | 80 ms (system), 389 ms (VoiceLib canceller) | at the first word (system) |
| Conversation, false barge-ins from its own voice | 0 in all three echo modes | 0 in all three echo modes |
A conversation listens while it speaks. When the user talks over it, the output fades within 100 ms, the queue drops, and a reply your handler is still writing is discarded. Three echo cancellation modes keep the session's own voice out of its ear: the platform's voice processing, VoiceLib's own canceller in the core, or a microphone muted while it speaks. The core canceller holds barge-in back until it has learned the room, so it never interrupts itself.
Install voicelib-relayd on a PC or Mac on the same network and run voicelib-relayd pair. The phone finds it, pins its certificate from the code, and streams Opus over QUIC both ways; the turn handler stays on the phone. A Quest headset gets its strongest tier this way.
voicelib-relayd serve
voicelib-relayd pair # a QR code and an eight-letter code
voicelib-relayd status