Skip to content

Brian B. Tung

← Blog

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.

Pitch against brightness for the 24 English voices 80 100 120 140 160 180 200 220 median F0 (Hz) 500 1,000 1,500 2,000 2,500 spectral centroid (Hz) af_heart af_bella af_nicole af_aoede af_kore af_sarah af_nova af_sky am_michael am_fenrir am_puck am_echo am_eric am_liam am_onyx am_adam bf_emma bf_isabella bf_alice bf_lily bm_george bm_fable bm_lewis bm_daniel female male dot size = pitch movement (F0 IQR)

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

am_onyx

lowest F0

83 Hz

730 Hz

listen

am_echo

darkest

106 Hz

909 Hz

listen

bm_daniel

least pitch movement

120 Hz

1450 Hz

listen

af_sky

median F0

149 Hz

1030 Hz

listen

bf_emma

brightest

178 Hz

2154 Hz

listen

af_heart

default narrator

193 Hz

1553 Hz

listen

bf_alice

most pitch movement

201 Hz

1501 Hz

listen

af_bella

highest F0

203 Hz

1605 Hz

listen

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

am_fenrir

"deep, powerful"

134 Hz

third-highest

am_onyx

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

Requested synthesis speed against delivered compression 1 2 3 4 5 6 requested speed 1 2 3 4 5 6 delivered compression requested = delivered line 1 line 2 line 3

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×

listen

not applicable

1.5×

listen

listen

2.0×

listen

listen

2.5×

listen

listen

3.0×

listen

listen

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.