Skip to content

Add Kokoro TTS plugin (server-mode, via Kokoro-FastAPI)#6409

Open
HenryVarro666 wants to merge 1 commit into
livekit:mainfrom
HenryVarro666:kokoro-tts-plugin
Open

Add Kokoro TTS plugin (server-mode, via Kokoro-FastAPI)#6409
HenryVarro666 wants to merge 1 commit into
livekit:mainfrom
HenryVarro666:kokoro-tts-plugin

Conversation

@HenryVarro666

Copy link
Copy Markdown

Adds livekit-plugins-kokoro: a native TTS plugin for the open-weight Kokoro model served by Kokoro-FastAPI. Fixes #6184.

Why a native plugin (root cause of #6184)

The openai.TTS adapter selects its stream parser by model name: only tts-1/tts-1-hd use the raw-audio path; everything else — including the default gpt-4o-mini-tts and the natural choice model="kokoro" — sends stream_format="sse" and parses the response with iter_lines(), only pushing audio from data: {"type": "speech.audio.delta", ...} events. Kokoro-FastAPI ignores the unknown stream_format field (pydantic extra=ignore) and streams raw binary, so no line ever matches, zero frames are pushed, and the framework raises APIError: no audio frames were pushed — exactly what #6184 reports. Reproduced against a live Kokoro-FastAPI v0.6.0:

[openai-compat default] APIError: no audio frames were pushed for text: ...   (after 3 retries)
[kokoro native]         44 frames, 7.71s audio, TTFB 315ms, total 531ms

The plugin requests response_format="pcm", stream=true (raw 24 kHz mono s16le — Kokoro-FastAPI's sample rate is fixed server-side) and pushes chunks through AudioEmitter with mime_type="audio/pcm" as they arrive.

Relation to #1615

#1615 (@kailashsp) runs Kokoro in-process via kokoro-onnx, and was parked on the shared-inference-process direction davidzhao mentioned there. This PR is complementary, not a replacement: it is server-mode only — an HTTP client with zero in-process inference — so that architectural direction doesn't apply. It follows the same shape as the other HTTP vendor TTS plugins.

Features

  • Voice selection incl. Kokoro blending syntax ("af_bella(2)+af_sky(1)"), speed, lang_code
  • list_voices() helper (handles both the current and legacy response shapes)
  • update_options(), optional bearer token for deployments behind an authenticating proxy (Kokoro-FastAPI itself needs none), KOKORO_BASE_URL env var
  • streaming=False capability — Kokoro-FastAPI takes complete text, so the framework's StreamAdapter handles sentence streaming

Testing

Hermetic tests in tests/test_plugin_kokoro_tts.py (pytest --plugin kokoro, no real server or key needed — a local aiohttp fake serves the endpoints): PCM passthrough byte-exactness, request-body correctness, update_options/lang_code, HTTP error → APIError mapping, list_voices both shapes. 4/4 pass.

Live verification against ghcr.io/remsky/kokoro-fastapi-gpu:v0.6.0 (H100): audio artifact plays correctly, voice blending produces distinct waveforms, 68 voices listed. To try it locally:

docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest
python -c "..."  # kokoro.TTS(voice="af_heart") — defaults to http://localhost:8880/v1

make lint / ruff format --check / mypy (strict) all pass.

Note on uv.lock: besides the new package entries, the diff picks up a pending re-lock from an earlier dependency change on main (phonic 0.32.5 → 0.32.9, primp/lxml pruned) — any uv lock run reproduces this. Happy to drop it and let you re-lock separately if preferred.

Adds livekit-plugins-kokoro: a native TTS plugin for the open-weight Kokoro
model served by Kokoro-FastAPI. Requests raw PCM (24 kHz mono s16le) with
stream=true and forwards chunks through AudioEmitter as they arrive, instead
of going through the OpenAI compatibility layer, whose SSE response parsing
is incompatible with Kokoro-FastAPI's raw binary streaming for every model
name except tts-1/tts-1-hd (fixes livekit#6184).

Supports voice selection and Kokoro voice blending syntax, speed, lang_code,
optional bearer auth for proxied deployments, a list_voices() helper, and
update_options(). Hermetic tests included (local aiohttp fake server).
@HenryVarro666 HenryVarro666 requested a review from a team as a code owner July 13, 2026 22:22
@CLAassistant

CLAassistant commented Jul 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Native Kokoro TTS Support to Bypass Broken OpenAI Protocol Compatibility Layer

2 participants