Skip to content

Kokoro TTS

The @ariontalk/plugin-kokoro-tts plugin adds high-quality on-device neural voice synthesis to ArionTalk. It uses the Kokoro 82M open-weight model running locally in the browser via kokoro-js on ONNX Runtime WebGPU, giving your widget natural-sounding speech without sending text to an external server.

Installation

Terminal window
pnpm add @ariontalk/plugin-kokoro-tts kokoro-js

The package exports kokoroTtsPlugin, KokoroSynthesizer, and KokoroTtsOptions.

Usage with the widget

Register the Kokoro TTS plugin by passing kokoroTtsPlugin() to the ttsPlugins array on the widget element:

<ariontalk-widget id="widget" settings></ariontalk-widget>
<script type="module">
import '@ariontalk/widget';
import { kokoroTtsPlugin } from '@ariontalk/plugin-kokoro-tts';
document.querySelector('#widget').ttsPlugins = [
kokoroTtsPlugin()
];
</script>

When registered, a Speech toggle row appears in the widget settings panel allowing users to switch between System voices and Kokoro neural voices.

Preloading and lazy downloading

The Kokoro model file is ~325 MB, and the plugin requires WebGPU (see below). To keep initial page loads fast, downloading only happens when requested:

  • Opt-in download: The model is NOT downloaded when the page loads. It is downloaded lazily when the user selects Kokoro in the settings panel and clicks Apply.
  • Model cache: Once downloaded, the model instance is cached in memory. Subsequent sessions start immediately without re-downloading.
  • Automatic fallback: If model loading fails (e.g. network error or memory limit), the engine automatically falls back to system speech synthesis without interrupting the user.

Curated voices

Kokoro TTS includes 9 curated voices across American and British English:

Voice IDNameLanguageAccent
af_heartHearten-USAmerican English
af_bellaBellaen-USAmerican English
af_nicoleNicoleen-USAmerican English
bf_emmaEmmaen-GBBritish English
am_michaelMichaelen-USAmerican English
am_fenrirFenriren-USAmerican English
am_puckPucken-USAmerican English
bm_georgeGeorgeen-GBBritish English
bm_fableFableen-GBBritish English

Configuration options

Pass a KokoroTtsOptions object to kokoroTtsPlugin() to customize model loading and voice exposure:

OptionTypeDefaultDescription
modelIdstring'onnx-community/Kokoro-82M-v1.0-ONNX'Hugging Face model identifier for Kokoro ONNX model weights.
dtype'fp32' | 'fp16' | 'q8' | 'q4' | 'q4f16''fp32' on webgpu, 'q8' on wasmModel precision. Forced to fp32 on WebGPU, the only pairing the model supports there.
device'wasm' | 'webgpu''webgpu'Inference backend. 'wasm' is roughly 17x slower and cannot keep up with live conversation. See below.

WebGPU is required

The plugin runs on WebGPU with fp32 weights. On a browser without WebGPU it declines to load, nothing is downloaded, the settings panel shows “Kokoro unavailable, using system voices”, and the conversation continues on the browser’s own voices.

Two measurements explain why there is no WebAssembly fallback. Both are real-time factors: synthesis time divided by the duration of audio produced, so below 1.0 means synthesis keeps ahead of playback.

BackendDownloadReal-time factorLongest wait before speech
WebGPU + fp32~325 MB0.161.5 s
WebAssembly + q8~86 MB2.6631 s

At 2.66 the queue never catches up: gaps open between sentences and grow through a reply. WebAssembly is not a slower option here, it is one that cannot hold a conversation, so falling back to it would trade a clear failure for a confusing one.

Quantized weights cannot be used to shrink the WebGPU download either. They do not fail on that backend, they return a waveform whose samples are wrong, so playback becomes near-silence broken by bursts of unrelated phonemes. kokoro-js sanctions only fp32 there, and the plugin coerces dtype accordingly with a warning.

device: 'wasm' remains available for non-interactive use, such as pre-generating audio, where a 17x slowdown does not matter and the smaller download does. It is not supported for live conversation. | voices | string[] | 9 curated voices | List of voice IDs to expose in the settings UI. | | defaultVoice | string | 'af_heart' | Default voice ID used when none is selected. | | lookahead | number | 2 | Number of upcoming utterances synthesized ahead during streaming playback. |

Custom configuration example

document.querySelector('#widget').ttsPlugins = [
kokoroTtsPlugin({
dtype: 'q8',
lookahead: 2,
defaultVoice: 'bf_emma',
voices: ['af_heart', 'bf_emma', 'am_michael', 'bm_george'],
}),
];

System vs. Kokoro comparison

AspectSystem TTS (default)Kokoro TTS Plugin
EngineBrowser Web Speech API (speechSynthesis)On-device 82M neural model via ONNX
Sound qualityBasic OS voices (varies by OS/browser)High-quality, natural-sounding neural voice
LanguagesAll OS-supported languagesEnglish (en-US, en-GB)
Network download0 MB (built into OS)~325 MB model download on first activation
WebGPUNot applicableRequired. Falls back to system voices when unavailable
Offline supportYesYes (once cached by browser)