Kokoro's 24 English voices, measured: pitch, brightness, and pace
Jump to 5
If code has to pick a voice rather than a person browsing a list, it needs something to sort on. The descriptions that circulate for Kokoro-82M's voices are adjectives, and at least one of them does not match what the model produces. So each voice was measured instead.
This comes from a browser extension that reads a video page's subtitle track, synthesizes speech from it locally, and plays it in sync, where voice choice also turned out to be a timing decision. The companion post covers throughput and engine selection.
Setup. Kokoro-82M v1.0 ONNX export (Apache-2.0, onnx-community/Kokoro-82M-v1.0-ONNX, fetched August 2026), onnxruntime-node on an Apple M1 Max, August 2026. Every voice speaks the same two-sentence passage from the source broadcast, and the measurements below are taken from exactly that audio, so the numbers and the downloadable samples describe the same recordings. The measurements are fundamental frequency (perceived pitch), the interquartile range of F0 (how much pitch moves), and spectral centroid (a brightness proxy), computed from the model's own output.
A single phrase turned out to be too short to judge pace or intonation, which is why the passage runs about 13 to 23 seconds per voice rather than a few seconds.
The range
The model ships around 50 voices; 24 are English, and those were measured.
| Property | Range across the 24 English voices |
|---|---|
| F0, female voices | 149–203 Hz |
| F0, male voices | 83–151 Hz |
| Spectral centroid | 730–2154 Hz |
| Clip length, identical passage | 12.8–22.6 s |
That last row has the most practical consequence: the same passage takes 77% longer in the slowest voice than in the fastest. Where speech has to fit fixed time slots, voice selection changes the timing budget before it changes the character of the output. A slower voice also reaches any compression ceiling sooner, so it starts degrading on tight lines that a faster voice handles cleanly.
Full data: voice-acoustics.csv.
Samples spanning that range. Each voice speaks the same two-sentence passage, long enough to judge pace and intonation rather than a single phrase:
| Voice | Selected as | F0 | Centroid | Sample |
|---|---|---|---|---|
|
| lowest F0 | 83 Hz | 730 Hz | |
|
| darkest | 106 Hz | 909 Hz | |
|
| least pitch movement | 120 Hz | 1450 Hz | |
|
| median F0 | 149 Hz | 1030 Hz | |
|
| brightest | 178 Hz | 2154 Hz | |
|
| default narrator | 193 Hz | 1553 Hz | |
|
| most pitch movement | 201 Hz | 1501 Hz | |
|
| highest F0 | 203 Hz | 1605 Hz |
Every sample on this page is also available uncompressed: same path,.wav instead of.mp3 (24 kHz mono). The mp3s are 96 kbps, which is transparent enough for pace and pronunciation but not necessarily for the finer comparisons here, so the originals are there to check against.
One circulating description does not match the pitch
A table of per-voice adjectives circulates widely for this model and appears to originate from a single unattributed README. Most of those adjectives ("rich", "professional", "sophisticated") describe qualities that pitch cannot confirm or refute, so they are not testable this way. One is a direct claim about pitch, and it does not match:
| Voice | Description | Measured F0 | Rank among the 12 male voices |
|---|---|---|---|
|
| "deep, powerful" | 134 Hz | third-highest |
|
| "rich, sophisticated" | 83 Hz | lowest of the twelve |
The voice described as deep measures as one of the higher male voices, and the actual lowest voice in the set is described in terms that say nothing about pitch. Judge it directly: am_fenrir against am_onyx, and for comparison am_eric (151 Hz, the highest male voice, described as "professional, authoritative") and af_kore ("bright, energetic", measuring 12th of 24 for brightness).
Full comparison: voice-claims-vs-measured.csv.
The narrow point is about programmatic selection. Adjectives are fine for browsing; if code has to pick a deeper voice for an older character, a measured column does that reliably and a copied adjective does not.
The speed parameter saturates near 2.2×
Kokoro accepts a speed argument, useful for fitting a long line into a short caption window. Past roughly 2×, requesting more returns progressively less:
| Requested | Delivered compression | Delivered ÷ requested |
|---|---|---|
| 1.5× | 1.57× | 1.05 |
| 2.0× | 1.95× | 0.97 |
| 2.5× | 2.18× | 0.87 |
| 3.0× | 2.23× | 0.74 |
| 4.0× | 2.47× | 0.62 |
| 5.0× | 2.64× | 0.53 |
| 6.0× | 2.72× | 0.45 |
One 22-character line; two longer lines in speed-saturation.csv follow the same curve.
Requesting 6× returns 2.72×. Two things follow for anything built on this parameter. Ceilings much above 2.5× buy little on this model, though a different model or use may behave differently. And a downstream stage that assumes the requested rate was delivered will under-compress: if a time-stretch stage is told a clip was already shortened 3× when the model delivered 2.2×, the line still overruns.
Two ways to shorten a line, at matched ratios
When a generated line is too long for the slot it has to fill, there are two levers: ask the model to speak faster, or time-compress the audio afterwards with a pitch-preserving stretch (WSOLA here). They produce different artifacts, and which one degrades more gracefully is a listening question rather than a measurement, so here is the same line both ways at matched nominal ratios.
| Ratio | Model speaks faster | Time-stretched after synthesis |
|---|---|---|
| 1.0× | not applicable | |
| 1.5× | ||
| 2.0× | ||
| 2.5× | ||
| 3.0× |
Uncompressed versions of the 2.5× pair, where compression artifacts are easiest to confuse with codec noise: model speaks faster · time-stretched.
For reference, the original audio delivery of the same line (wav).
One thing to know before comparing: because the speed parameter saturates, the pairs are not the same length at the higher ratios. At a nominal 2.5× the time-stretched clip really is 2.5× shorter, while the faster-synthesis clip is only about 2.2× shorter. So the time-stretched side is doing more work at the top of the range.
The measured signals published alongside the audio (voiced fraction, pitch stability, in speed-saturation.csv) shift in roughly the region where the audio starts to sound worse, but neither tracks whether words stay understandable, so they cannot settle it. Scoring intelligibility properly means a listening study or a recognizer, and neither is in scope here. The samples are published so the comparison is available rather than asserted.
Reproducing this
The model is public and the method is small: synthesize one fixed sentence per voice, then measure fundamental frequency, F0 interquartile range, and spectral centroid from the returned audio. The speed sweep is the same line synthesized at each requested rate, with the delivered compression computed as the ratio of the 1.0× duration to each result's duration.
Data files: voice-acoustics.csv · voice-claims-vs-measured.csv · voice-samples.csv · speed-saturation.csv
Synthesis is deterministic here: the same text and voice produce a bit-identical waveform each time, so these measurements reproduce exactly rather than approximately.