Kokoro 82M: the open-weight text to speech model as an API
Kokoro 82M is an open-weight text to speech model that turned a small budget into a famous result. The model carries 82 million parameters. Training used about one thousand dollars of A100 time on a few hundred hours of permissively licensed audio. Even so, reviewers kept comparing its speech quality to systems many times its size. It shipped as v1.0 on 27 January 2025 under Apache 2.0. On this platform it answers the kokoro-tts alias on an OpenAI-compatible speech route. All 28 official English voices are there, metered per character from a prepaid wallet.
This page covers the model, the full voice catalog you can call here, and the request itself. It also carries our instrumented numbers from the serving lane. And it draws the honest line between self-hosting and calling an endpoint.
Last verified: 2026-09-25
What it is
The official model card describes Kokoro as an open-weight TTS model. Its quality is comparable to larger models, and it runs faster and cheaper. The architecture is StyleTTS 2 with an ISTFTNet decoder and no diffusion step. That is why an 82M-parameter model lands in hundreds of megabytes. It also runs at useful speed on plain CPUs. The training data story matters for commercial users. The card states the model was trained exclusively on permissive or non-copyrighted audio with IPA phoneme labels. It also lists the Creative Commons sources it drew from.
Four facts from the card shape what you can build on it:
- Fixed voice packs, no cloning. Kokoro speaks in the voices it was trained with. There is no reference-audio cloning path, which also means no consent questions around a cloned reference and no voice drift.
- English is the deep language. v1.0 ships 54 voices across eight languages, and English holds 28 of them, split into American and British groups. The card's own voice guide warns that non-English support may be thin.
- A phoneme fallback exists. The pipeline converts text to phonemes with the misaki library and falls back to espeak-ng for out-of-dictionary words, and you can force a pronunciation by supplying phonemes directly. Odd names and acronyms are fixable, not fatal.
- The output is plain PCM wav at 24 kHz. No container gymnastics, no proprietary codec, nothing to watermark. Our own verification of this lane's output with a watermark detector found none, as expected for this model.
One caution from the card itself, repeated here because it protects buyers. The model's author warns that websites with "kokoro" in their root domain are not affiliated with the model. Some have used that implied affiliation to sell services. The card links archived snapshots of the offending pages. When you compare Kokoro offerings, check who actually runs the weights you are calling.
Here the model answers to the kokoro-tts alias on the speech route. The lane takes calls today, measured 9 September 2026. It is metered by the character from a prepaid wallet. The models index carries the catalog's current state.
Use cases
The profile: fixed English voice packs, up to 3,500 characters per request, and a lane measured at 7.0 million characters per day. That is a volume profile, and the good fits follow from it.
- Narration and articles read aloud. News digests, blog audio, documentation narration, and internal comms are steady streams of medium-length English text. Split at sentence boundaries under the cap and concatenate.
- Agents and apps that talk. A spoken confirmation or summary is usually a paragraph, and the prepaid wallet caps the damage a runaway loop can do: at zero balance its next request is simply refused.
- Accessibility and read-aloud surfaces. Fixed, consistent voices matter more than voice variety here, and the A-grade voices (below) hold character across long sessions.
- Prototypes without a GPU. The local install path needs Python, PyTorch, and espeak-ng. The API path needs one HTTP call. When the question is only whether speech helps the product, one of those two roads starts answering it in minutes.
- Course, video, and IVR voice-over in volume. Per-character metering makes the cost of a script the number of characters in it, known before you send anything.
- Paired with a cloning model. When a project needs one cloned narrator plus a hundred hours of stock English speech, the split is natural: clone on a cloning-capable model, run the volume through Kokoro.
Every English voice, listed
On our September 2026 read of this query, no platform page publishes the voices in its page content. They sit behind login-gated demos and playground dropdowns. One vendor markets a 19-voice subset. Here is the complete official English set in the open, from the official voice guide. It is exactly the catalog this platform serves.
| Group | Ids |
|---|---|
| American female (11) | af_heart (default), af_bella, af_nicole, af_alloy, af_aoede, af_jessica, af_kore, af_nova, af_river, af_sarah, af_sky |
| American male (9) | am_adam, am_echo, am_eric, am_fenrir, am_liam, am_michael, am_onyx, am_puck, am_santa |
| British female (4) | bf_alice, bf_emma, bf_isabella, bf_lily |
| British male (4) | bm_daniel, bm_fable, bm_george, bm_lewis |
The guide grades each voice on the quality and quantity of its training data. The grades are not courtesy stars. af_heart grades A and af_bella A-. The next tier, B-, holds af_nicole and bf_emma. A broad C+ band covers af_aoede, af_kore, af_sarah, am_fenrir, am_michael and am_puck. Several voices sit in the C and D range. One American male voice grades lowest of all.
Two practical consequences. Pick a narrator from the top of the grade table rather than by name. And read the guide's length guidance before long jobs. Voices perform best in a middle range of input lengths. They can wobble on very short utterances, under roughly 10 to 20 phoneme tokens. They can rush on long ones, past roughly 400. That is one more reason to chunk long scripts at sentence boundaries instead of filling the cap.
The whole catalog is one free read away: GET /v1/audio/voices?model=kokoro-tts with a valid key. It meters nothing and needs no balance.
Run it yourself or call the API
The Apache 2.0 weights are downloadable, and the CPU story is real. The reference pip install kokoro path plus espeak-ng synthesizes on a laptop. Community ONNX builds run in browsers. Kokoro-82M still draws Hacker News threads about GPU-poor setups. The self-host road is genuinely open, so here is the honest decision rule.
Take the local road when the local properties are what you are actually buying. Offline or embedded operation. Free unlimited synthesis once the machine exists. Phoneme-level control over odd words. And daily volume so high that billing per character would outgrow any hosting bill. The official repository documents the install, the language codes, and the espeak-ng dependency. The community wrapper of record exposes the same OpenAI route shape from a Docker container you own.
Call the API when the undifferentiated work is the part you want gone. That covers the runtime, the updates, the metering, and the monitoring. Existing OpenAI client libraries plug straight in, so no new SDK enters your codebase. Spend is capped by the wallet's balance rather than by your alerting. The torch install, the phoneme fallback configuration, and the segmentation strategy for long text become someone else's maintenance. Model or pipeline updates arrive on redeploy without a ticket in your tracker.
The measurements below are also part of what you are buying. Producing them yourself on a self-hosted lane is a real project. Trusting an unmeasured one is a gamble.
The two roads pair well: prototype and burst on the API, keep a local build for offline work, and let the same voice ids flow between both.
Kokoro vs Audio8: which one
Kokoro and Audio8 answer to the same wallet on the same speech route. The honest comparison is not which model is better. It is which lane fits the job.
Audio8 is the reach model: 0.6B parameters, a zero-shot cloning architecture, a bundled 44.1 kHz codec, and eleven card-recommended languages. Kokoro is the depth model: 82M parameters, fixed voice packs, a 24 kHz output, and English as the deep language of its eight. On the hosted voice catalogs the order flips. This platform serves all 28 official English Kokoro voices. Audio8's hosted surface carries one registered default voice. It keeps per-request cloning on that model's local path.
The measured split comes from one fence. Our task-17 measurements of 9 September 2026 put Kokoro's lane at roughly 0.8 seconds plus 0.0149 seconds per character. Audio8's clean curve on the same window runs at about 1.4 seconds plus 0.131 seconds per character. That is roughly nine times the per-character time. Ceilings and caps follow the same line: 7.0 million characters per day against 0.37 million, and a 3,500-character request cap against 250. The design centers differ too. Kokoro's official guidance favors middle-length inputs. It wobbles under roughly 10 to 20 phoneme tokens and rushes past roughly 400. Audio8's project guidance asks for inputs within 150 characters for best quality.
English narration at volume belongs on this lane. Short-form multilingual speech and cloning prototypes belong on Audio8's page. It carries the other side of every number above. Both routes sit behind one wallet. Both answer calls today.
API usage
Calls go to POST /v1/audio/speech, authenticated with a Bearer key issued by the console. The body:
| Field | Required | Meaning |
|---|---|---|
model | yes | kokoro-tts on this platform |
input | yes | the text to synthesize, up to 3,500 characters |
voice | yes | a catalog id, af_heart by default |
response_format | no | output format selection; the lane emits wav |
speed | no | playback rate multiplier |
Chunked transfer is the only delivery mode. A stream field is not in the accepted set. Sending one returns an unknown-parameter error rather than being ignored. A silent no-op would be worse. The response is wav, PCM 16-bit, mono, 24 kHz, confirmed against the lane's own output bytes.
What the route enforces, in the order you will meet it:
- 3,500 characters per request. Input past the cap fails with a 400 at the door, before any synthesis work starts, and nothing is charged for it. The cap is the measured one (task-17 review F-3, 9 September 2026): this lane synthesizes at roughly 0.8 seconds plus 0.0149 seconds per character, so a full-cap request takes about 52.8 seconds, just inside the request budget. A 10,000-character article is three requests: two at the cap, one shorter.
- Give the first byte room. The lane buffers synthesis before any audio leaves, so tens of seconds can pass before playback starts. Configure a read timeout of at least 120 seconds, and give curl the
--no-bufferflag when you consume the stream live. - Billing follows the characters you send, as runes. A completed request bills the input's Unicode rune count, so an accented character or a CJK character is one unit, not more. A generation that dies before the first byte is never billed. A death mid-stream keeps the delivered audio and does not bill the turn; because raw audio has no in-band error channel, the connection aborting is itself the error signal, so a clean end always means complete audio. If your client disconnects mid-audio, the turn still bills: the input was consumed.
- Retries re-bill. The
Idempotency-Keyheader is accepted but carries no replay semantics on this route, because audio output is too large for the replay store. Whatever retried the request pays for the second synthesis, so inspect your client's retry behavior before this route meets production traffic.
curl
curl -X POST "https://api.ironstratum.com/v1/audio/speech" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kokoro-tts",
"input": "Kokoro turns 82 million parameters into a voice, and this lane meters it by the character.",
"voice": "af_heart"
}' \
--no-buffer \
--output speech.wav
python
import os
import requests
resp = requests.post(
"https://api.ironstratum.com/v1/audio/speech",
headers={"Authorization": "Bearer " + os.environ["KEY"]},
json={
"model": "kokoro-tts",
"input": "Kokoro turns 82 million parameters into a voice.",
"voice": "af_heart",
},
timeout=120, # first byte can take tens of seconds at the cap
)
resp.raise_for_status()
with open("speech.wav", "wb") as f:
for chunk in resp.iter_content(chunk_size=65536):
f.write(chunk)
openai-sdk
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.ironstratum.com/v1",
api_key=os.environ["KEY"],
)
with client.audio.speech.with_streaming_response.create(
model="kokoro-tts",
voice="af_heart",
input="Kokoro turns 82 million parameters into a voice.",
) as response:
response.stream_to_file("speech.wav")
Migrating an existing OpenAI speech integration means editing two values, the base URL and the model id. Nothing else in your code changes.
Benchmarks
What follows is dated evidence from two directions. One is our own instrumented runs on the serving lane. The other is the model's primary artifacts. The lane records are the platform launch catalog, section D, and the task-16 concurrency grid of 28 August 2026. The task-17 measurement window of 9 September 2026 is the third source. The same numbers are stored as comments beside the model's row in the platform's data.
| Metric | Value | Basis |
|---|---|---|
| Throughput ceiling | 7.0M chars/day | task-16 grid, true concurrency 8 |
| Time to first audio, p50 | 4.779 s at c=1 · 10.080 s at c=4 · 17.916 s at c=8 | task-16 grid |
| Tail at concurrency 8 | p95 18.492 s | task-16 grid |
| Real-time factor | 2.343 at c=1 · 1.241 at c=4 · 0.751 at c=8 | task-16 grid |
| Per-request curve | ~0.8 s + 0.0149 s per char | task-17 F-3 measurements |
| Full-cap request (3,500 chars) | ~52.8 s | derived from the curve |
| Mixed-load penalty | <= ~14% p50 vs solo | task-16 mixed grid |
| Watermark | none detected | detector verification, 27 August 2026 |
Two readings of that table. The lane is batching-positive: aggregate real-time factor improves as concurrency rises to 8. The ceiling is a planning number for sustained daily volume, not a per-request promise. And per-request latency is honest about being buffered. Single requests ride the curve, which is why the read-timeout rule above exists.
For the model itself, the primary artifacts are the card and its evaluation page. The card's releases table records v1.0 (27 January 2025, 8 languages, 54 voices) and v0.19 before it. Its evaluation page preserves leaderboard screenshots from three community arenas. They were captured in February 2025, a month after v1.0 shipped. At the time, the model's arena run was the thing people talked about. The card's own quality claim is that an 82M model is comparable to larger systems. That is the claim to hold it to. Your acceptance test is your own ears on your own text. Use the voices at the top of the grade table, at your typical script length.
Getting started
- Open an account via the console's invite flow. The console runs as an invite-only beta during this phase; the wallet, the keys, and the spend history all live there.
- Create an API key. Each key stands alone: revoke one and it stops working on the spot, without touching anything else in the account.
- Check the rate once. A refusal bills nothing, a completed request bills its characters, and an empty wallet is the stop that nothing gets past. Current rates live on the pricing page, one look and the budget question is closed.
- Make the first call. Take the curl tab, drop in your key, and synthesize a single sentence in
af_heart. Once one sentence plays, the rest is chunking arithmetic.
From there, the speech catalog covers the platform's other voice models and the models index lays out everything served.