Community Research · Apple Silicon

Qwen3-ASR 在 macOS 上的社区优化

官方只给 PyTorch + CUDA/vLLM。社区用五条互相独立的路线把模型搬上 Apple Silicon:MLX 逐层重写、通用 MLX 音频库、原生 Swift/Rust、GGUF + Core ML/ANE、以及服务端双后端框架。本报告汇总可复跑的实测数据、优化手法、量化代价与踩坑清单,并标注每类证据的可信边界。

调研日期 2026-11-11 模型 Qwen3-ASR 0.6B / 1.7B 平台 macOS 14–27 · M1–M6 一手来源 12 处 零依赖 · 离线可读
0 · 结论速览 1 · 起点:官方边界与 MPS 为何不可用 2 · 五条技术路线对比 3 · 优化手法拆解(按层次) 4 · 实测数据汇总 5 · 量化:收益、代价与最优配方 6 · 踩坑清单与已知限制 7 · 可复跑命令 8 · 选型建议与你的场景 9 · 来源清单与证据分级

0结论速览

一句话:在 Mac 上跑 Qwen3-ASR,不要走官方 PyTorch/MPS,走 MLX 或 GGUF/Core ML;量化用「decoder 4-bit + encoder 8-bit」这条社区反复验证过的配方;流式与长音频的瓶颈在切分和 KV 复用,不在算子。

~3×–4×
MLX 相对 Torch/MPS
SGLang-Omni 跨 M1 Pro / M4 Pro / M5 Max / M6 的公开基准,吞吐与延迟同向;但两组精度不同(4-bit vs BF16),非严格同条件对比。
1.71×
0.6B 4-bit 相对 fp16
M4 Pro,10 s clip;代价是 LibriSpeech test-other WER 从 4.30% 升到 5.74%。8-bit 为 1.32× 且 test-clean 输出与 fp16 完全一致。
4.2×
混合 encoder 窗口化
长音频场景下最有效的单项算子优化;另有 WAV 直通(+25%)、原生 aligner(2.64×)。
0.53–0.55×
投机解码是负收益
0.6B 给 1.7B 打草稿,因 draft audio encoder 开销反而更慢,默认关闭。社区里少见的「明确记录失败优化」。

四个值得记住的判断

  1. 官方 MPS 不是「慢一点的可用路径」,是不可用。 MacWispr 实测 HF PyTorch 0.6B (MPS) 处理约 10 s 音频要 39 s、RTF 1.31;qwen3-asr-server 干脆把 DEVICE=mps 归一化成 cpu。
  2. 正确性比速度更早成为问题。 早期 MLX 移植用标准 nn.RoPE 代替 Qwen3 的 interleaved MRoPE(sections [24,20,20]),输出「看起来合理但质量下降」;这才是 mlx-qwen3-asr 选择逐层重写而非包装的根本原因。
  3. 量化敏感点在 audio encoder 与 embed_tokens,不在 decoder。 全 4-bit 的 0.6B WER 2.63%,encoder 保 8-bit 回落到 2.37%(fp16 2.33%),只多 90 MB。日语场景 4-bit embed_tokens 会出现 ~172% CER 的幻觉。
  4. 社区数据是「自报基准」,不是统一评测。 不同芯片、不同 checkpoint、不同精度、不同协议混在一起;跨项目比较 RTF/WER 前必须先看测试条件。详见第 9 节证据分级。

1起点:官方边界与 MPS 为何不可用

Qwen 团队于 2026 年 1 月开源 Qwen3-ASR 家族(Apache 2.0,技术报告 arXiv:2601.21337):0.6B / 1.7B 两个识别模型 + Qwen3-ForcedAligner-0.6B 非自回归对齐器,支持 30 语言 + 22 中文方言(共 52 种),离线/流式统一,单条长音频最长 20 分钟。0.6B 在并发 128 下官方宣称 TTFT 低至 92 ms、1 秒可转写 2000 秒语音。

维度官方提供对 macOS 的含义
推理后端qwen-asr 的 transformers / vLLM 两套;流式仅 vLLMvLLM 官方安装指向 CUDA nightly wheel(cu129),Mac 无对应路径
设备与算子示例 device_map="cuda:0"、flash-attn(仅 fp16/bf16)、gpu_memory_utilizationFlashAttention 2 与 CUDA graph 均不可用
实际 fallback官方文档未列 Apple GPU 支持transformers 后端在 Mac 上落 CPU,社区实测比 MLX 慢 7–20×
服务端兼容路径—SGLang-Omni 的 Torch/MPS 只是「compatibility and correctness path」,且限制很多(见 6 节)

