Skip to content

Kokoro Text-to-Speech on macOS

Kokoro gives BookOrbit natural-sounding narration without sending book text to a cloud speech service. In this guide, you will run Kokoro directly on your Mac, make sure it can speak, connect it to BookOrbit, and choose the voices your readers can use.

This walkthrough uses Kokoro-FastAPI with Apple MPS. It works especially well with BookOrbit because it includes voice discovery and word timing for spoken-word highlighting.

You need:

  • An Apple Silicon Mac.
  • BookOrbit already running.
  • A BookOrbit account with the manage_app_settings permission.
  • Terminal access and enough free space for the Python environment and model.

You will keep Kokoro running in its own Terminal window whenever you want to use narration.

Kokoro needs espeak-ng for speech processing and uv to manage its Python environment.

Install Homebrew if needed, then run:

Terminal window
brew install espeak-ng
curl -LsSf https://astral.sh/uv/install.sh | sh

Open a new Terminal window if the uv installer asks you to refresh your shell, then check both tools:

Terminal window
uv --version
espeak-ng --version

Both commands should print a version number.

Create a home for Kokoro, download Kokoro-FastAPI, and install it in an isolated Python environment:

Terminal window
mkdir -p "$HOME/Applications/kokoro"
cd "$HOME/Applications/kokoro"
git clone https://github.com/remsky/Kokoro-FastAPI.git fastapi-native
cd fastapi-native
uv venv --python 3.10 .venv
uv pip install -e .
uv run --no-sync python docker/scripts/download_model.py --output api/src/models/v1_0

The model download can take a little while. When it finishes, confirm that Python can see your Mac’s GPU:

Terminal window
uv run --no-sync python - <<'PY'
import torch
print("MPS built:", torch.backends.mps.is_built())
print("MPS available:", torch.backends.mps.is_available())
PY

Both lines should end in True. If MPS available is False, update macOS and restart before continuing.

From the Kokoro folder, run:

Terminal window
cd "$HOME/Applications/kokoro/fastapi-native"
export USE_GPU=true
export USE_ONNX=false
export DEVICE_TYPE=mps
export PYTORCH_ENABLE_MPS_FALLBACK=1
export PYTHONPATH="$PWD:$PWD/api"
export MODEL_DIR=src/models
export VOICES_DIR=src/voices/v1_0
export WEB_PLAYER_PATH="$PWD/web"
export API_LOG_LEVEL=INFO
uv run --no-sync uvicorn api.src.main:app --host 0.0.0.0 --port 8880

Kokoro is ready when Terminal shows messages similar to:

Application startup complete.
Uvicorn running on http://0.0.0.0:8880

Leave this Terminal window open. Kokoro stops when you close it or press Control-C.

Before involving BookOrbit, generate one short sample. Open a second Terminal window and run:

Terminal window
curl -fsS -X POST http://localhost:8880/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{
"model": "kokoro",
"voice": "af_heart",
"input": "Kokoro is ready for BookOrbit.",
"response_format": "mp3",
"speed": 1.0
}' \
-o kokoro-test.mp3
open kokoro-test.mp3

If you hear the sentence, the Mac side is ready. Keep the Kokoro Terminal running and move on to BookOrbit.

Open Settings > Server > Text-to-Speech, then select Add provider.

The base URL depends on where BookOrbit runs:

BookOrbit runs inBase URL
Docker Desktophttp://host.docker.internal:8880/v1
Directly on the Mac, such as a development checkouthttp://localhost:8880/v1

Fill in the provider form:

FieldValue
NameKokoro
Base URLThe address from the table above
API keyLeave blank
Default modelkokoro
This provider can list its own voicesOn

Select Save.

BookOrbit Text-to-Speech provider form configured for Kokoro

Expand the new provider and select Test connection. BookOrbit should report Connected and show the number of voices it found.

Expanded Kokoro provider with its configuration, voices, and connection test

Kokoro and BookOrbit are now talking to each other.

Kokoro includes many voices, but a shorter list makes the reader’s voice picker easier to use. Select Manage voices, then choose one of these starting points:

  • Load Kokoro preset adds a small set of well-known voices with friendly names.
  • Import from provider adds every voice reported by your Kokoro server.

Use the speaker button to hear a voice. Remove any you do not want to offer, rename voices if helpful, and then select Save voices.

Manage Voices dialog with curated Kokoro voices and preview controls

You can return here at any time. The saved list controls which voices readers are allowed to use.

Open an eBook and choose Listen with narration. Pick one of the Kokoro voices, adjust the speed if needed, and start playback.

BookOrbit remembers your voice and reading position. With Kokoro-FastAPI, the reader can also follow the narration with word-by-word highlighting.

That is the complete setup. For future sessions, you only need to repeat Start Kokoro before using narration.

Start with the point where the flow stopped:

What happenedWhat to try
The sample MP3 was not createdCheck the Kokoro Terminal for an error and confirm it says Uvicorn is running on port 8880.
The sample works, but BookOrbit cannot connectIf BookOrbit uses Docker Desktop, make sure the base URL uses host.docker.internal, not localhost.
Port 8880 is already in useRun lsof -nP -iTCP:8880 -sTCP:LISTEN, then stop the conflicting process or start Kokoro on another port and use the same port in BookOrbit.
Kokoro reports CPU instead of MPSStop it, then confirm all the environment variables in Start Kokoro are set in the same Terminal before starting Uvicorn.
The connection works, but no voices appearEdit the provider and make sure This provider can list its own voices is on. Then use Manage voices > Import from provider.
A voice disappeared from the readerCheck Manage voices. Removing a curated voice also removes it from the reader.

MLX-Audio starts speaking faster for the short passages BookOrbit usually sends. It is a good alternative if quick response matters more than Kokoro-FastAPI’s live voice discovery and word-by-word highlighting.

Install it in a separate environment:

Terminal window
mkdir -p "$HOME/Applications/kokoro/mlx-audio-native"
cd "$HOME/Applications/kokoro/mlx-audio-native"
uv venv --python 3.12 .venv
uv pip install mlx-audio fastapi uvicorn python-multipart webrtcvad "setuptools<81"
uv pip install misaki num2words spacy==3.8.5 phonemizer-fork espeakng-loader
uv pip install "en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl"

Start it on port 8000:

Terminal window
cd "$HOME/Applications/kokoro/mlx-audio-native"
uv run --no-sync mlx_audio.server --host 0.0.0.0 --port 8000

Add it to BookOrbit using these differences:

FieldMLX-Audio value
Base URL, BookOrbit in Docker Desktophttp://host.docker.internal:8000/v1
Base URL, BookOrbit running directly on the Machttp://localhost:8000/v1
Default modelmlx-community/Kokoro-82M-bf16
This provider can list its own voicesOff

After saving, open Manage voices and select Load Kokoro preset. MLX-Audio does not provide the live voice list or word timing, so BookOrbit uses the preset voices and highlights one text block at a time.

If native Apple GPU acceleration is not available, BookOrbit can run its bundled Kokoro CPU service. From the folder containing BookOrbit’s Compose file, run:

Terminal window
docker compose --profile tts up -d

Add the provider with http://kokoro:8880/v1 as its base URL, kokoro as its model, and voice discovery on. This is the simplest Intel Mac option, but narration starts more slowly than with MPS or MLX.