kitten-tts-rs
Library Listed
Rust port of KittenTTS — ultra-lightweight ONNX-based text-to-speech
- Downloads
- 3
- Dependents
- 0
- Stars
- 314
- Forks
- 28
- Contributors
- 1
- Commits
- 25
- Latest release
- 0.2.2 ·
About
Rust implementation of KittenTTS. KittenTTS delivers high-quality voice synthesis with models ranging from 15M to 80M parameters (25–80 MB on disk). This Rust implementation provides self-contained binaries with no Python dependency.
- A Rust CLI program. It is ideally suited for AI agent skills.
- An OpenAI compatible API server. It supports SSE streaming for realtime audio applications like the EchoKit.
Adapted from: KittenML/KittenTTS (Apache-2.0). All model weights are from the original project.
Key Features of KittenTTS
- Ultra-lightweight — 15M to 80M parameters; smallest model is just 25 MB (int8)
- CPU-optimized — ONNX-based inference runs efficiently without a GPU
- 8 built-in voices — Bella, Jasper, Luna, Bruno, Rosie, Hugo, Kiki, and Leo
- Adjustable speech speed — control playback rate via the
--speedparameter - Text preprocessing — built-in pipeline handles numbers, currencies, units, and more
- 24 kHz output — high-quality audio at a standard sample rate
- Edge-ready — small enough to run on embedded devices, Raspberry Pi, phones
Read the full README
What This Rust Port Adds
- Two binaries —
kitten-ttsCLI andkitten-tts-server(OpenAI-compatible API) - Fast startup — ~100ms vs ~2s for Python import overhead
- Tiny footprint — ~10 MB binary (+ model weights) vs ~500 MB Python environment
- GPU acceleration — optional CUDA, TensorRT, CoreML, or DirectML via Cargo features
- Cross-platform — builds for Linux (x86_64, aarch64) and macOS (aarch64)
Available Models
| Model | Parameters | Size | Download |
|---|---|---|---|
| kitten-tts-mini | 80M | 80 MB | KittenML/kitten-tts-mini-0.8 |
| kitten-tts-micro | 40M | 41 MB | KittenML/kitten-tts-micro-0.8 |
| kitten-tts-nano | 15M | 56 MB | KittenML/kitten-tts-nano-0.8 |
| kitten-tts-nano (int8) | 15M | 25 MB | KittenML/kitten-tts-nano-0.8-int8 |
Quick Start
1. Install Dependencies
espeak-ng is required for phonemization:
# macOS
brew install espeak-ng
# Ubuntu/Debian
sudo apt-get install -y espeak-ng
# Fedora/RHEL
sudo dnf install espeak-ng
# Arch
sudo pacman -S espeak-ng
2. Download Binaries
Download the pre-built binaries for your platform from the Releases page:
# Example: Linux x86_64
curl -LO https://github.com/second-state/kitten_tts_rs/releases/latest/download/kitten-tts-x86_64-linux.tar.gz
tar xzf kitten-tts-x86_64-linux.tar.gz
# Example: macOS Apple Silicon
curl -LO https://github.com/second-state/kitten_tts_rs/releases/latest/download/kitten-tts-aarch64-macos.tar.gz
tar xzf kitten-tts-aarch64-macos.tar.gz
Each archive contains two binaries:
kitten-tts— CLI tool for one-off speech generationkitten-tts-server— OpenAI-compatible API server
3. Download Models
curl -LO https://github.com/second-state/kitten_tts_rs/releases/latest/download/kitten-tts-models.tar.gz
tar xzf kitten-tts-models.tar.gz
This extracts a models/ directory with all available models:
models/
├── kitten-tts-mini/ # 80M params, 80 MB — highest quality
├── kitten-tts-micro/ # 40M params, 41 MB — balanced
├── kitten-tts-nano/ # 15M params, 56 MB (fp32)
└── kitten-tts-nano-int8/ # 15M params, 25 MB — smallest
4. Generate Speech (CLI)
# Basic usage (outputs output.wav)
./kitten-tts ./models/kitten-tts-mini 'Hello, world!' Bruno
# Specify output file and speed
./kitten-tts ./models/kitten-tts-mini 'Hello, world!' --voice Luna --speed 1.2 --output hello.wav
# List available voices
./kitten-tts ./models/kitten-tts-mini "" --list-voices
5. Run the API Server
Start the server with a model directory:
./kitten-tts-server ./models/kitten-tts-mini --host 0.0.0.0 --port 8080
The server exposes an OpenAI-compatible /v1/audio/speech endpoint:
curl -X POST http://localhost:8080/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{
"model": "kitten-tts",
"input": "Hello, world! This is KittenTTS running as an API server.",
"voice": "alloy"
}' \
--output speech.mp3
Request body:
| Field | Type | Default | Description |
|---|---|---|---|
input | string | (required) | Text to synthesize |
voice | string | (required) | Voice name (OpenAI or KittenTTS names) |
model | string | "" | Accepted for compatibility; ignored |
response_format | string | "mp3" | Output audio format (see below) |
speed | float | 1.0 | Speech speed multiplier (0.25–4.0) |
stream | bool | false | Enable SSE streaming (requires "pcm" format) |
Supported audio formats:
| Format | Content-Type | Description |
|---|---|---|
mp3 | audio/mpeg | MP3 128 kbps CBR (default, resampled to 44.1 kHz) |
opus | audio/ogg | Opus in OGG container (resampled to 48 kHz) |
flac | audio/flac | FLAC lossless (24 kHz native) |
wav | audio/wav | WAV 16-bit PCM (24 kHz native) |
pcm | audio/pcm | Raw 16-bit signed little-endian PCM (24 kHz) |
aac | — | Not yet supported (returns error) |
API endpoints:
| Method | Path | Description |
|---|---|---|
POST | /v1/audio/speech | Generate speech from text |
GET | /v1/models | List loaded model |
GET | /health | Health check |
Voice mapping (OpenAI → KittenTTS):
| OpenAI | KittenTTS | Gender |
|---|---|---|
| alloy | Bella | Female |
| echo | Jasper | Male |
| fable | Luna | Female |
| onyx | Bruno | Male |
| nova | Rosie | Female |
| shimmer | Hugo | Male |
All 8 KittenTTS voices (Bella, Jasper, Luna, Bruno, Rosie, Hugo, Kiki, Leo) can also be used directly by name.
SSE Streaming
For lower time-to-first-audio on longer texts, set "stream": true with "response_format": "pcm". The server returns Server-Sent Events with base64-encoded PCM audio chunks, compatible with the OpenAI streaming TTS format:
curl -N -X POST http://localhost:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{
"model": "kitten-tts",
"input": "Hello, this is a streaming test. Each sentence is sent as a separate audio chunk.",
"voice": "alloy",
"response_format": "pcm",
"stream": true
}'
Each event is a JSON object on a data: line:
data: {"type":"speech.audio.delta","delta":"<base64-encoded-pcm>"}
data: {"type":"speech.audio.delta","delta":"<base64-encoded-pcm>"}
data: {"type":"speech.audio.done"}
The delta field contains 16-bit signed little-endian PCM at 24 kHz, base64-encoded. The first chunk is split at the earliest clause boundary for fast initial playback.
Building from Source
CPU Only (recommended for most users)
git clone https://github.com/second-state/kitten_tts_rs.git
cd kitten_tts_rs
cargo build --release
# Binaries at: target/release/kitten-tts and target/release/kitten-tts-server
With CUDA (NVIDIA GPU)
Requires CUDA toolkit and cuDNN installed on the system. Linux and Windows only.
cargo build --release --features cuda
With TensorRT (NVIDIA GPU, optimized)
Requires TensorRT runtime. Linux and Windows only.
cargo build --release --features tensorrt
With CoreML (Apple Silicon / macOS)
cargo build --release --features coreml
With DirectML (Windows GPU)
cargo build --release --features directml
Building and Testing Locally
After building from source, download models directly from Hugging Face to test:
# Download the nano-int8 model (smallest, 25 MB — good for testing)
mkdir -p models/kitten-tts-nano-int8
for FILE in config.json kitten_tts_nano_v0_8.onnx voices.npz; do
curl -L -o "models/kitten-tts-nano-int8/$FILE" \
"https://huggingface.co/KittenML/kitten-tts-nano-0.8-int8/resolve/main/$FILE"
done
For other models, replace the directory name and URL with the appropriate values from the Available Models table:
# Mini (80M params, highest quality)
mkdir -p models/kitten-tts-mini
for FILE in config.json kitten_tts_mini_v0_8.onnx voices.npz; do
curl -L -o "models/kitten-tts-mini/$FILE" \
"https://huggingface.co/KittenML/kitten-tts-mini-0.8/resolve/main/$FILE"
done
# Micro (40M params, balanced)
mkdir -p models/kitten-tts-micro
for FILE in config.json kitten_tts_micro_v0_8.onnx voices.npz; do
curl -L -o "models/kitten-tts-micro/$FILE" \
"https://huggingface.co/KittenML/kitten-tts-micro-0.8/resolve/main/$FILE"
done
# Nano fp32 (15M params)
mkdir -p models/kitten-tts-nano
for FILE in config.json kitten_tts_nano_v0_8.onnx voices.npz; do
curl -L -o "models/kitten-tts-nano/$FILE" \
"https://huggingface.co/KittenML/kitten-tts-nano-0.8-fp32/resolve/main/$FILE"
done
Test the CLI:
./target/release/kitten-tts ./models/kitten-tts-nano-int8 'Hello, world!' Bruno
Test the API server:
./target/release/kitten-tts-server ./models/kitten-tts-nano-int8 --port 8080
# In another terminal:
curl -X POST http://localhost:8080/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{"input": "Hello from the API", "voice": "alloy"}' \
--output test.mp3
CoreML on Apple Silicon: Pros and Cons
Pros
- Uses Apple's Neural Engine and Metal GPU for compatible operations
- No additional software installation needed (built into macOS)
- Can accelerate larger models where GPU compute outweighs overhead
Cons
- Slower than CPU for small models — In our benchmarks on Apple Silicon (Mac mini M4 Pro), the 80M-parameter mini model ran ~1.7x slower with CoreML (8.2s) than CPU-only (4.8s)
- Dynamic shape limitations — CoreML requires static tensor shapes; KittenTTS uses dynamic output shapes, so CoreML can only accelerate a subset of operations while the rest falls back to CPU
- Model compilation overhead — CoreML compiles the ONNX model to its internal format on first load, adding latency
- First build is slower — The
ortcrate may need to build ONNX Runtime from source with CoreML support
Recommendation
For KittenTTS models (15M–80M params), CPU-only is faster and simpler. ONNX Runtime's CPU backend already uses SIMD (NEON on ARM, AVX on x86) and multi-threading effectively. CoreML would be more beneficial for models with 1B+ parameters where GPU compute dominates.
Architecture
src/
├── main.rs # CLI binary (clap)
├── lib.rs # Library root
├── model.rs # ONNX session, inference, text chunking
├── phonemize.rs # espeak-ng → IPA phonemes → token IDs
├── preprocess.rs # Text normalization (numbers, currency, etc.)
├── voices.rs # NPZ voice embedding loader
└── bin/kitten-tts-server/ # API server binary
├── main.rs # Axum/Tokio server, model loading
├── error.rs # OpenAI-style error responses
├── state.rs # Shared model state (Arc<Mutex>)
└── routes/{health,models,speech,encode}.rs
How It Works
- Text preprocessing — Expands numbers ("42" → "forty-two"), currencies ("$10.50" → "ten dollars and fifty cents"), and normalizes whitespace
- Phonemization — Converts English text to IPA phonemes via
espeak-ng - Token encoding — Maps IPA phonemes to integer token IDs using a symbol table matching the original Python implementation
- Voice selection — Loads style embeddings from the NPZ voice file
- ONNX inference — Runs the model with input tokens, voice style, and speed parameters
- Audio encoding — Outputs MP3 (default), Opus, FLAC, WAV, or raw PCM
Compared to Python KittenTTS
| Python | Rust | |
|---|---|---|
| Dependencies | onnxruntime, misaki, phonemizer, numpy, soundfile, spacy | ort, hound, espeak-ng (system) |
| Install size | ~500 MB (with venv) | ~10 MB binary |
| Startup time | ~2s (Python import) | ~100ms |
| Deployment | pip install + venv | Single binary (CLI + API server) |
| GPU support | onnxruntime-gpu pip package | Cargo feature flags |
Performance
Benchmarked on Apple Mac M4 Pro (CPU only, no GPU acceleration). WAV output format. RTF (Real-Time Factor) = execution time / audio length — lower is better, < 1.0 means faster than real-time.
Test inputs:
- Short:
"Hello, world!"(14 chars) - Long: 5-sentence paragraph (571 chars, multiple chunks)
kitten-tts-nano-int8 (15M params, 25 MB)
| Test | Exec Time | Audio Length | RTF |
|---|---|---|---|
| CLI short | 0.93s | 1.47s | 0.63 |
| CLI long | 5.73s | 47.18s | 0.12 |
| API short | 0.24s | 1.94s | 0.12 |
| API long | 6.78s | 61.91s | 0.11 |
kitten-tts-mini (80M params, 80 MB)
| Test | Exec Time | Audio Length | RTF |
|---|---|---|---|
| CLI short | 0.71s | 1.52s | 0.47 |
| CLI long | 11.33s | 44.11s | 0.26 |
| API short | 0.64s | 2.04s | 0.31 |
| API long | 14.35s | 55.91s | 0.26 |
CLI times include model loading (~0.3s). API server times are warm (model pre-loaded, after warmup requests).
The nano-int8 model runs 8–9x faster than real-time and is recommended for interactive and real-time applications. The mini model produces higher quality audio at ~4x faster than real-time.
License
Apache-2.0 (same as KittenTTS)
Acknowledgments
Compatibility
- Runs on
- CUDA
What shows it
- CUDA: kitten-tts-rs feature cuda
- Native code
- Required
- Binds native code: audiopus_sys, mp3lame-sys, ort-sys
- Python bindings
- No Python binding crate found
- License
- Apache-2.0
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
Rust port of KittenTTS — ultra-lightweight ONNX-based text-to-speech |
3 downloads over 30 days | 0 | 314 | 0.2.2 | CUDA | Binds native code: audiopus_sys, mp3lame-sys, ort-sys | Apache-2.0 |
|
sherpa-onnx Featured
Safe Rust wrapper for sherpa-onnx speech recognition toolkit Also in Run and serve models. |
259,599 downloads over 30 days | 28 | 15,834 | 2.0.1 | GPU support unknown | Binds native code: sherpa-onnx, sherpa-onnx-sys | Apache-2.0 |
|
jpreprocess Listed
Japanese text preprocessor for Text-to-Speech application (OpenJTalk rewrite in rust language). Also in Speech and audio. |
14,491 downloads over 30 days | 7 | 61 | 0.15.0 | GPU support unknown | No native code found | BSD-3-Clause |
|
silero Listed
Production-oriented Rust wrapper for the Silero VAD ONNX model. Also in Run and serve models. |
1,888 downloads over 30 days | 3 | 6 | 0.7.0 | CUDA, ROCm | Binds native code: ort-sys (feature coreml) | Apache-2.0 OR MIT |
|
A Rust implementation of the Qwen3 Text-to-Speech (TTS) model inference. Also in Run and serve models. |
204 binary downloads per release | Not applicable | 237 | Not measured | Not measured | None stated | |
|
cohere-transcribe-rs Listed
Rust implementation for the CohereLabs/cohere-transcribe-03-2026 speech-to-text model. Includes a CLI and an OpenAI-compatible API server. Also in Speech and audio. |
0 downloads over 30 days | 0 | 101 | 0.1.1 | CUDA | Binds native code: torch-sys (feature tch-backend). Build uses a native toolchain: cmake | Apache-2.0 |
|
voxr New
Audio and speech on boostr: compressed-audio decode, resampling, DSP and grapheme to phoneme, with speech synthesis (Kokoro, VITS), voice cloning (VoxCPM2), transcription with word timings (Whisper), voice activity (Silero) and audio-text scoring (CLAP), on CPU or CUDA. Also in Speech and audio. |
642 downloads over 30 days | 2 | 2 | 0.9.1 | CUDA | No native code found | Apache-2.0 |
All projects in Run and serve modelsAll projects in Speech and audio
Why ListedNo archive, New or Featured rule places it, so it is Listed.
What it lacks for Featured
- It has 0 active dependents and 0 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 314 stars, 28 forks and 1 contributor. It needs 4,539 stars, 434 forks and 79 contributors together.
What else the check found
- The last activity is on 29 Mar 2026, 225 days ago. The rules expect an update within 365 days. Dormancy rule
- The latest release requires the deprecated dependency audiopus_sys. RUSTSEC-2026-0150 Rot signals rule
Exact rules: Listed, Featured library. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: version 0.2.2 base 300, capped at 1 releases = 50, raised to the 365-day floor: E = 365 daysdormancy: last activity 2026-03-29, 225 days ago, E = 365: activerot: deprecated requirement `audiopus_sys (RUSTSEC-2026-0150, https://rustsec.org/advisories/RUSTSEC-2026-0150.html)`featured: not featured: active_users 0 < 11 and new_adopters 0 < 9 and repository route stars 314 (needs 4539), forks 28 (needs 434), contributors 1 (needs 79)listed: listed: no archive, new or featured rule applies
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: the crates.io description
- crates.io database dump, fetched
- RustSec advisory database, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption0 active dependents, 0 new dependents in 365 days1 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | 0 | crates.io database dump | Yes | |
| New dependents (365 days) | 0 | crates.io database dump | Yes | |
| Peak active dependents | 0 | crates.io database dump | Yes | |
| Active dependents as a share of the peak | 1 | crates.io database dump | Yes | |
| Binary downloads per release | Not measured | Yes |
MaintenanceLatest human commit: 7 months ago3 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-03-29 | GitHub repository | Yes | |
| Latest release | 2026-03-29 | crates.io database dump | Yes | |
| First release | 2026-03-29 | crates.io database dump | Yes | |
| Latest version | 0.2.2 | crates.io database dump | Yes | |
| Days the oldest outside issue waits for a reply | 223 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 1 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | Yes | |
| Published docs | true | crates.io database dump | Yes | |
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityUnpatched vulnerabilities: none
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | none | RustSec advisory database | Yes | |
| RustSec unmaintained advisory | none | RustSec advisory database | Yes | |
| Deprecation notice | none | crates.io database dump | Yes | |
| Deprecated requirement | audiopus_sys (RUSTSEC-2026-0150, https://rustsec.org/advisories/RUSTSEC-2026-0150.html) | crates.io database dump | Yes |
Distribution1 releases, 3 downloads over 30 days5 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 1 | crates.io database dump | Yes | |
| Downloads over 30 days | 3 | crates.io database dump | Yes | |
| Binary downloads over the last 3 releases | Not measured | Yes | ||
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | false | crates.io database dump | Yes | |
| Crate deleted from crates.io | false | crates.io database dump | Yes |
Repository314 stars, 28 forks, 1 contributors, 25 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 314 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 28 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 1 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 25 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | Apache-2.0 | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | CUDA | crates.io database dump | No | |
| What shows each backend | CUDA: kitten-tts-rs feature cuda | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | Binds native code: audiopus_sys, mp3lame-sys, ort-sys | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | 0 | crates.io database dump | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.