来源:Qwen 官方博客、QwenLM/Qwen3-ASR、mlx-qwen3-asr 项目背景(DeepWiki 整理) 一手 第三方整理

关键对照: MacWispr 的 M5 系列 ~10 s 音频阶梯测试里,HF PyTorch 0.6B (MPS) 为 39 s / RTF 1.31,项目直接标注「Not viable for dictation」;同条件下 MLX 0.6B 8-bit 约 0.4 s / RTF ~0.04,差距约两个数量级。另 guoqing1988/qwen3-asr-server README 明确写 DEVICE=mps 会直接归一化为 cpu,macOS 走 vendored QwenASR Rust(CPU)。

2五条技术路线对比

官方 Qwen3-ASR(PyTorch + CUDA / vLLM) 在 macOS 上只能 CPU fallback → 社区在下面五条线上各自补齐 Metal / ANE 路径 A · MLX 逐层重写 moona3k/mlx-qwen3-asr Python · 无 PyTorch 依赖 735 tests / 160+ artifacts parity 门 + 流式 + server 最严谨 · 可复跑 B · 通用 MLX 库 Blaizzy/mlx-audio mlx-community 量化权重 3/4/6/8-bit · REST · 对齐器 上层 App / 插件大多基于它 生态最广 C · 原生 Swift / Rust mlx-swift-asr / speech-swift MLState · Metal warmup 无 Python · App 内嵌 Ominix / MacWispr / Dictate 首延迟最优 D · GGUF + Core ML transcribe.cpp / Handy Q8_0 / Q4_K_M · ANE encoder 单 C++/Rust 二进制 Glimpse / CapsWriter 无 Python · 跨 Intel E · 服务端双后端 sgl-project/sglang-omni MLX vs Torch/MPS OpenAI Audio API / realtime Discussion #2158 跨芯片基准 唯一严格对照 共同工程底座 16 kHz mono 输入 · 128-bin log-mel(400 FFT / 160 hop) · 交错 MRoPE [24,20,20] · GQA + QK Norm + SwiGLU · 低能量点 30 s 切分 · KV cache 复用
路线代表项目运行形态 / 依赖最突出优势主要短板
A · MLX 重写moona3k/mlx-qwen3-asr 一手Python 3.10+,仅 mlx / numpy / regex / huggingface-hub;CLI + Session API + HTTP server严格 parity 质量门、735 tests、160+ 可复跑 JSON artifacts;优化与质量损失逐项量化需要 Apple Silicon;非 WAV 仍需 ffmpeg;speculative decoding 暂不可用
B · 通用库Blaizzy/mlx-audio + mlx-community 一手pip 安装,20+ TTS / 15+ STT 共用接口;OpenAI 兼容 REST;Swift package量化梯度最全(3/4/6/8-bit),上游生态与 App 最多早期版本有 RoPE 与 30 s 截断问题;model_quant_predicate 阻碍自定义混合精度权重
C · 原生 Swift/Rustontypehq/mlx-swift-asr、soniqo/speech-swift、macwisprSPM 包 / 原生 App,macOS 15+(部分 14+);Swift 6.2+消除 Python 开销;Metal shader warmup、MLState 常驻 KV;适合听写级首延迟模型覆盖与功能少于 Python 线;Core ML 全 ANE 路径要求 macOS 15+
D · GGUF / Core MLtranscribe.cpp、Glimpse Core ML encoder、CapsWriterggml C++ / Rust 单二进制;Metal、Vulkan、CPU;GGUF + 可选 .mlmodelc无需 Python/torch,Intel Mac 也能跑;1.7B Q4_K_M 仅 1.23 GB 且 WER 1.81%GGUF 路径暂无原生流式;Core ML encoder 单次仅 15 s;ANE 执行不保证独占
E · 服务端框架sglang-omni RFC #1967默认 Torch/MPS;SGLANG_USE_MLX=1 切原生 MLX worker;OpenAI Audio / SSE / realtime WebSocket唯一有跨芯片、带 commit 与协议的公开对照;适合服务化部署MPS 路径能力受限(60 s、2048 token KV);realtime 在 Apple 双后端尚未完整 qualify

