$5 free credits when you sign up Claim now
Wan 2.2 Animate now available Test it!
Video Upscaling models now available Test it!
Z-Anime image model Test it!
Kokoro TTS Guide: How to Control 41 Voices with Nothing but Punctuation
admin Jul 10, 2026 8 min read

Kokoro TTS Guide: How to Control 41 Voices with Nothing but Punctuation

Most TTS models give you knobs – SSML markup, emotion tags, voice design sliders. Kokoro gives you a text box and 41 preset voices.

The catch: it sounds better than models ten times its size. At 82 million parameters, Kokoro consistently ranks among the top open-source TTS models on the TTS Arena leaderboard. Fully open-source under Apache 2.0, no hidden dependencies.

In deAPI, Kokoro runs as a single API call. You pick a voice, send text, and get back an mp3 at 24 kHz. The writing is the prompting – this guide shows you how to make it sound good.

When to Use Kokoro (and When to Use Qwen3 TTS)

If you’ve read our Qwen3 TTS guide, you know Qwen3 is a full customization suite – voice cloning from audio samples, voice design from text descriptions. Kokoro sits on the opposite end of that spectrum.

Need a polished preset voice with zero configuration? That’s Kokoro. Need a specific voice identity – your brand’s spokesperson, a narrator cloned from a recording? That’s Qwen3. Kokoro trades all that flexibility for a single API call with a voice slug.

How Kokoro Reads Your Text

Kokoro reads punctuation and nothing else. The model ignores SSML tags, emotion markers like [happy], and ALL CAPS entirely. Its prosody – rhythm and intonation – comes from two things: the punctuation you write and the voice you select. Sentence meaning shapes the output too, but punctuation is the lever you actually control.

Here’s what each mark does:

MarkWhat it does
.Full stop. Long pause, intonation resets completely.
,Short breath pause. Keeps the sentence flowing.
...Trailing pause, 0.5-1 second. Falling intonation – great for dramatic beats.
-Brief parenthetical pause, lighter than a comma.
;Mid-length pause. Sits between a comma and a period.
:Pause with anticipation, as if introducing something.
?Rising intonation on yes/no questions. Wh-questions (what, how, why) get a natural falling contour automatically.
!Higher energy and emphasis. One is enough – stacking !!! won’t make it louder.

Line breaks matter too. A double line break (\n\n) acts as a strong paragraph boundary, creating a longer pause than a period.

What Doesn’t Work

A few things to avoid so you’re not debugging silence:

ALL CAPS. I CAN'T BELIEVE IT sounds identical to I can't believe it. For emphasis, use ! or pick a more expressive voice.

Emoji. The model attempts to spell them out – ":)" becomes “colon, closing parenthesis.” Strip all emoji from your input.

Emotion markers. [excited], [whisper], [sad] – Kokoro will either try to read these as IPA phonemes or spell them letter by letter. Neither outcome is what you want.

SSML tags. <break time="500ms"/> is treated as literal text. Kokoro has no SSML parser at all.

Formatting Numbers, Abbreviations, and Names

Kokoro’s text frontend (misaki) handles common English patterns well, but some formats trip it up.

Years are the biggest trap. 1999 often reads as “one thousand nine hundred ninety-nine” instead of “nineteen ninety-nine.” Write years as words when the pronunciation matters.

Phone numbers work better expanded: five five five, one two three four instead of 555-1234.

Abbreviations like Mr., Dr., and USA expand correctly. Niche abbreviations (MVP, DMV) get spelled letter by letter, which may or may not be what you want. When in doubt, write the full phrase.

Brand names and loanwords – this is where Kokoro’s IPA support shines. You can embed phonetic pronunciation inside square brackets:

The name is pronounced [ˈhwɑː.weɪ], like "halfway" but not quite.

The model’s misaki frontend reads IPA inside [...] and produces the exact pronunciation you specify. Use it for any word the model might mangle.

Choosing a Voice

Kokoro ships with 41 preset voices across 7 languages. The naming convention tells you everything: the first letter is the locale, the second is gender, then an underscore and the name.

PrefixLanguage
aAmerican English (20 voices)
bBritish English (8 voices)
eSpanish (3 voices)
fFrench (1 voice)
hHindi (4 voices)
iItalian (2 voices)
pBrazilian Portuguese (3 voices)

Second letter: f = female, m = male. So bm_fable is a British male voice named Fable.

Voice Recommendations by Use Case

Instead of listing all 41 voices, here’s what to reach for depending on your project:

Audiobook narration: bm_fable for British storytelling warmth, or am_eric if you want an American narrative tone.

Product voiceover or ads: af_nova brings broadcast energy – the kind of voice you hear in app launch trailers. If the product skews younger, am_liam has a casual tone that works well for demos.

Podcast intros: af_nova or af_jessica – both project clearly, with enough personality to hold a listener through the first ten seconds.

IVR and system notifications: af_alloy is the safest default – neutral and personality-free by design. bm_daniel works as a British-accented alternative.

Character dialogue: Generate each character as a separate API call with a different voice, then stitch the audio files together. am_puck sounds playful, while am_fenrir drops into a low intimidating register – good contrast for two-character scenes.

All 41 Voices

American English (en-us) – 20 voices

SlugNameGenderCharacter
af_alloyAlloyFNeutral, all-purpose
af_aoedeAoedeFSoft, melodic
af_bellaBellaFWarm, friendly
af_heartHeartFEmotional, warm
af_jessicaJessicaFBusiness-like, clear
af_koreKoreFExpressive, young
af_nicoleNicoleFNatural, conversational
af_novaNovaFEnergetic, broadcast
af_riverRiverFCalm, restrained
af_sarahSarahFWarm, conversational
af_skySkyFBright, light
am_adamAdamMDeep, authoritative
am_echoEchoMNeutral
am_ericEricMWarm, narrative
am_fenrirFenrirMLow, powerful
am_liamLiamMYouthful, casual
am_michaelMichaelMClassic, professional
am_onyxOnyxMVery low, dramatic
am_puckPuckMPlayful, light
am_santaSantaMLow, festive

