Local AI Text-to-Speech in the Browser with Kokoro
Kokoro-82M runs text-to-speech fully in the browser through Transformers.js, with WebGPU, WASM, and CPU backends and no server calls.
Local AI Text-to-Speech in the Browser with Kokoro
Text-to-speech has typically meant sending text to a cloud service and waiting for audio to come back. Kokoro, an open-weight TTS model, takes a different path. Through a JavaScript package called kokoro-js, the model can run entirely on the client side in the browser, with no audio or text leaving the device. The project is published at https://github.com/hexgrad/kokoro and ships its weights under the Apache-2.0 license.
A Small Model That Runs Client-Side
Kokoro is an 82-million-parameter text-to-speech model. The project describes it as a frontier TTS model for its size, delivering quality comparable to larger models while being faster and more cost-efficient. The relatively small parameter count is what makes in-browser execution practical, since the weights are light enough to download and run without server hardware.
The browser support comes through kokoro-js, which the project says is built to run “100% locally in the browser thanks to Transformers.js.” Transformers.js is the library that loads the model and handles inference inside the page, so a web application can synthesize speech without a backend API.
Installation is a single package:
npm i kokoro-js
The model itself is distributed in ONNX format under the model ID onnx-community/Kokoro-82M-v1.0-ONNX, which kokoro-js downloads and runs.
Choosing a Backend and Precision
kokoro-js exposes three execution backends. The wasm backend runs in the browser using WebAssembly, the webgpu backend runs in the browser using the GPU, and the cpu backend is intended for Node. For the WebGPU path, the project recommends using fp32 precision.
Precision is configurable through a dtype option, with five choices: fp32, fp16, q8, q4, and q4f16. The quantized options (q8, q4, and q4f16) reduce the model footprint, which can matter for download size and memory, while fp32 is the higher-precision setting suggested for WebGPU. Selecting a backend and dtype lets a developer trade off between download size, memory use, and the hardware available in the browser.
Voices and Output
The package includes a set of voices spanning American and British English. Each voice carries metadata such as traits, target quality, training duration, and a letter grade. Examples include af_heart, graded A, and af_bella, graded A-. The full list is available at runtime by calling tts.list_voices(), so an application can present voices to users or pick one programmatically.
Beyond single-shot generation, kokoro-js supports streaming output through a TextSplitterStream, which breaks longer text into chunks for incremental synthesis. Generated audio can also be saved to a WAV file, which is useful for both browser playback and Node scripts that produce audio assets.
Why Local Synthesis Matters Here
Running the model in the browser keeps the text and the resulting audio on the user’s machine, since nothing is sent to a remote service for processing. The combination of an 82M-parameter model, ONNX weights, and Transformers.js makes this self-contained setup possible without a dedicated speech backend. For developers, the practical takeaway is that a capable TTS voice can now be a front-end dependency installed from npm rather than an external API call, with WebGPU available where the browser and hardware support it.
Source: github.com
Related Tips
How the Model Context Protocol Handles Authorization
A look at the Model Context Protocol authorization spec: OAuth 2.1 roles, token validation, scopes, and the discovery flow between clients and servers.
Memory Systems for Long-Running AI Agents
How long-running AI agents manage memory through compaction, note-taking, and sub-agents, based on Anthropic's context engineering guidance.
Abliteration: Removing AI Refusals Explained
Abliteration uncensors language models by finding the refusal direction in the residual stream and orthogonalizing weights against it, without retraining.