上层应用与插件(都落在 B / C 线上)

项目macOS 上的具体做法值得借鉴的点
MacWhisper 0.8.0 一手菜单栏听写 App;Qwen3-ASR 独占 .venv-qwen,默认 mlx-community/Qwen3-ASR-0.6B-bf16(~2.9 GB),1.7B ~7.6 GB 按需下载;macOS 14+HF commit 固定(model_revisions.py)避免上游静默变更;热词(context)作领域词表;collapse_repeats 只裁 6+ 次失控重复;v0.8.0 直接移除 Whisper 并自动迁移旧配置
dsh-plugin-local-voice 1.6.1 二手介绍DSH Desktop 插件;mlx-audio==0.5.5 + Qwen3-ASR-1.7B-8bit(~2.47 GB,默认从魔搭拉);浏览器内 16 kHz 重采样 + 能量切句(静音 ~0.7 s 出一行、单段 9 s 强制切)常驻 qwen3_worker.py 进程,模型只加载一次;首次转写懒启动、空闲 5 分钟回收;启动时探测 darwin/arm64 + 解释器 + 模型目录,任一不满足就不注册 Qwen3 并回落到 SenseVoice;可选 LLM 校对默认关闭以保持零外网
LobeHub Qwen ASR Skill 二手0.6B-4bit(~400 MB)+ FastAPI :8100,/health /info /transcribe_url;国内走 hf-mirror.com把模型封装成 Skill 可调用服务;无需 Docker
handy-transcribe 一手Rust 单二进制 CLI,解码 → VAD 分块 → transcribe.cpp(ggml) → 拼接;M1 Pro 上 972 s 中文技术演讲用 0.6B Q8_0 49 s 转完(~20× 实时)适合给智能体/脚本调用的无头批处理;无 Python、无 torch、无 API key
Ominix ASR 二手Rust + MLX 三级流水线:0.6B 8-bit 识别 → Qwen3-1.7B-4bit 润色/翻译 → Qwen3-4B-4bit 摘要;M4 上 10–20× 实时增强模型空闲自动卸载、MLX 内存软上限 + 清缓存/图编译缓存;domain.txt 术语热加载
qwen3-asr-server 一手兼容 OpenAI Audio API;DEVICE=mps 归一化为 cpu;macOS 走 vendored QwenASR Rust,默认 0.6B「两级空闲释放」「远场过滤」等服务端工程;但 Mac 上不是 GPU 路径

3优化手法拆解(按层次)

下表把散落在各仓库 README、模型卡与 PR 里的优化按「框架 → 算子 → 内存 → 数据通路 → 系统」分层,尽量只保留有数字或有明确实现位置的条目。

