A model card's speed number describes two things at once, the vendor's hardware and their build of the runtime, and it says nothing about yours. On my machine the same MLX port came in more than twice as slow as its own card claims, and I adopted it anyway. What decides whether a local TTS model belongs on your box is the latency budget you're inside plus the controls your pipeline needs, neither of those lives on the spec sheet. Measured on 2026-10-28, two cached clips and one cold start, nothing tuned between runs.
What the runs actually cost
The challenger is inclusionAI/Ming-3.0-tts-0.5B, dense, a Qwen2.5-0.5B backbone with a DiT head, an audio tokenizer and a CAM++ speaker encoder, 44.1 kHz output. The port I ran is mlx-community/Ming-3.0-tts-0.5B-8bit, 1.5 GB on disk. Cached runs on my M4 mini: clip B took 6.29 s of generation for 7.40 s of audio, RTF 0.85, clip C took 6.37 s for 7.30 s, RTF 0.87. The first run was 33.0 s wall, 24 s of that HF download, which is why nobody should quote their first run as a benchmark. Output came back 44.1 kHz mono 16-bit. Sample size is honest at n=2 cached clips, the spread between them is 0.02 RTF and both land in the same half-second of budget.
Where the card's number came from
The port claims RTF 0.39 and peak 2.2 GB on an M4 Pro, I'm a plain M4 mini, so my measured 0.85 against their claimed 0.39 is a 2.2x gap, well outside anything rounding explains. Same with the quality tables, the HF card carries vendor-run benchmarks, Seed-TTS eval EN WER 1.584% and similarity 0.691 against CosyVoice3-1.5B at 1.45%/0.695, GLM-TTS 2.23%/0.672 and F5-TTS 1.83%/0.647, Qwen3-TTS-1.7B best 1.24%, plus a MiniMax multilingual set (DE 0.365%, ES 1.099%, FR 4.264%, KO 1.728%, JA 3.765%). None of it re-measured by me, one of those rows loses to FireRedTTS3 anyway. The card was created 2026-09-22 and last touched 2026-10-27, sitting at 161 likes and 6,316 downloads a month when I checked. Those tables are a lead you verify on your own hardware before quoting them, the only quality claim in this piece is the one I ran myself.
Why twenty times slower still took the slot
My baseline lane is Phonon S 31M q8, measured on this same machine, RTF 0.043, time to first chunk 8-23 ms, load 0.18 s warm against 4.5 s cold, 24 kHz, English only. Ming runs about twenty times slower there, and speed is where Phonon keeps the win. Capability is where it doesn't compete, add_voice wants .safetensors from Gradium Studio and there's no audio-prompt path at all, so no style instruction and no delivery control.
What Ming brings over that a fast small model doesn't have is zero-shot cloning from a short reference clip, Voice Design from a natural-language description, freeform delivery control, fourteen inline paralinguistic tags (breath, cough, sigh, laughter, hesitation, surprise), explicit emotion, speed, pitch and volume, built-in voices like UK_George and US_Emma, seven languages plus Sichuanese and Cantonese dialects. The adoption decision then reads as a match between controls and use cases, with RTF entering through whichever budget you're inside. A twenty-times gap that buys style direction and cloning opens a second lane next to the one you keep for speed.
Where the slower lane still loses
Live calls. At RTF 0.85 a seven second line costs roughly 6.4 seconds to render, so Ming is wrong for anything duplex or turn-critical, the speech lane on my call stack stays on the fast model. The port carries three known gaps, CAM++ speaker embeddings never got extracted in MLX so cloning runs off reference audio plus transcript only, text normalization is unported so numbers go in written as words, and the stop head occasionally fails behind real speech. That last gap gets a number on the record before any listening, the trailing second of a sample sits at RMS 1439 out of 32767, a non-zero tail your ears judge as artifact or breath.
The trap that cost more than the model
The port requires mlx-audio 0.6.1 or newer because 0.6.0 and earlier versions say the wrong words, that's the prompt-contract fix in mlx-audio #1047. No benchmark table catches it, no exception fires, the model speaks fluently in the wrong sentence. I installed 0.6.3 and checked the floor before benching anything. Version floors on ports deserve the same treatment as quantization, a mismatch there produces plausible audio that fails transcription against what you asked for.
What shipped
Three clips went to listening, ming_freeform at 6.4 s, ming_tags at 7.4 s, ming_pitch at 7.3 s, all from cached runs on this box, plus the two lanes sitting side by side with Phonon still the default for speed. Adoption waits on listening to those three clips here, the vendor WER table never enters the decision. The ASR siblings in the same family (Ming-3.0-asr-tiny, Ming-3.0-audio-flash, community GGUFs at 12,399 downloads a month) are where the GPU boxes get them, since NVIDIA's 34B Transcribe wants H100-class hardware while both my cards already sit at 23,494 and 23,503 MiB of 24,576 used.
The claim survives on one number pair, 0.85 measured against 0.39 claimed, and on one rule, check the dependency floor before you bench because the silent failure mode speaks fluent garbage. Does anyone fold the version-floor check into their bench script, or is that still folklore? And what's your bar before adopting something twice off its card number?


Top comments (1)
The version-floor trap is the part that stayed with me — mlx-audio 0.6.0 and earlier speaking fluently in the wrong sentence, with no exception firing, is much scarier than a slow benchmark because you could ship it without noticing. I also liked the honesty about the first run: 33 seconds wall with 24 seconds of that being a download should not count as a benchmark, and n=2 cached clips at 0.85 and 0.87 is still more useful than a big vendor table. Keeping two lanes makes sense to me — Phonon at 0.043 for live calls, and this one for zero-shot cloning and delivery control even at roughly twenty times slower. Do you actually fold the version-floor check into a bench script now, or is it still a manual check before the run?