Kokoro is an 82M-parameter architecture, which keeps this checkpoint lightweight and fast — synthesis runs comfortably
in real time on a regular CPU, with no GPU required for inference.
Samples
All three were synthesized from held-out validation text not seen during training (see Why This Checkpoint).
2 (adversarial/SLM loss starts here — required to avoid style-encoder collapse)
Sample rate
24,000 Hz, 80 mel bands
Training time
≈ 52 hours (13h Stage 1 + 38.6h Stage 2)
Why This Checkpoint
StyleTTS2/GAN-style training can silently collapse the style encoder partway through a run, so checkpoints are not
reliable to pick by filename or epoch number alone. Several km_m1 candidates produced during training were instead
synthesized on 20 held-out validation sentences (not seen during training) and scored for word error rate (WER)
using a Kazakh-fine-tuned Whisper ASR model with jiwer:
Voicepack
WER on held-out set
Verdict
final (this release)
16.4%
Clean, intelligible speech
epoch4_good
131.3%
Garbled / repetitive looping — stale, incompatible with the current decoder despite the filename
epoch9_collapsed
217.4%
Confirmed style-encoder collapse
final matches the exact decoder weights shipped here (kokoro_kazakh.pth) — both were exported from the same
training checkpoint, so there is no decoder/voicepack mismatch. Stage 2 validation loss also decreased monotonically
across all 5 epochs of this run (0.402 → 0.385), with no sign of the divergence seen in the collapsed run.
Installation & Usage
Runs on CPU — no GPU needed.
pip install torch kokoro "misaki[kk]"
misaki[kk] pulls in espeak-ng bindings for Kazakh phonemization; see
kikiri-tts for a ready-made inference script (inference_kazakh.py).
Note:kokoro_kazakh.pth is stored using the legacy weight_norm key format (weight_g / weight_v) so it
loads cleanly with current torch/kokoro releases. If you re-export this checkpoint yourself from a different
PyTorch version, double-check the resulting key names match what your installed kokoro expects — a silent
weight_g/weight_v vs. parametrizations.weight.original0/original1 mismatch will make load_state_dict
skip the decoder/predictor weights without raising an error, producing noise instead of speech.
python
1import torch
2from kokoro import KModel
3from misaki import espeak
45g2p = espeak.EspeakG2P(language="kk")6model = KModel(repo_id="hexgrad/Kokoro-82M", config="config.json", model="kokoro_kazakh.pth").eval()7voicepack = torch.load("km_m1.pt", map_location="cpu", weights_only=True)89text ="Сәлем! Бұл қазақ тіліндегі сөйлеу синтезі."10phonemes, _ = g2p(text)11ref_s = voicepack[min(len(phonemes)-1, voicepack.shape[0]-1)]1213audio = model(phonemes, ref_s, speed=1.0)
Download the checkpoint files directly with huggingface_hub:
Measured on an AMD Ryzen 5 5500U (6 physical cores / 12 threads via SMT, up to 4.06 GHz, no GPU), synthesizing
a 3-sentence, 22.45s-audio test set:
CPU threads
Synthesis time
Real-time factor (RTF)
Speed vs. real time
Peak RAM
1
20.9 s
0.93×
1.1×
1.46 GB
2
13.1 s
0.58×
1.7×
1.46 GB
3
11.0 s
0.49×
2.0×
1.39 GB
4
9.5 s
0.42×
2.4×
1.41 GB
5
9.1 s
0.41×
2.5×
1.41 GB
6
8.7 s
0.39×
2.6× (peak)
1.41 GB
8
9.7 s
0.43×
2.3×
1.42 GB
10
9.7 s
0.43×
2.3×
1.42 GB
12
10.1 s
0.45×
2.2×
1.39 GB
Throughput scales with core count up to the number of physical cores (6 here); beyond that, additional SMT
threads add scheduling overhead without extra real compute, so speed slightly regresses. Even single-threaded,
this model already runs faster than real time. Peak memory stays flat at ~1.4 GB regardless of thread count.
The table above measures single-request latency: how many threads to give one synthesis call so it finishes
faster. That's a different question from throughput: how many simultaneous requests from different users the
machine can serve. For that, each request should run single-threaded, with concurrency handled by running multiple
worker processes in parallel instead of parallelizing one request across threads — this avoids the synchronization
overhead that caps the table above at ~2.6×.
Concurrent single-threaded workers, same CPU:
Concurrent workers
Aggregate speed vs. real time
Requests/sec
1
1.1×
0.14
2
1.9×
0.26
3
2.4×
0.32
4
2.7×
0.44
6
3.1×
0.50
8
3.1×
0.53
10
2.6×
0.52
12
2.8×
0.63
With process-level concurrency, aggregate throughput exceeds the single-request ceiling (~3.1× real time vs. 2.6×),
and keeps benefiting from SMT threads past the physical core count — the opposite pattern from the latency table
above. In practice, on this 6-core/12-thread CPU, running around 6-8 concurrent single-threaded workers is a
reasonable default for serving multiple users at once.