层次手法实现位置 / 命令报告收益证据
框架用 MLX 逐层重写,绕开 PyTorch/MPSencoder.py / decoder.py / mrope.py / attention.py;依赖仅 mlx numpy regex huggingface-hub相对 Torch/MPS 约 2.3×(M1 Pro)~3.9×(M5 Max)~3× 吞吐(M6)一手
正确的 interleaved MRoPE(sections [24,20,20],stride-3 频率分配)mrope.py不是加速项,是正确性前提;其他 port 常用标准 RoPE 导致质量静默下降一手 背景为第三方整理
原生 Swift / Rust 消除 Python 开销Qwen3ASRSTT、transcribe.cpp ggmlM1 Pro Swift RTF 0.15–0.27;M1 Pro Rust CLI ~20× 实时一手
算子 / 注意力混合 encoder 窗口化(短音频 dense block-diagonal mask,长上下文按窗口分段执行)hybrid encoder windowing长音频最高 4.2×一手
GQA 融合注意力,不显式展开 K/V headsmx.fast.scaled_dot_product_attention未单独给出倍数(组合收益)一手
缓存 mel filterbank 与 Hann windowWhisper-compatible 128-bin log-mel,MAE < 3e-7 vs WhisperFeatureExtractor避免重复计算;parity 已验证一手
Core ML MLState 让 KV cache 常驻 ANEspeech-swift,macOS 15+ / iOS 18+,KV cache 固定 1024 tokensper-token CoreML latency 降 30–50%(相对早期 stateless)厂商 FAQ
内存 / 长音频预分配 KV cache + in-place slice 写入 + 可回滚裁剪generate.py组合收益;流式复用完整 8 s attention window 的 encoder 输出与 decoder KV一手
低能量点切 30 s chunk,chunk 间释放内存chunking.py;SGLang 默认 max_audio_clip_s=30避免 30 s 特征截断;80 s clips 上 MLX 10.59% vs PyTorch 17.99% primary error一手
模型与 tokenizer 实例缓存 / 常驻进程Session;dsh-plugin 的 qwen3_worker.py重复调用免重载;常驻进程 + 懒启动 + 空闲 5 min 回收一手 二手
数据通路原生 WAV 二进制 fast path 绕开 ffmpeg 进程启动PCM/float WAV 自定义 parser量化短片段最高 +25%;WAV 可完全不装 ffmpeg一手
内置 BPE tokenizer,推理路径不依赖 transformerstokenizer.py减少依赖冲突与加载开销一手
16 kHz 直采 + Metal shader warmup + 动态 max tokensmacwispr AudioRecorder.swift / warmup / dynamic budget免去重采样、消除首次听写冷启动、不再固定 448 tokens一手
周边任务原生 MLX forced aligner(Fenwick tree / O(n log n) LIS 校正)forced_aligner.py2.64×(0.21 s vs 0.56 s,n=50),100% 文本一致、时序 MAE 5.69 ms一手
说话人分离 offload 到 MPS--diarize-device {auto,cpu,mps,cuda},默认 auto 优先 MPSM 系列上从「分钟级」降到「秒级」,输出一致一手
domain context / 热词注入 system promptcontext="EBITDA non-GAAP FX hedging"专业术语纠错;空 system prompt 与官方默认一致一手
不要把「优化」等同于「一定更快」。 mlx-qwen3-asr 把投机解码明确标成实验特性且默认关闭:0.6B 给 1.7B 打草稿在短/10 s 片段上只有 0.53–0.55×,原因是 draft audio encoder 的开销吃掉了收益。这是社区里少见的、把失败优化也写进 README 并留下 benchmark artifact 的案例。

4实测数据汇总

4.1 路线 A:M4 Pro 48 GB / macOS 26 / v0.4.0(延迟,10 次中位数)

配置短片段 ~2.5 s10 s 片段RTF (10 s)相对 fp16
0.6B fp16(基线)0.17 s0.30 s0.029—
0.6B 8-bit (g64)0.10 s0.23 s0.0241.32×
0.6B 4-bit (g64)0.09 s0.17 s0.0181.71×
1.7B fp160.36 s0.73 s0.077慢 2.4×

质量(LibriSpeech,每子集 100 speaker-balanced 样本):0.6B test-clean WER 2.33% / CER 0.59%,test-other 4.30% / 2.11%;1.7B test-clean 1.94% / 0.57%,test-other 3.45% / 1.48%。FLEURS 10 语言 ×10 样本:0.6B 9.54%、1.7B 6.70%(相对改善 30%,延迟 1.9×)。内存:0.6B fp16 ~1.2 GB,1.7B ~3.4 GB。

来源:moona3k/mlx-qwen3-asr README + docs/BENCHMARKS.md + docs/benchmarks/ 内 160+ JSON artifacts 一手

4.2 路线 E:SGLang-Omni 跨芯片 MLX vs Torch/MPS

芯片 / 环境工作负载MLXTorch/MPS口径
M1 Pro 32 GB · macOS 15.3短 M4A,官方 ckpt 5eb1441,2 warmup + 10 measuredp50 0.24 s / p95 0.26 s;启动 14.7 s;KV 52034p50 0.55 s / p95 0.64 s;启动 16.7 s;KV 2048同 checkpoint、同协议,约 2.3×
M4 Pro 16-core GPU 24 GB · 26.6.2full SeedTTS EN4-bit:11.601 samples/s,RTFx 54.945,WER 1.9143%,mean 85.91 ms—commit 69ddc6ba
M5 Max 24 GB · 26.6.2单请求 smoke,query_to_cars.wav4-bit:median 0.047 s / p95 0.048 s,10/10 正确BF16:0.182 s / 0.184 s约 3.9×;精度不同,非 apples-to-apples
M6 24 GB · 27.0.1full SeedTTS EN 1,088 clips,3 passes,3,264/3,264 完成4-bit:10.768 samples/s,RTFx 50.999,WER 1.8992%,mean 91.37 ms / p95 110.09 msBF16:3.555 samples/s,RTFx 16.837,WER 1.5436%,mean 280.11 ms / p95 365.39 ms吞吐约 3×,但 4-bit WER 高 0.36pp

