Kokoro-7M ONNX Models & Voice Pack
Ultra-lightweight (7.48M parameters) Text-to-Speech bundle for Kokoro-7M-Distill (oddadmix/Kokoro-7M-Distill), containing both Full FP32 and INT8 Quantized ONNX models, fully optimized for CPU execution with ONNX Runtime and paired with the official conditioned voice af_msa.onnx.
- Sample Rate: 24 kHz
- Conditioned Voice:
af_msa.onnx - CPU Speed: 17.6x–18.4x faster than real-time (~330 ms for 6.1s speech)
- Zero Weights at Inference: 100% pure ONNX Runtime execution.
Files in this Folder
| File | Size | Type | Description |
|---|---|---|---|
kokoro_7m.onnx |
28.82 MB | Full Model | Full-precision FP32 model with Level 1–3 CPU graph optimizations. |
kokoro_7m_int8.onnx |
25.23 MB | INT8 Model | Dynamic INT8 quantized model for reduced footprint and max CPU speed. |
af_msa.onnx |
0.52 MB | Voice Model | Standalone ONNX voice model (evaluates style embeddings via ONNX Runtime). |
test.py |
5.9 KB | Test Script | Self-contained test runner supporting both Full Model and INT8. |
README.md |
— | Readme | Documentation and usage guide. |
Why
af_msa? The student model was distilled and conditioned specifically on theaf_msavoice pack. Distillation benchmarks show usingaf_heartseverely degrades naturalness and clarity (UTMOS drops from 4.14 to 3.57). Always pair Kokoro-7M withaf_msa.
Quickstart: How to Test
1. Requirements
Install minimal inference dependencies:
pip install onnxruntime soundfile numpy kokoro
2. Run Test
Test Full Precision Model (Default):
python test.py
Test INT8 Quantized Model:
python test.py --int8
Test Custom Text:
python test.py --text "Hello world! Testing Kokoro seven million on CPU."
python test.py --int8 --text "Testing INT8 quantized speech synthesis."
Generated audio is saved to out.wav (24 kHz, 16-bit PCM).
Performance (CPU Benchmarks)
Benchmarked on an Intel Core CPU with standard 4-thread budget:
| Model | File Size | Latency (6.1s speech) | Real-Time Factor (RTF) | Speed |
|---|---|---|---|---|
Full Model (kokoro_7m.onnx) |
28.82 MB | 349 ms | 0.0568 | 17.6x real-time |
INT8 Model (kokoro_7m_int8.onnx) |
25.23 MB | 331 ms | 0.0543 | 18.4x real-time |
Python Usage (100% Pure ONNX Runtime)
import numpy as np
import onnxruntime as ort
import soundfile as sf
from kokoro import KPipeline
# 1. Choose model: "kokoro_7m.onnx" (full) or "kokoro_7m_int8.onnx" (int8)
model_path = "kokoro_7m.onnx" # or "kokoro_7m_int8.onnx"
sess_opts = ort.SessionOptions()
sess_opts.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
model_sess = ort.InferenceSession(model_path, sess_opts, providers=["CPUExecutionProvider"])
voice_sess = ort.InferenceSession("af_msa.onnx", sess_opts, providers=["CPUExecutionProvider"])
# 2. Phonemize text
pipeline = KPipeline(lang_code="a", repo_id="oddadmix/Kokoro-7M-Distill", model=False)
text = "Hello! Kokoro-7M is running with an ONNX voice on CPU."
_, tokens = pipeline.g2p(text)
# 114-symbol vocabulary mapping
VOCAB = {
';': 1, ':': 2, ',': 3, '.': 4, '!': 5, '?': 6, '—': 9, '…': 10, '"': 11,
'(': 12, ')': 13, '“': 14, '”': 15, ' ': 16, '̃': 17, 'ʣ': 18, 'ʥ': 19,
'ʦ': 20, 'ʨ': 21, 'ᵝ': 22, 'ꭧ': 23, 'A': 24, 'I': 25, 'O': 31, 'Q': 33,
'S': 35, 'T': 36, 'W': 39, 'Y': 41, 'ᵊ': 42, 'a': 43, 'b': 44, 'c': 45,
'd': 46, 'e': 47, 'f': 48, 'h': 50, 'i': 51, 'j': 52, 'k': 53, 'l': 54,
'm': 55, 'n': 56, 'o': 57, 'p': 58, 'q': 59, 'r': 60, 's': 61, 't': 62,
'u': 63, 'v': 64, 'w': 65, 'x': 66, 'y': 67, 'z': 68, 'ɑ': 69, 'ɐ': 70,
'ɒ': 71, 'æ': 72, 'β': 75, 'ɔ': 76, 'ɕ': 77, 'ç': 78, 'ɖ': 80, 'ð': 81,
'ʤ': 82, 'ə': 83, 'ɚ': 85, 'ɛ': 86, 'ɜ': 87, 'ɟ': 90, 'ɡ': 92, 'ɥ': 99,
'ɨ': 101, 'ɪ': 102, 'ʝ': 103, 'ɯ': 110, 'ɰ': 111, 'ŋ': 112, 'ɳ': 113,
'ɲ': 114, 'ɴ': 115, 'ø': 116, 'ɸ': 118, 'θ': 119, 'œ': 120, 'ɹ': 123,
'ɾ': 125, 'ɻ': 126, 'ʁ': 128, 'ɽ': 129, 'ʂ': 130, 'ʃ': 131, 'ʈ': 132,
'ʧ': 133, 'ʊ': 135, 'ʋ': 136, 'ʌ': 138, 'ɣ': 139, 'ɤ': 140, 'χ': 142,
'ʎ': 143, 'ʒ': 147, 'ʔ': 148, 'ˈ': 156, 'ˌ': 157, 'ː': 158, 'ʰ': 162,
'ʲ': 164, '↓': 169, '→': 171, '↗': 172, '↘': 173, 'ᵻ': 177
}
# 3. Synthesize
chunks = []
silence = np.zeros(int(24000 * 0.15), dtype=np.float32)
for _, ps, _ in pipeline.en_tokenize(tokens):
if not ps: continue
input_ids = np.array([[0] + [VOCAB[p] for p in ps if p in VOCAB] + [0]], dtype=np.int64)
# Query style vector from voice ONNX model
idx = np.array([min(input_ids.shape[1] - 1, 509)], dtype=np.int64)
style_vec = voice_sess.run(None, {"index": idx})[0]
# Generate audio chunk from model ONNX
chunk = model_sess.run(None, {
"input_ids": input_ids,
"style": style_vec.astype(np.float32),
"speed": np.array([1.0], dtype=np.float32)
})[0].squeeze()
chunks.append(chunk)
chunks.append(silence)
full_audio = np.concatenate(chunks[:-1]) if len(chunks) > 1 else chunks[0]
sf.write("out.wav", full_audio, 24000)
print(f"Generated {len(full_audio)/24000:.2f}s of audio saved to out.wav!")
Model tree for Shadow0482/Kokoro-7M-ONNX
Base model
oddadmix/Kokoro-7M-Distill