British English (en-gb) – 8 voices

SlugNameGenderCharacter
bf_aliceAliceFClassic British, elegant
bf_emmaEmmaFWarm, narrative (RP)
bf_isabellaIsabellaFYounger, expressive
bf_lilyLilyFDelicate, light
bm_danielDanielMBusiness-like, clear
bm_fableFableMStorytelling, narrative
bm_georgeGeorgeMMature, authoritative
bm_lewisLewisMNatural, conversational

Spanish (es) – 3 voices

SlugNameGender
ef_doraDoraF
em_alexAlexM
em_santaSantaM

French (fr-fr) – 1 voice

SlugNameGender
ff_siwisSiwisF

Hindi (hi) – 4 voices

SlugNameGender
hf_alphaAlphaF
hf_betaBetaF
hm_omegaOmegaM
hm_psiPsiM

Italian (it) – 2 voices

SlugNameGender
if_saraSaraF
im_nicolaNicolaM

Brazilian Portuguese (pt-br) – 3 voices

SlugNameGender
pf_doraDoraF
pm_alexAlexM
pm_santaSantaM

Writing for Better Output

Two practical tips that affect audio quality more than voice selection:

Keep chunks under 500 characters. Kokoro handles up to 10,000 characters per call, but prosody quality degrades on longer passages. Split your text at natural paragraph boundaries and generate each chunk separately. The result sounds more consistent than a single massive generation.

Use the speed parameter for global pacing. The range is 0.5 to 2.0, with 1.0 as default. For audiobook-style narration, try 0.9. Ad reads benefit from 1.05 – just enough acceleration to feel energetic without rushing. When you need a localized pause rather than an overall tempo change, ... or - in the text is more precise than adjusting the speed dial.

Examples with Code

Each example below is a complete deAPI API call in Python. Replace YOUR_API_KEY with your actual key.

1. Audiobook Narration

import requests

response = requests.post(
    "<https://api.deapi.ai/v2/text-to-speech>",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "Kokoro",
        "input": (
            "The old lighthouse stood alone on the cliff, battered by the wind. "
            "Inside, a single candle burned... small, stubborn, defiant. "
            "Margaret climbed the spiral stairs, one careful step at a time. "
            "She had done this a thousand times before. And yet, tonight felt different."
        ),
        "voice": "bm_fable",
        "speed": 0.95,
        "language": "en-gb"
    }
)

# Poll for result
request_id = response.json()["request_id"]

Why it works: bm_fable has a soft British storytelling quality. The ellipsis before “small, stubborn, defiant” creates a cinematic pause, while the periods between short final sentences give each its own weight. Setting speed to 0.95 nudges the pacing into a book-reading rhythm.

2. Product Voiceover

response = requests.post(
    "<https://api.deapi.ai/v2/text-to-speech>",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "Kokoro",
        "input": (
            "Tired of slow mornings? Meet BrewMax, the coffee maker "
            "that thinks faster than you do. "
            "Fresh brew in forty seconds. Every. Single. Time."
        ),
        "voice": "am_liam",
        "speed": 1.05,
        "language": "en-us"
    }
)

Why it works: Every. Single. Time. – each period forces a full stop and intonation reset, turning three words into three punches. That’s Kokoro’s version of slamming a table. The question mark on the opener gives rising intonation, hooking the listener before the product name drops.

3. Podcast Intro

response = requests.post(
    "<https://api.deapi.ai/v2/text-to-speech>",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "Kokoro",
        "input": (
            "Welcome back to Signal and Noise, the podcast that "
            "cuts through the hype. "
            "I'm your host, Maya Reeves, and today we're diving into "
            "something that nobody saw coming. "
            "Ready? Let's go."
        ),
        "voice": "af_nova",
        "speed": 1.0,
        "language": "en-us"
    }
)

Why it works: af_nova has on-air energy without sounding robotic. The comma after “Signal and Noise” creates the classic podcast cadence – name, beat, tagline. Ready? Let's go. closes with a rising question followed by a flat declaration, which is the standard podcast transition into content.

4. IVR / System Notification

response = requests.post(
    "<https://api.deapi.ai/v2/text-to-speech>",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "Kokoro",
        "input": (
            "Thank you for calling. Your estimated wait time is, "
            "three minutes. To speak with an agent, press one. "
            "To leave a message, press two."
        ),
        "voice": "af_alloy",
        "speed": 1.0,
        "language": "en-us"
    }
)

Why it works: Notice the comma before “three minutes” – it creates the slight pause you hear in real IVR systems where the wait time gets dynamically inserted. af_alloy is deliberately personality-free, which is exactly what a phone system needs.

One More Thing: Language Boundaries

Kokoro has voices for 7 languages, but each voice only speaks its own. An American English voice reading a Spanish sentence will butcher the pronunciation. If your content switches languages, split it into separate API calls with matching voices – af_alloy for the English parts, ef_dora for the Spanish.


Try it yourself. Generate your first Kokoro audio clip – sign up for $5 in free credits, no card required. Paste a paragraph, pick a voice, and hear what punctuation actually does to prosody.

No subscription No credit card required

Start building with AI in under a minute

Access all models from this article through a single REST API. Start with $5 free credits — no subscription, no credit card.

Migration assistance available talk to an engineer