The decision
mlx-audio==0.4.5 implements VibeVoice-ASR, and mlx-community publishes converted weights.
Adopting that path deletes an entire provisioned environment (torch-vibevoice, 56 packages),
the tracked logits_to_keep patch, and a source checkout — and it roughly halves the memory.
It also replaces every recorded VibeVoice figure in model_tests/, because the transcript is
not the same. That trade is a product decision, not a technical unknown, which is why it is
parked here rather than settled in #11.
Evidence: model_tests/benchmark/results/2026-08-17-mlx-collapse-probes.json, runner
model_tests/benchmark/run_mlx_vibevoice_probe.py.
What is measured
Same audio, sha256-verified before loading (CantoMap 149.9 s), against the recorded torch run:
| Configuration |
Segments |
Peak |
Generate |
| torch bf16 + patch (recorded) |
49 |
20.84 GB MPS |
79.7 s |
| MLX bf16 |
47 |
20.74 GB |
275.1 s |
| MLX 8-bit |
47 |
12.43 GB |
56.3 s |
- 8-bit and bf16 MLX produce identical text on all 47 segments, so the divergence from torch
is the implementation and not quantization. That also makes 8-bit the only MLX configuration
worth having: bf16 costs the same memory as torch and is 3.5× slower for the same output.
- Full coverage on both sides (last segment end == duration), so 47-vs-49 is different
segmentation, not a truncated decode.
- Differences beyond the count: orthography shifts to traditional forms in places (
大樹 for
大树), at least one lexical difference (男人車站 for 蓝印车站), and non-speech event tags
disagree on the same interval ([Human Sounds] for [Silence]).
- Speaker structure survives:
mlx-audio maps VibeVoice's Speaker onto speaker_id and
omits the key entirely on non-speech segments, which is closer to the adapter floor than
torch's post-processed null.
Counter scopes differ between MLX and PyTorch MPS and must not be differenced across columns.
Within its own counter, 12.4 GB is the first VibeVoice figure that does not immediately rule out
a 16 GiB machine — the spec's "16 GiB is not validated" warning is about the 20 GB path.
What adopting it costs
Everything cited for vibevoice today came from the torch implementation, so each would need
re-running before it describes the shipped configuration:
- the 30-minute and 60-minute duration/stability runs, and the OOM behaviour under a strict cap;
- the
verbatim refutation (看哈 → 看一下) — it may not reproduce, or may differ;
- the diarization figures scored against CantoMap;
- the determinism basis: VibeVoice's acoustic tokenizer samples a Gaussian latent and the torch
path is seeded at 1234. Whether the MLX path has an equivalent knob is unchecked.
Plus one open question the probe did not touch: whether the 47-vs-49 segmentation is better or
worse. Neither side is scored against labels, so nothing here says which transcript is more
faithful — only that they differ.
Acceptance
Either decision is a fine outcome; both need to be recorded rather than left implicit.
- If adopted: re-run the list above on the MLX 8-bit path, replace the stack's figures, delete
requirements/torch-vibevoice.in and its lock (delete, not edit — torch-vibevoice is marked
provisional in the manifest for this reason), drop the patch and the checkout from the
manifest, and re-check the three adapter normalization cases against the new output shapes.
- If not: record why in ENVIRONMENTS.md, and drop the
provisional marker so
a future reader does not re-open a settled question.
Note the 16 GiB angle is the strongest argument for looking: model_tests/DECISION_REPORT.md
routes product-demo editing through this stack and warns it is not a 16 GiB pipeline. 12.4 GB
would change that sentence, and it is the sentence a user of that route reads first.
The decision
mlx-audio==0.4.5implements VibeVoice-ASR, andmlx-communitypublishes converted weights.Adopting that path deletes an entire provisioned environment (
torch-vibevoice, 56 packages),the tracked
logits_to_keeppatch, and a source checkout — and it roughly halves the memory.It also replaces every recorded VibeVoice figure in
model_tests/, because the transcript isnot the same. That trade is a product decision, not a technical unknown, which is why it is
parked here rather than settled in #11.
Evidence:
model_tests/benchmark/results/2026-08-17-mlx-collapse-probes.json, runnermodel_tests/benchmark/run_mlx_vibevoice_probe.py.What is measured
Same audio, sha256-verified before loading (CantoMap 149.9 s), against the recorded torch run:
is the implementation and not quantization. That also makes 8-bit the only MLX configuration
worth having: bf16 costs the same memory as torch and is 3.5× slower for the same output.
segmentation, not a truncated decode.
大樹for大树), at least one lexical difference (男人車站for蓝印车站), and non-speech event tagsdisagree on the same interval (
[Human Sounds]for[Silence]).mlx-audiomaps VibeVoice'sSpeakerontospeaker_idandomits the key entirely on non-speech segments, which is closer to the adapter floor than
torch's post-processed
null.Counter scopes differ between MLX and PyTorch MPS and must not be differenced across columns.
Within its own counter, 12.4 GB is the first VibeVoice figure that does not immediately rule out
a 16 GiB machine — the spec's "16 GiB is not validated" warning is about the 20 GB path.
What adopting it costs
Everything cited for
vibevoicetoday came from the torch implementation, so each would needre-running before it describes the shipped configuration:
verbatimrefutation (看哈→看一下) — it may not reproduce, or may differ;path is seeded at 1234. Whether the MLX path has an equivalent knob is unchecked.
Plus one open question the probe did not touch: whether the 47-vs-49 segmentation is better or
worse. Neither side is scored against labels, so nothing here says which transcript is more
faithful — only that they differ.
Acceptance
Either decision is a fine outcome; both need to be recorded rather than left implicit.
requirements/torch-vibevoice.inand its lock (delete, not edit —torch-vibevoiceis markedprovisional in the manifest for this reason), drop the patch and the checkout from the
manifest, and re-check the three adapter normalization cases against the new output shapes.
provisionalmarker soa future reader does not re-open a settled question.
Note the 16 GiB angle is the strongest argument for looking:
model_tests/DECISION_REPORT.mdroutes product-demo editing through this stack and warns it is not a 16 GiB pipeline. 12.4 GB
would change that sentence, and it is the sentence a user of that route reads first.