讨论里的结论原文:MLX/Torch 差异「在吞吐、延迟、RTF、Metal footprint 与 swap 行为上方向一致且量级很大」。RFC 另记录 Fun-ASR 1000-clip 持续负载下 MLX worker RSS 稳定在 ~2.3 GB,而 Torch/MPS 为 2.0–4.1 GB 锯齿(PyTorch MPS caching allocator,有界、非泄漏,但需纳入容量规划);以及未标注模型的一组原始数据:weight load 1.28 s vs 4.51 s、KV pool 6164 vs 2048 tokens、warm request 0.33/0.41 s vs 0.58/0.61 s。

来源:Discussion #2158、RFC #1967 一手 注意:M5/M6 与 macOS 27 的条目为社区自报,未经独立复现。

4.3 路线 C / D:Swift、ANE 与 GGUF

项目 / 条件数据说明
mlx-swift-asr,M1 Pro / macOS 15.3,0.6B-6bit ~400 MBRTF 0.159–0.264(3.8–6.3× 实时);典型 0.15–0.27纯推理耗时,不含模型加载与 Metal warmup(3–5 s)
speech-swift FAQ,M5 ProQwen3-ASR-0.6B RTF 0.012厂商自报:约 7× 快于 WhisperKit large-v3 turbo(0.084)、比 whisper.cpp large-v3(0.10)快 40%;0.6B 4-bit 峰值 ~1.0 GB
macwispr,M5 系列 ~10 s 音频,MLX 三次取最优0.6B 4-bit 0.60 s / RTF 0.060;0.6B 8-bit ~0.4 s / ~0.04(默认);1.7B 4-bit ~1.20 s / 0.120;1.7B 8-bit 0.77–1.78 s / 0.08–0.18对照 HF PyTorch 0.6B (MPS) 39 s / RTF 1.31
Handy 1.7B GGUF 模型卡,Apple M4 metal backend,全量 LibriSpeech test-clean 2,620 条BF16/F16 1.62%(3.80/3.81 GB);Q8_0 1.61%(2.04 GB);Q6_K 1.65%(1.58 GB);Q5_K_M 1.65%(1.41 GB);Q4_K_M 1.81%(1.23 GB)Whisper 英文 normalizer + jiwer 3.x;BF16~Q5_K_M 落在 bootstrap CI 内,Q4_K_M 仅退化 ~0.2pp → 1.7B 比 0.6B 量化余量更大
handy-transcribe,M1 Pro972 s 中文技术演讲,0.6B Q8_0 用 49 s(~20× 实时)Rust 单二进制,VAD 分块后拼接

4.4 MLX 与官方 PyTorch 的 parity(正确性证据)

指标(0.6B,100 条多语言)MLXPyTorch差值
Primary error rate9.54%10.34%−0.81pp
WER16.00%16.69%−0.70pp
CER5.43%5.64%−0.21pp

68% 片段文本完全一致,差异多为数字/拼写/标点的表面形式;encoder 输出与 fp32 PyTorch 参考 MAE 0.003(v0.4.1 tail-padding 修复后尾部降到 0.005 以内);mel MAE < 3e-7。真实会议混合集(AMI IHM + Earnings22,n=200)MLX 23.23% vs PyTorch 23.04%,差 0.19pp。重要 caveat:PyTorch 参考在 Mac 上跑 CPU,慢 7–20×,README 自己声明这不是同硬件 GPU 对比;80 s 长片段 10.59% vs 17.99% 的优势主要来自 MLX 在停顿处切分,而非模型本身更准。

5量化:收益、代价与最优配方

社区在量化上做了两轮独立实验,结论高度一致:别整模型一刀切 4-bit,encoder 与 embedding 要区别对待。

