架构
speech-swift 是一个模块化的 Swift 包,由共享协议、独立的模型模块和统一的 CLI 组成。所有推理都在端侧使用 MLX(Metal GPU)或 CoreML(Neural Engine)运行。
模块依赖图
┌──────────┐
│ AudioCLI │ (entry point)
└────┬─────┘
│
┌──────┴──────┐
│ AudioCLILib │ (commands)
└──────┬──────┘
│
┌─────────┬───────┼───────┬──────────┬──────────────┐
│ │ │ │ │ │
┌────┴───┐ ┌──┴──┐ ┌──┴──┐ ┌─┴────┐ ┌───┴────┐ ┌──────┴───────┐
│Qwen3ASR│ │Qwen3│ │Cosy │ │Perso-│ │Speech- │ │ Speech- │
│Parakeet│ │ TTS │ │Voice│ │naPlex│ │ VAD │ │Enhancement │
└────┬───┘ └──┬──┘ └──┬──┘ └──┬───┘ └───┬───┘ └──────┬───────┘
│ │ │ │ │ │
└────────┴───────┼───────┴─────────┘ │
│ │
┌──────┴──────┐ │
│ Qwen3Common │ (shared layers) │
└──────┬──────┘ │
│ │
┌──────┴──────┐ │
│ AudioCommon │ ◄──────────────────────┘
└─────────────┘ (protocols, audio I/O)MOSS Transcribe Diarize
MossTranscribe 通过原生 CoreML 和 MLX 后端返回带说话人标记的时间戳分段。CoreML 为短音频使用固定 1,024-token 状态;MLX 使用动态 131,072-token 上下文、仿射 INT5/INT8 解码器权重及可选 FP16/INT8 KV 缓存。两者均为离线自回归运行时,不支持流式输出。
VoiceChat 11B
任务与参考:双工语音到语音(speech-to-speech);SALM-Duplex: Efficient and Direct Duplex Modeling for Speech-to-Speech Language Model(Interspeech 2025),由 NVIDIA 上游 VoiceChat 模型卡引用。
完整运行时,M5 Pro 48 GB,Release,80 ms 实时节奏:保护输出头的 INT5 峰值 RSS 约 8.69 GB;三次受控的全流程 RTF 结果为 0.96、0.96 和 0.99。优化后的 INT8 性能尚未重新测量。
VoiceChat 实现完整的原生 MLX 音频到音频路径:因果 FastConformer 感知、Nemotron-H 双工文本/函数通道、采用八次 MaskGIT 迭代的独立文本条件 EAR-TTS 解码器,以及 22.05 kHz 神经音频编解码器。流式处理保留有界的逐层注意力和因果卷积缓存,稳态的八帧实时编解码器窗口则使用编译图。每个 80 ms 输入帧都会产生一次语言决策、31 个 RVQ 码和恰好 1,764 个输出采样。加载器要求完整的 encoder/ + llm/ + tts/ bundle,并拒绝旧的仅理解导出。INT5 现在可在测试的 M5 Pro 上持续保持低于 1 的总体 RTF,但每帧 p95 余量仍然很小。
推理后端
| 后端 | 硬件 | 模型 |
|---|---|---|
| MLX | Metal GPU | Qwen3-ASR、Qwen3-TTS、CosyVoice3、Qwen3.5-Chat、PersonaPlex、VoiceChat 11B、Omnilingual ASR (300M / 1B / 3B / 7B)、Cohere Transcribe 2B, Voxtral Mini 3B, Pyannote、Silero VAD、WeSpeaker, MOSS Transcribe Diarize, SpeechBrain ECAPA LID |
| CoreML | Neural Engine | Qwen3-ASR 编码器(混合)、Parakeet TDT、Parakeet EOU 流式、Omnilingual ASR 300M、Kokoro-82M、Qwen3.5-Chat(可选)、Sortformer 说话人分离、DeepFilterNet3、Silero VAD(可选)、WeSpeaker(可选), MOSS Transcribe Diarize, SpeechBrain ECAPA LID |
| Accelerate | CPU (SIMD) | 音频预处理(STFT、mel、FFT)、信号处理 |
模型权重格式
MLX 模型采用 safetensors 格式,使用 4 位或 8 位量化(group size 64)。CoreML 模型采用 .mlmodelc 编译格式。scripts/ 中的转换脚本将 PyTorch checkpoint 转换为相应格式。
Cohere 和 Voxtral 还提供 MLX 仿射 INT5 包。MLX 不支持仿射 INT7;INT8 是受支持的更高质量选项。
| 模型 | 参数量 | 量化 | 磁盘大小 |
|---|---|---|---|
| Qwen3-ASR 0.6B (MLX) | ~600M | 4-bit / 8-bit | 680 MB / 1.0 GB |
| Qwen3-ASR 0.6B (CoreML) | ~186M(编码器) | INT8 | ~180 MB |
| Qwen3-ASR 1.7B (MLX) | ~1.7B | 4-bit / 8-bit | 2.1 GB / 3.2 GB |
| Parakeet-TDT 0.6B (CoreML) | ~600M | INT8 | 500 MB |
| Whisper Large-v3 Turbo (CoreML) | 809M | FP16 | 1.6 GB |
| MOSS Transcribe Diarize 0.9B (MLX) | 908.5M | FP16 audio + INT5 / INT8 decoder | 987.0 MiB / 1,200.1 MiB |
| MOSS Transcribe Diarize 0.9B (CoreML) | ~900M | FP16 / INT8 block-32 | 1.7 GB / 1.2 GB |
| Parakeet-EOU 120M (CoreML) | ~120M | INT8 | ~120 MB |
| Omnilingual-ASR-CTC 300M (CoreML) | 326M | INT8 | 312 MB |
| Omnilingual-ASR-CTC 300M (MLX) | 326M | 4-bit / 8-bit | 193 MB / 342 MB |
| Omnilingual-ASR-CTC 1B (MLX) | 1.01B | 4-bit / 8-bit | 549 MB / 1006 MB |
| Omnilingual-ASR-CTC 3B (MLX) | ~3B | 4-bit / 8-bit | 1.71 GB / 3.16 GB |
| Omnilingual-ASR-CTC 7B (MLX) | ~7B | 4-bit / 8-bit | 3.55 GB / 6.63 GB |
| Cohere Transcribe 2B (MLX) | 2B | FP16 / INT5 / INT8 | 3.85 / 1.62 / 2.25 GiB |
| Voxtral Mini 3B 2507 (MLX) | 3B | FP16 / INT5 / INT8 | 8.71 / 3.77 / 5.18 GiB |
| Qwen3-ForcedAligner 0.6B (MLX) | ~600M | 4-bit / 8-bit | 979 MB / 1.4 GB |
| Qwen3-ForcedAligner 0.6B (CoreML) | ~600M | INT4 / INT8 | 630 MB / 1.0 GB |
| Qwen3-TTS 0.6B (MLX) | ~600M | 4-bit / 8-bit | 1.7 GB / 2.4 GB |
| Qwen3-TTS 1.7B (MLX) | ~1.7B | 4-bit / 8-bit | 3.2 GB / 4.8 GB |
| CosyVoice3 0.5B (MLX) | ~500M | 4-bit LLM | ~1.2 GB |
| IndexTTS2 expanded bundle (MLX) | 1.5B-class | FP16 + auxiliary models | ~4.8 GB |
| Kokoro-82M (CoreML) | 82M | INT8(1 bucket) | ~89 MB |
| Qwen3.5-Chat 0.8B (MLX) | ~800M | INT4 | 418 MB |
| Qwen3.5-Chat 0.8B (CoreML) | ~800M | INT8 | 981 MB |
| PersonaPlex 7B (MLX) | ~7B | 4-bit / 8-bit | 4.9 GB / 9.1 GB |
| VoiceChat 11B (MLX) | ~11B | INT5 / INT8 | 8.56 GB / 12.11 GB |
| Pyannote VAD (MLX) | ~1.49M | float32 | ~5.7 MB |
| Silero VAD v5 | ~309K | float32 | ~1.2 MB(MLX 与 CoreML) |
| WeSpeaker ResNet34 | ~6.6M | float32 | ~25 MB(MLX 与 CoreML) |
| SpeechBrain ECAPA VoxLingua107 | 21.25M | FP16 | ~40.6 MiB (MLX) / ~40.8 MiB (CoreML) |
| ReDimNet2-B6 | 12.3M | float16 | ~25 MiB(CoreML) |
| Pyannote Community-1 (CoreML) | 8.35M | float32 + native VBx | ~32 MB |
| Sortformer (CoreML) | — | float16 | ~50 MB |
| DeepFilterNet3 (CoreML) | ~2.1M | FP16 | ~4.2 MB |
| LocalVQE v1.4-AEC (CoreML + C++) | 200K + 2,742 | FP16 + FP32 | ~732 KB |
性能优化
- MLX compile() — 针对自回归循环的 kernel fusion。Talker 使用
compile(shapeless: true),Code Predictor 使用固定 cache 大小的compile(shapeless: false)。 - Metal shader 库 — 预编译的 metallib 避免了约 5 倍的 JIT 编译开销。通过
scripts/build_mlx_metallib.sh构建。 - 分块 codec 解码 — TTS 解码器以 25 帧为一块、10 帧上下文重叠的方式处理音频,避免 GPU 超时。
- 批量加倍 CFG — CosyVoice3 DiT 通过将 conditional 与 unconditional 一起 batch,把 flow matching 的 pass 数减半。
- 融合 RoPE — 使用基于 Metal kernel 的
MLXNN.RoPE,替代手动旋转。 - BN 融合 — WeSpeaker 的 batch normalization 在转换时融合到 Conv2d 权重中。
音频处理
所有音频 I/O 都使用 Float32 PCM。内部的重采样负责格式转换:
| 模型 | 期望采样率 | 格式 |
|---|---|---|
| Qwen3-ASR | 16 kHz | Mono Float32 |
| Cohere Transcribe 2B | 16 kHz | Mono Float32 |
| Voxtral Mini 3B | 16 kHz | Mono Float32 |
| Qwen3-TTS | 24 kHz 输出 | Mono Float32 |
| CosyVoice3 | 24 kHz 输出 | Mono Float32 |
| Kokoro-82M | 24 kHz 输出 | Mono Float32 |
| PersonaPlex | 24 kHz I/O | Mono Float32 |
| Pyannote VAD | 16 kHz | Mono Float32 |
| Silero VAD | 16 kHz | Mono Float32 |
| WeSpeaker | 16 kHz | Mono Float32 |
| SpeechBrain ECAPA LID | 16 kHz | Mono Float32 |
| ReDimNet2-B6 | 16 kHz | Mono Float32 |
| DeepFilterNet3 | 48 kHz | Mono Float32 |
源码结构
Sources/
AudioCommon/ 共享协议、音频 I/O、系统输出捕获(SystemAudioTap)、HuggingFace
下载器、SentencePieceModel(protobuf 读取器)
MLXCommon/ MLX utilities: weight loading, QuantizedLinear helpers,
SDPA multi-head attention helper, metal budget
Qwen3Common/ Shared model components (KV cache, RoPE, quantization)
Qwen3ASR/ Qwen3-ASR speech-to-text
ParakeetASR/ Parakeet TDT speech-to-text (CoreML)
ParakeetStreamingASR/ Parakeet EOU 120M streaming dictation (CoreML)
OmnilingualASR/ Meta wav2vec2 + CTC, 1,672 languages
(CoreML 300M + MLX 300M / 1B / 3B / 7B)
CohereTranscribeASR/ Cohere Transcribe 2B speech-to-text (MLX)
VoxtralASR/ Voxtral Mini 3B speech-to-text (MLX)
Qwen3TTS/ Qwen3-TTS text-to-speech
CosyVoiceTTS/ CosyVoice3 text-to-speech
KokoroTTS/ Kokoro-82M text-to-speech (CoreML)
Qwen3Chat/ Qwen3.5-0.8B on-device LLM chat (MLX + CoreML)
PersonaPlex/ PersonaPlex speech-to-speech
SpeechVAD/ VAD (Silero + Pyannote), diarization, speaker embeddings
SpeechLanguageID/ 口语语言识别(SpeechBrain ECAPA、MLX + CoreML、107 个标签)
SpeechEnhancement/ DeepFilterNet3 noise suppression (CoreML)
SourceSeparation/ Open-Unmix HQ / UMX-L + HTDemucs (Demucs v4) music source separation (MLX, 4 stems)
MAGNeTMusicGen/ MAGNeT text-to-music generation (MLX, 30 s @ 32 kHz, INT4/INT8)
VoxCPM2TTS/ VoxCPM2 text-to-speech (MLX, 48 kHz, voice cloning + voice design)
IndexTTS2TTS/ IndexTTS2 voice cloning (MLX, semantic GPT + emotion/tempo/pause control + S2Mel + BigVGAN)
VibeVoiceTTS/ VibeVoice long-form / multi-speaker TTS (MLX, EN/ZH)
MADLADTranslation/ MADLAD-400 many-to-many translation (MLX, 400+ languages)
AudioCLILib/ CLI command implementations
AudioCLI/ CLI entry point
scripts/ Model conversion (PyTorch → MLX/CoreML), benchmarking
Tests/ Unit and integration tests
Examples/ Demo apps (PersonaPlexDemo, SpeechDemo)