kitten-tts-rs

Library Listed

Rust port of KittenTTS — ultra-lightweight ONNX-based text-to-speech

Checked · Sources

Downloads
3
Dependents
0
Stars
314
Forks
28
Contributors
1
Commits
25
Latest release
0.2.2 ·

About

From the project README ·

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 --speed parameter
  • 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-tts CLI and kitten-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

ModelParametersSizeDownload
kitten-tts-mini80M80 MBKittenML/kitten-tts-mini-0.8
kitten-tts-micro40M41 MBKittenML/kitten-tts-micro-0.8
kitten-tts-nano15M56 MBKittenML/kitten-tts-nano-0.8
kitten-tts-nano (int8)15M25 MBKittenML/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 generation
  • kitten-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:

FieldTypeDefaultDescription
inputstring(required)Text to synthesize
voicestring(required)Voice name (OpenAI or KittenTTS names)
modelstring""Accepted for compatibility; ignored
response_formatstring"mp3"Output audio format (see below)
speedfloat1.0Speech speed multiplier (0.25–4.0)
streamboolfalseEnable SSE streaming (requires "pcm" format)

Supported audio formats:

FormatContent-TypeDescription
mp3audio/mpegMP3 128 kbps CBR (default, resampled to 44.1 kHz)
opusaudio/oggOpus in OGG container (resampled to 48 kHz)
flacaudio/flacFLAC lossless (24 kHz native)
wavaudio/wavWAV 16-bit PCM (24 kHz native)
pcmaudio/pcmRaw 16-bit signed little-endian PCM (24 kHz)
aac—Not yet supported (returns error)

API endpoints:

MethodPathDescription
POST/v1/audio/speechGenerate speech from text
GET/v1/modelsList loaded model
GET/healthHealth check

Voice mapping (OpenAI → KittenTTS):

OpenAIKittenTTSGender
alloyBellaFemale
echoJasperMale
fableLunaFemale
onyxBrunoMale
novaRosieFemale
shimmerHugoMale

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 ort crate 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
  1. Text preprocessing — Expands numbers ("42" → "forty-two"), currencies ("$10.50" → "ten dollars and fifty cents"), and normalizes whitespace
  2. Phonemization — Converts English text to IPA phonemes via espeak-ng
  3. Token encoding — Maps IPA phonemes to integer token IDs using a symbol table matching the original Python implementation
  4. Voice selection — Loads style embeddings from the NPZ voice file
  5. ONNX inference — Runs the model with input tokens, voice style, and speed parameters
  6. Audio encoding — Outputs MP3 (default), Opus, FLAC, WAV, or raw PCM
Compared to Python KittenTTS
PythonRust
Dependenciesonnxruntime, misaki, phonemizer, numpy, soundfile, spacyort, hound, espeak-ng (system)
Install size~500 MB (with venv)~10 MB binary
Startup time~2s (Python import)~100ms
Deploymentpip install + venvSingle binary (CLI + API server)
GPU supportonnxruntime-gpu pip packageCargo 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)
TestExec TimeAudio LengthRTF
CLI short0.93s1.47s0.63
CLI long5.73s47.18s0.12
API short0.24s1.94s0.12
API long6.78s61.91s0.11
kitten-tts-mini (80M params, 80 MB)
TestExec TimeAudio LengthRTF
CLI short0.71s1.52s0.47
CLI long11.33s44.11s0.26
API short0.64s2.04s0.31
API long14.35s55.91s0.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

  • KittenML for the original KittenTTS models and Python library
  • pyke/ort for the excellent ONNX Runtime Rust bindings
  • espeak-ng for phonemization
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.

kitten-tts-rs beside the projects that share a topic with it
ProjectDownloadsDependentsStarsLatest releaseRuns on (GPU)Native codeLicense
kitten-tts-rs This page Listed

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

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
qwen3_tts_rs App Listed

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

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
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

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 days
  • dormancy: last activity 2026-03-29, 225 days ago, E = 365: active
  • rot: 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
Adoption0 active dependents, 0 new dependents in 365 days1 not measured
Adoption measurements
SignalValueSourceFetchedCounts
Active dependents0crates.io database dumpYes
New dependents (365 days)0crates.io database dumpYes
Peak active dependents0crates.io database dumpYes
Active dependents as a share of the peak1crates.io database dumpYes
Binary downloads per releaseNot measuredYes
MaintenanceLatest human commit: 7 months ago3 not measured
Maintenance measurements
SignalValueSourceFetchedCounts
Latest human commit2026-03-29GitHub repositoryYes
Latest release2026-03-29crates.io database dumpYes
First release2026-03-29crates.io database dumpYes
Latest version0.2.2crates.io database dumpYes
Days the oldest outside issue waits for a reply223GitHub repositoryYes
Maintainer replies over 365 days1GitHub repositoryYes
Repository archivedfalseGitHub repositoryYes
Repository gonefalseGitHub repositoryYes
Release commit or manifest in the repotruecrates.io packageYes
Published docstruecrates.io database dumpYes
Latest release fails cargo checkNot measuredYes
Build check dateNot measuredYes
Build check toolchainNot measuredYes
SecurityUnpatched vulnerabilities: none
Security measurements
SignalValueSourceFetchedCounts
Unpatched vulnerabilities past the grace windownoneRustSec advisory databaseYes
RustSec unmaintained advisorynoneRustSec advisory databaseYes
Deprecation noticenonecrates.io database dumpYes
Deprecated requirementaudiopus_sys (RUSTSEC-2026-0150, https://rustsec.org/advisories/RUSTSEC-2026-0150.html)crates.io database dumpYes
Distribution1 releases, 3 downloads over 30 days5 not measured
Distribution measurements
SignalValueSourceFetchedCounts
Releases1crates.io database dumpYes
Downloads over 30 days3crates.io database dumpYes
Binary downloads over the last 3 releasesNot measuredYes
Homebrew installs on request over 365 daysNot measuredYes
Repology repository familiesNot measuredYes
Docker pull growth over 90 daysNot measuredYes
Docker pulls at the growth baselineNot measuredYes
Every version a prereleasefalsecrates.io database dumpYes
Every version 0.0.xfalsecrates.io database dumpYes
Every version yankedfalsecrates.io database dumpYes
Crate deleted from crates.iofalsecrates.io database dumpYes
Repository314 stars, 28 forks, 1 contributors, 25 commits. Stars alone never qualify a project.
Repository measurements
SignalValueSourceFetchedCounts
GitHub stars314GitHub repositoryYes — one part of the repository route
GitHub forks28GitHub repositoryYes — one part of the repository route
Contributors with a GitHub account1GitHub contributorsYes — one part of the repository route
Commits on the default branch25GitHub repositoryNo
Repository's main crate left out of the entrynonecrates.io database dumpYes
Facts that never count
Facts that never count measurements
SignalValueSourceFetchedCounts
LicenseApache-2.0crates.io database dumpNo
Runs on, from listed crates and their direct dependenciesCUDAcrates.io database dumpNo
What shows each backendCUDA: kitten-tts-rs feature cudacrates.io database dumpNo
Native code, from listed crates and their dependenciesBinds native code: audiopus_sys, mp3lame-sys, ort-syscrates.io database dumpNo
Python bindings, from direct dependencies of listed cratesNo Python binding crate foundcrates.io database dumpNo
Crates that depend on a listed crate directly0crates.io database dumpNo

Corrections and review history

Report a correction

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.