配置(0.6B,LibriSpeech 100 speaker-balanced / 子集)test-clean WERtest-other WER速度(10 s clip)
fp162.33%4.30%1.00×
8-bit (g64)2.33%(输出完全一致)4.14%1.32×
4-bit (g64)2.59%5.74%1.71×
最优配方:decoder 4-bit + audio encoder 8-bit(group size 64)。 0.6B 全 4-bit 是 2.63% WER,把 encoder 提到 8-bit 后回落到 2.37%(fp16 2.33%),代价只多 90 MB。mlx-qwen3-asr 官方预量化产物就按这个配方发布:0.6b-4bit 517 MB / WER 2.37%,0.6b-8bit 801 MB / 2.33%(与 fp16 完全一致),1.7b-4bit 1.2 GB / 1.73%,1.7b-8bit 2.0 GB / 1.94%。混合精度权重需要 mlx-qwen3-asr >= 0.4.3 的 per-module loader,旧版本会 shape error。

独立消融:16 种量化配置(Common Voice 22.0,zh-TW / en / ja / ko)

社区模型卡 Alkd/Qwen3-ASR-1.7B-audio8-text4-mlx 做了 16 配置系统消融,选出 audio_tower 8-bit + model.layers 4-bit + embed_tokens 4-bit,与 mlx-community/Qwen3-ASR-1.7B-4bit 在相同条件下对比(n=1000):

指标混合精度mlx-community 4-bit差值
磁盘体积1,253 MB1,529 MB−18.0%
zh-TW CER3.670%3.644%+0.026pp(噪声内)
en WER6.458%6.482%−0.024pp
速度 zh-TW0.244 s/样本0.268 s/样本快 9.9%
速度 en0.294 s/样本0.318 s/样本快 7.5%
加载时 RAM 增量~0 MB+1,095 MB显著
两个量化陷阱:
① 日语幻觉:embed_tokens 量化到 4-bit 时,日语等语言出现 ~172% CER 的幻觉(mlx-community 4-bit 为 174%),是 4-bit embedding 的固有局限,不是某个转换脚本的问题。做中日韩多语种要保留 8-bit/bf16 embedding。
② mlx-audio 的 model_quant_predicate 硬编码:return not path.startswith("audio_tower") 无条件禁止 audio_tower 量化,导致自定义混合精度权重会被静默加载进未量化 Linear,shape 不匹配并产出空转写。该模型卡给出的绕过方案是:先加载 bf16 基座 → 手动 nn.quantize(...) 两次(audio 8-bit / text 4-bit)→ model.load_weights(saved, strict=True)。

6踩坑清单与已知限制

