brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
kokoro-ttsLocal and self-hosted text-to-speech with Kokoro, the ~82M-parameter open-weight (Apache 2.0) model by hexgrad. Use when synthesizing speech offline, on-device, in the browser, or on your own server without per-character API cost — for high-volume narration, audiobooks, privacy-constrained pipelines, and prototyping. Covers running Kokoro via the Python `ko…
Independent GitHub snapshot · Automated classification · Original documentation governs
kokoro package, ONNX / kokoro-js in the browser, and the
OpenAI-compatible Kokoro-FastAPI wrapper; picking voices and language codes; blending
voices; chunking long text; controlling pronunciation via misaki/espeak-ng; and
judging when Kokoro is the right tool versus when its lack of voice cloning, narrow
emotional range, and weaker non-English quality mean you should reach for a hosted
or larger model instead. Not for voice cloning, expressive/emotional character
performance, or high-fidelity multilingual work — say so and route elsewhere.Kokoro is a small, fast, permissively licensed text-to-speech model. Its entire value proposition is that you run it yourself: no API key, no per-character billing, no audio leaving your machine. This skill helps an agent decide whether Kokoro fits a job, run it through the right runtime, and get acceptable output — and, just as importantly, recognize the jobs where Kokoro will disappoint the user and something else is the correct answer.
All version, license, voice-count, ranking, and performance facts below were verified on 2026-07-10 against the sources listed at the end. Treat them as volatile.
Reach for Kokoro when:
Do NOT use Kokoro (and tell the user so) when the job needs:
If the request is voice cloning or emotional VO, do not try to fake it with blending or prompt tricks — state the limitation plainly and suggest a cloning/expressive provider.
Voice IDs follow [langprefix][gender]_[name], e.g. af_heart = American Female
"Heart", bm_george = British Male "George", if_sara = Italian Female "Sara".
Language codes (pass as lang_code in Python; aliases en-us→a, en-gb→b):
| code | language | code | language |
|---|---|---|---|
a | American English | i | Italian |
b | British English | j | Japanese |
e | Spanish | p | Brazilian Portuguese |
f | French | z | Mandarin Chinese |
h | Hindi |
Source: VOICES.md.
Quality is not uniform — pick by grade, not by name. VOICES.md assigns each voice an "Overall" grade combining a target-quality letter and how much training audio it received (more audio = higher grade). Documented highlights (verified 2026-07-10):
af_heart (grade A, the card's default), af_bella (A−),
af_nicole (B−, breathy/ASMR), bf_emma (B−, British).af_aoede, af_kore, af_sarah, am_fenrir, am_michael,
am_puck (all C+). bm_fable, bm_george (C, British male).am_adam (F+),
af_jessica / af_river (D). Most non-English voices are C/D, trained on ~minutes of
synthetic data.Production heuristic: default to af_heart (lang a). For a project the user should
audition 3–4 A/B-graded voices before committing — grades predict, they do not guarantee,
per-sentence quality.
Documented limit: Kokoro processes at most 510 phonemized tokens per forward pass (512 with boundary tokens). VOICES.md notes voices "perform best on a goldilocks range of 100–200 tokens," are weak on very short utterances (<10–20 tokens), and rush on long ones (>400). Source: model card / VOICES.md.
Consequences for production:
KPipeline splits automatically; its split_pattern defaults to r'\n+'
for English and returns one (graphemes, phonemes, audio) result per chunk, which you
concatenate. Source: pipeline.py.\n at sentence boundaries).
This is a common silent-failure trap — verify non-English output length.Kokoro does not read graphemes directly — text is converted to phonemes by
misaki, hexgrad's G2P library, then fed to the
model. English uses misaki's dictionary (spaCy + num2words). Out-of-dictionary words
fall back to espeak-ng (EspeakFallback, on by default); espeak-ng is also the backbone
for non-English G2P. Install espeak-ng as a system dependency or OOV words degrade to
letter-by-letter spelling. Documented example: with fallback, eBook → ˈi bˈʊk; without
it, → ˈiː bˈi ˈoʊ ˈoʊ kˈeɪ (spelled out). Source: misaki README.
To fix a mispronounced word (proper noun, brand, acronym, number read wrong):
[word](/phonemes/), e.g. [Misaki](/misˈɑki/) or [Kokoro](/kˈOkəɹO/). Put the
IPA/Kokoro phonemes between the slashes; stress marks like ˈ matter.Heuristic: always dry-run domain jargon, names, and numbers before a long batch — these are Kokoro's most common error class, and each is a one-line phoneme fix.
A Kokoro "voice" is a style vector (voicepack tensor). Blending is a weighted average
of two style vectors, which produces a new usable voice. The documented mechanism is a
weighted numpy add, style1*(w0/100) + style2*(w1/100), with weights normalized if they
don't sum to 100; several tools cap blending at exactly two voices. Source:
nazdridoy/kokoro-tts voice-blending docs.
voice="af_sky+af_bella"
(equal), or weighted per that server's syntax. Source:
remsky/Kokoro-FastAPI.Use blending to: nudge timbre/pitch between two graded voices, or build a house voice that isn't any single shipped one. It does not add emotion, create a new speaker identity from a reference, or rescue a low-grade voice — averaging two C-grade voices yields a C-grade blend.
kokoro package (default for servers/batch)Best for narration pipelines, audiobooks, and anything on your own box. PyTorch backend; GPU optional. Example (labeled example — adapt paths/voices):
# pip install kokoro>=0.9.2 soundfile ; plus system espeak-ng
from kokoro import KPipeline
import soundfile as sf
import numpy as np
pipeline = KPipeline(lang_code='a') # 'a' = American English
text = "The quarterly report is ready.\nRevenue rose twelve percent."
chunks = []
for graphemes, phonemes, audio in pipeline(text, voice='af_heart', speed=1.0):
chunks.append(audio) # one result per split (default r'\n+')
sf.write('out.wav', np.concatenate(chunks), 24000) # 24 kHz mono
Why structured this way: KPipeline does G2P + chunking + inference; iterating yields per-chunk
audio you concatenate, which is exactly the long-form pattern above. speed (~0.8–1.3)
trades pace for naturalness. For lower-level control, KModel runs a single already-phonemized
chunk. Source: model card, Python API.
Runs 100% client-side via Transformers.js — no server, nothing uploaded. Model id
onnx-community/Kokoro-82M-v1.0-ONNX. Example (labeled example):
// npm i kokoro-js
import { KokoroTTS, TextSplitterStream } from "kokoro-js";
const tts = await KokoroTTS.from_pretrained("onnx-community/Kokoro-82M-v1.0-ONNX", {
dtype: "q8", // "fp32" | "fp16" | "q8" | "q4" | "q4f16"
device: "webgpu", // "wasm" | "webgpu" in-browser, "cpu" in Node ; use fp32 with webgpu
});
const audio = await tts.generate("Hello from the browser.", { voice: "af_heart" });
audio.save("audio.wav"); // tts.list_voices() lists all IDs
// Streaming: push tokens, get audio incrementally
const splitter = new TextSplitterStream();
const stream = tts.stream(splitter);
(async () => { for await (const { text, phonemes, audio } of stream) audio.save("chunk.wav"); })();
Quantization trade-off: q8/q4 shrink download and speed WASM at some quality cost;
fp32 is highest quality and is recommended with WebGPU. Source:
kokoro-js README,
onnx-community/Kokoro-82M-v1.0-ONNX.
For non-JS ONNX use, kokoro-onnx (Python) runs on onnxruntime (CPU) or
onnxruntime-gpu (CUDA) and is what enables Raspberry-Pi / edge deployments.
The fastest way to give an existing app a local TTS backend: a Dockerized wrapper exposing
an OpenAI-compatible /v1/audio/speech endpoint, so any client written for OpenAI TTS
works by changing the base URL. Supports voice mixing (af_sky+af_bella), MP3/WAV/Opus/FLAC/M4A/PCM,
streaming, per-word timestamps, a phoneme endpoint, and CPU/NVIDIA/AMD images. Example
(labeled example):
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8880/v1", api_key="not-needed")
client.audio.speech.create(
model="kokoro", voice="af_heart", input="Local TTS, OpenAI-shaped API.",
response_format="mp3",
).stream_to_file("out.mp3")
Source: remsky/Kokoro-FastAPI. Note it is a third-party wrapper (Apache-2.0-licensed model, separate project) — pin a version and verify its endpoint/voice-mixing syntax against its current README, as it evolves.
Hosted endpoints. Several inference platforms (e.g. Replicate, Baseten, and others) host Kokoro if you want the model's economics without self-hosting; those reintroduce a per-use cost and send text off-box, so they undercut the two main reasons to choose Kokoro. Prefer them only for burst capacity or when you can't run the model locally.
RTF (real-time factor) definitions differ between sources — some report audio-seconds-per-compute-second (higher = faster), others the inverse. Read the units.
Heuristic: for real-time or streaming UX, prefer GPU or a strong multi-core CPU;
low-core/edge CPUs work for batch/offline but may fall near or below real-time on long text.
Quantized ONNX (q8/q4) helps on constrained CPU/WASM at a quality cost.
Honest framing for a user: Kokoro is exceptional for 82M parameters and $0 marginal cost, competitive with far larger models on neutral English narration, and clearly behind frontier commercial and larger open models on expressiveness, cloning, and multilingual fidelity. Sell it on economics, privacy, and footprint — not on being the highest-quality voice available.
Before shipping Kokoro audio, listen for:
\n.lang_code to the voice's prefix
(a/b voices with English text, etc.); mismatches sound off.