Speaking on Apple Silicon
mlx-audio is the audio extension for MLX — text-to-speech, speech-to-text, and a few audio-conditioned utilities. It lives outside the core mlx-lm package; you install it separately. The text-to-speech side is what this lesson covers.
The tradeoff to understand up front: TTS quality is moving fast and the leading models change every few months. A code path that worked perfectly with the popular TTS model of six months ago may need a new model name today. The pattern (load model, synthesize, save) is stable; the specific model identifiers and their voice slots are not. Treat the model names below as 2026-05 snapshots.
Install + minimum loop
Two commands. pip install mlx-audio in your mlx env, then a Python snippet that loads a TTS model and synthesizes one sentence to a WAV file.
Latency expectations on Apple Silicon
For a small TTS model (Kokoro-82M and its size class) on an M-class Mac, the wall-clock latency to synthesize a short sentence is typically a fraction of the audio's playback duration — i.e. faster than realtime. Step up to a 1B-class model like Sesame CSM and it gets heavier, but the loop is the same. For longer text or larger models, you'll see latency scale with token count and model size, but you should still see better-than-realtime on M-Pro and up. If you're seeing slower-than-realtime, the most likely cause is the model not being optimized for MLX yet (or being run through a wrapper that doesn't take advantage of unified memory).
Voices and prompts
Most modern TTS models accept a voice parameter (selects from a discrete set of trained voices) and the text to synthesize. Some accept additional conditioning — emotion, speaking rate, pause control via SSML-style markers. Read the model card for the exact API; the wrapper around the raw model in mlx-audio usually surfaces the same controls but renames them to fit a common API.
What to remember from this lesson
The mental model: TTS in MLX is one more API surface that loads, runs, and emits — same shape as mlx-lm's generate, but the output is bytes of audio instead of a string. The specific best-of-class model will change; the loop won't.