#坑现象规避 / 现状严重度
1标准 RoPE 代替 interleaved MRoPE输出「读着通顺但 WER 变差」,极难从单条样本发现用带 parity 门的实现;核对 sections [24,20,20] 与 stride-3 频率分配高
230 s 特征截断(mlx-audio Issue #459,第三方整理提及)长录音只转出前 30 s选支持低能量点 30 s chunking 的实现,或用 SGLang 的 max_audio_clip_s高
3ffmpeg@7 + TorchCodec(SGLang Apple Silicon)无版本化 ffmpeg 会装到 FFmpeg 9,而 torchcodec==0.11.1 只支持 FFmpeg 4–8;ffmpeg@7 是 keg-only,必须显式加 DYLD_LIBRARY_PATHbrew install ffmpeg@7;不要替换成非版本化 formula;用 M4A/MP3 测解码,WAV 可能不触发 FFmpeg 加载而掩盖问题高
4macOS SIP 剥离 DYLD_*经 SIP 保护的可执行文件启动服务时环境变量丢失把 DYLD_LIBRARY_PATH 设在最终的 sgl-omni 进程上,例如在 /usr/bin/time 之类 wrapper 之后放 /usr/bin/env DYLD_LIBRARY_PATH=...高
5Torch/MPS 兼容路径能力受限tp_size=1、greedy、eager torch_native/sdpa;无 radix caching / chunked prefill / CUDA graphs;KV 预算 2048 tokens;native 与 streaming 都卡 60 s;无 token logprobs长音频用 stream=false 让服务端按 30 s 分块;要性能就 SGLANG_USE_MLX=1中高
6语言 hint 严格不支持的 hint 直接 HTTP 400(不静默回落英文);22 种中文方言名不能强制,只能用 Chinese/zh预先规范化;旧写法 cn / zh-* 会被接受为 Chinese中
7流式质量与稳定性final text 比 offline 差约 2pp(多语 11.3% vs 9.5%,长音频 11.9% vs 10.6%);stable_text 设计上单调,缩短已稳定前缀的修正不会应用对最终稿再跑一次 offline 或 tail re-decode;SRT/VTT 仅离线模式支持中
8投机解码负收益短/10 s 片段 0.53–0.55×保持关闭,等 draft encoder 开销被优化低
9长音频重复(SGLang Issue #2150)长录音出现循环重复;repetition_penalty > 1 可压制但会伤干净音频准确率仍 open,缺少可复现的原始片段;MLX 路径的 repetition_penalty 转发在 #2157中
10realtime WebSocket 未完成 Apple 双后端资格验证VAD、partial/final、clear/cancel、断连恢复、长会话缺完整矩阵;#2214 只有 M4/16 GB 的 MLX smoke不要把 uploaded-file SSE 的证据当作 live PCM 的证据中
11Core ML encoder 15 s 上限 / ANE 不独占长音频必须切块;官方模型卡明说部分算子可能跑在 CPUGlimpse 自动切分;不要把「Core ML」直接等同于「省电 ANE」低
12版本与口径漂移早期媒体稿写 441 tests / 4-bit 提速 4.7× / 2.5 s 音频 0.46 s;当前 README 是 735 tests / 1.71× / 0.17 s(不同版本与 workload)引用时必须带版本、芯片、片段长度与测试协议;以仓库 docs/benchmarks/ 的 JSON artifacts 为准中

7可复跑命令

A · 最省事的本地转写(路线 A,推荐配方)

pip install -U mlx-qwen3-asr
brew install ffmpeg                     # 仅非 WAV 格式需要
mlx-qwen3-asr meeting.mp3 --model moona3k/mlx-qwen3-asr-0.6b-4bit -f srt -o out/
mlx-qwen3-asr --doctor                  # 环境自检
pytest -q                               # 735 tests(源码安装)
python scripts/eval_librispeech.py --subset test-clean --samples 100 \
  --sampling speaker_round_robin        # 质量复跑

B · 自定义量化 / 通用库

python scripts/convert.py --model Qwen/Qwen3-ASR-0.6B \
  --quantize 4 --encoder-bits 8 --group-size 64 --output-dir ./qwen3-asr-4bit

uv run mlx_audio.stt.generate \
  --model mlx-community/Qwen3-ASR-0.6B-8bit \
  --audio audio.wav --output-path output --stream

C · 服务化(OpenAI 兼容 / 双后端对照)

# mlx-qwen3-asr 自带 server
pip install "mlx-qwen3-asr[serve]"
mlx-qwen3-asr serve --api-key $(openssl rand -hex 16)   # :8765/v1

# SGLang-Omni Apple Silicon(注意 keg-only ffmpeg)
brew install ffmpeg@7
export DYLD_LIBRARY_PATH="$(brew --prefix ffmpeg@7)/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
SGLANG_USE_MLX=1 sgl-omni serve \
  --model-path Qwen/Qwen3-ASR-0.6B --model-name Qwen/Qwen3-ASR-0.6B \
  --asr.engine.max_running_requests 1 --port 8000

D · GGUF / Core ML 路线

ffmpeg -i input.mp3 -ar 16000 -ac 1 -c:a pcm_s16le input.wav
build/bin/transcribe-cli -m Qwen3-ASR-1.7B-Q8_0.gguf input.wav
# Core ML encoder:把 .mlmodelc 解压到 GGUF 同目录,运行时自动探测并回落

E · DSH 插件(与你的插件生态直接相关)

dsh plugin --profile desktop add dsh-plugin-local-voice
uv venv ~/.local/venvs/mlx-audio --python 3.12
~/.local/venvs/mlx-audio/bin/pip install "mlx-audio==0.5.5" sounddevice numpy huggingface_hub
python3 scripts/prepare_model.py            # 1.7B-8bit ~2.47 GB,默认魔搭
python3 scripts/prepare_model.py --source hf-mirror   # 或 hf

8选型建议与你的场景

目标推荐理由 / 注意
命令行批处理、CI 可复跑、写技术结论mlx-qwen3-asr + 0.6b-4bit(encoder 8-bit)唯一把每个优化都绑 quality gate 并留下 JSON artifacts 的实现;docs/BENCHMARKS.md 有 exact commands
要服务化、多并发、OpenAI Audio APISGLang-Omni + SGLANG_USE_MLX=1;或 mlx-qwen3-asr serve前者有分块调度与并发护栏(max_total_audio_s=3600 等);后者更轻,长音频用 async job API 避免 HTTP 超时
做 macOS/iOS 原生 App、追求首延迟ontypehq/mlx-swift-asr(最小)或 soniqo/speech-swift(双后端)Metal shader warmup、MLState KV 常驻;注意 Swift 库要 macOS 15+ / Swift 6.2+;别忘 warmup 的 3–5 s 要放在启动阶段
不想引入 Python / 需要 Intel Mac 也能跑transcribe.cpp GGUF(Q8_0 或 Q5_K_M)1.7B Q5_K_M 1.41 GB、WER 1.65%;GGUF 无原生流式,需自己做 VAD 分块
中文方言 / 长会议 / 要词级时间戳1.7B 8-bit 或 bf16 + 30 s 能量切分 + --diarize-device mps1.7B 多语相对改善 30%,延迟 1.9×;8-bit 在 test-clean 与 fp16 输出一致;diarize 不支持 streaming/mic
DSH 插件 / 常驻语音输入参考 dsh-plugin-local-voice 的进程模型常驻 worker + 懒加载 + 空闲回收 + 平台探测降级,是「模型 2.47 GB 不能每次重载」的正确解;若你做新插件,可考虑把后端换成 mlx-qwen3-asr 以拿到 WAV fast path 与原生 aligner
Reachy Mini 之类本地语音链路(Mac MPS)0.6B 4-bit MLX + 流式窗口(默认 2 s chunk / 30 s context)RTF 0.08 有充足余量给 VAD 与 TTS;注意 streaming 与 offline 约 2pp 质量差,最终文本可再跑一次 offline 修正
三个「不要」:① 不要直接用官方 qwen-asr + device_map="mps" 期待 GPU 加速;② 不要对日语/韩语用 4-bit embed_tokens;③ 不要为 1.7B 打开投机解码(当前净变慢)。另外,跨项目比 RTF 之前先确认是否含模型加载/Metal warmup——Swift 线普遍标注「inference only」,而 Python 线常含冷启动。

9来源清单与证据分级

等级来源用途
一手Qwen 官方博客、QwenLM/Qwen3-ASR模型规格、后端边界、官方性能口径
一手moona3k/mlx-qwen3-asr README、1.7b-4bit 模型卡路线 A 的全部优化、延迟/WER/parity 数据、预量化配方
一手RFC #1967、Discussion #2158、qwen3_asr cookbook双后端设计、跨芯片基准、Apple Silicon 安装坑与 MPS 限制
一手mlx-audio 中 Qwen3-ASR README、mlx-community 4-bit 模型卡、mlx-audio-swift 模型矩阵路线 B 的 API、量化梯度、转换来源(mlx-audio 0.3.1)
一手ontypehq/mlx-swift-asr、soniqo FAQ、macwispr README、MacWhisper README路线 C 的 Swift 基准、MLState、MPS 不可用对照、App 工程实践
一手Glimpse Core ML 模型卡、Handy 1.7B GGUF 卡(镜像)、handy-transcribe、CapsWriter 模型支持路线 D 的 GGUF WER 阶梯、Core ML 限制、Rust CLI 实测
一手Alkd 混合精度模型卡、qwen3-asr-server16 配置消融、model_quant_predicate 坑、macOS CPU 归一化
二手夜雨飘零:dsh-plugin-local-voice、LobeHub Qwen ASR Skill、Ominix ASR 介绍、BestHub 转载、CSDN mlx-audio-swift 教程、dev.to GGUF 文章中文社区实践、Skill/插件封装、早期版本数据(口径已漂移,见 6 节 #12)
第三方整理DeepWiki 项目背景、Next Gen Tech Insider、Bright Coding发布时间、mlx-audio 早期 RoPE / 截断问题的转述、speech-swift 概览;这类结论需回原始仓库复核
证据边界(读数据时请一并带上):