Arquitectura
speech-swift está organizado como un paquete Swift modular con protocolos compartidos, módulos de modelo independientes y una CLI unificada. Toda la inferencia se ejecuta en el dispositivo usando MLX (GPU Metal) o CoreML (Neural Engine).
Grafo de dependencias de módulos
┌──────────┐
│ AudioCLI │ (punto de entrada)
└────┬─────┘
│
┌──────┴──────┐
│ AudioCLILib │ (comandos)
└──────┬──────┘
│
┌─────────┬───────┼───────┬──────────┬──────────────┐
│ │ │ │ │ │
┌────┴───┐ ┌──┴──┐ ┌──┴──┐ ┌─┴────┐ ┌───┴────┐ ┌──────┴───────┐
│Qwen3ASR│ │Qwen3│ │Cosy │ │Perso-│ │Speech- │ │ Speech- │
│Parakeet│ │ TTS │ │Voice│ │naPlex│ │ VAD │ │Enhancement │
└────┬───┘ └──┬──┘ └──┬──┘ └──┬───┘ └───┬───┘ └──────┬───────┘
│ │ │ │ │ │
└────────┴───────┼───────┴─────────┘ │
│ │
┌──────┴──────┐ │
│ Qwen3Common │ (capas compartidas) │
└──────┬──────┘ │
│ │
┌──────┴──────┐ │
│ AudioCommon │ ◄──────────────────────┘
└─────────────┘ (protocolos, E/S de audio)MOSS Transcribe Diarize
MossTranscribe devuelve segmentos con marcas de tiempo y hablante mediante backends nativos CoreML y MLX. CoreML usa un estado fijo de 1.024 tokens para grabaciones cortas. MLX usa un contexto dinámico de 131.072 tokens, pesos de decodificador affine INT5/INT8 y cachés KV opcionales FP16/INT8. Ambos son runtimes offline y autorregresivos, no de streaming.
VoiceChat 11B
Tarea y referencia: speech-to-speech dúplex; SALM-Duplex: Efficient and Direct Duplex Modeling for Speech-to-Speech Language Model (Interspeech 2025), citado por la ficha upstream de VoiceChat de NVIDIA.
Runtime completo, M5 Pro 48 GB, Release, cadencia live de 80 ms: el INT5 con cabezales protegidos alcanza unos 8.69 GB de RSS máximo; tres resultados controlados del RTF de la ruta completa fueron 0.96, 0.96 y 0.99. El rendimiento INT8 optimizado aún no se ha vuelto a medir.
VoiceChat implementa la ruta completa nativa de MLX de audio a audio: percepción FastConformer causal, canales dúplex de texto/función Nemotron-H, un decodificador EAR-TTS independiente condicionado por texto con ocho iteraciones MaskGIT y un códec neuronal de 22,05 kHz. El streaming conserva cachés acotadas de atención y convolución causal por capa, mientras que la ventana live estable de ocho tramas del códec usa un grafo compilado. Cada trama de entrada de 80 ms produce una decisión de lenguaje, 31 códigos RVQ y exactamente 1.764 muestras de salida. El cargador exige un bundle completo encoder/ + llm/ + tts/ y rechaza las exportaciones antiguas de solo comprensión. INT5 ahora mantiene un RTF agregado inferior a 1 en el M5 Pro probado, aunque el margen p95 por trama sigue siendo estrecho.
Backends de inferencia
| Backend | Hardware | Modelos |
|---|---|---|
| MLX | GPU Metal | Qwen3-ASR, Qwen3-TTS, CosyVoice3, IndexTTS2, 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 | Encoder de Qwen3-ASR (híbrido), Parakeet TDT, Parakeet EOU streaming, Omnilingual ASR 300M, Kokoro-82M, Qwen3.5-Chat (opcional), diarización Sortformer, DeepFilterNet3, Silero VAD (opcional), WeSpeaker (opcional), MOSS Transcribe Diarize, SpeechBrain ECAPA LID |
| Accelerate | CPU (SIMD) | Preprocesamiento de audio (STFT, mel, FFT), procesamiento de señales |
Formato de pesos de los modelos
Los modelos MLX usan el formato safetensors con cuantización de 4 bits u 8 bits (tamaño de grupo 64). Los modelos CoreML usan el formato compilado .mlmodelc. Los scripts de conversión en scripts/ convierten desde checkpoints de PyTorch.
Cohere y Voxtral también ofrecen paquetes INT5 afines de MLX. MLX no admite INT7 afín; INT8 es la opción compatible de mayor calidad.
| Modelo | Parámetros | Cuantización | Tamaño en disco |
|---|---|---|---|
| Qwen3-ASR 0.6B (MLX) | ~600M | 4-bit / 8-bit | 680 MB / 1.0 GB |
| Qwen3-ASR 0.6B (CoreML) | ~186M (encoder) | 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 | LLM en 4-bit | ~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 y CoreML) |
| WeSpeaker ResNet34 | ~6.6M | float32 | ~25 MB (MLX y 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 |
Optimizaciones de rendimiento
- MLX compile() — Fusión de kernels para bucles autoregresivos. Talker usa
compile(shapeless: true), el Code Predictor usacompile(shapeless: false)con tamaños de caché fijos. - Librería de shaders Metal — El metallib precompilado evita una sobrecarga de compilación JIT ~5x. Construido vía
scripts/build_mlx_metallib.sh. - Decodificación de códec por chunks — El decoder TTS procesa audio en chunks de 25 frames con un solape de contexto de 10 frames para evitar timeouts de GPU.
- CFG con batch duplicado — El DiT de CosyVoice3 reduce a la mitad los pases de flow matching agrupando condicional + incondicional en un batch.
- RoPE fusionado — Usa
MLXNN.RoPErespaldado por un kernel Metal en lugar de rotación manual. - Fusión de BN — La batch normalization de WeSpeaker se fusiona en los pesos de Conv2d en tiempo de conversión.
Procesamiento de audio
Toda la E/S de audio usa PCM Float32. El remuestreo interno gestiona la conversión de formato:
| Modelo | Tasa esperada | Formato |
|---|---|---|
| Qwen3-ASR | 16 kHz | Mono Float32 |
| Cohere Transcribe 2B | 16 kHz | Mono Float32 |
| Voxtral Mini 3B | 16 kHz | Mono Float32 |
| Qwen3-TTS | 24 kHz de salida | Mono Float32 |
| CosyVoice3 | 24 kHz de salida | Mono Float32 |
| Kokoro-82M | 24 kHz de salida | Mono Float32 |
| PersonaPlex | 24 kHz E/S | 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 |
Estructura del código fuente
Sources/
AudioCommon/ Protocolos compartidos, E/S de audio, captura de
la salida del sistema (SystemAudioTap),
descargador de HuggingFace, SentencePieceModel
(lector de protobuf)
MLXCommon/ Utilidades MLX: carga de pesos, helpers QuantizedLinear,
helper de atención multi-head SDPA, presupuesto metal
Qwen3Common/ Componentes de modelo compartidos (caché KV, RoPE, cuantización)
Qwen3ASR/ Qwen3-ASR voz a texto
ParakeetASR/ Parakeet TDT voz a texto (CoreML)
ParakeetStreamingASR/ Dictado en streaming Parakeet EOU 120M (CoreML)
OmnilingualASR/ Meta wav2vec2 + CTC, 1.672 idiomas
(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 texto a voz
CosyVoiceTTS/ CosyVoice3 texto a voz
KokoroTTS/ Kokoro-82M texto a voz (CoreML)
Qwen3Chat/ Chat LLM en el dispositivo Qwen3.5-0.8B (MLX + CoreML)
PersonaPlex/ PersonaPlex voz a voz
SpeechVAD/ VAD (Silero + Pyannote), diarización, embeddings de hablante
SpeechLanguageID/ Identificación del idioma hablado (SpeechBrain ECAPA, MLX + CoreML, 107 etiquetas)
SpeechEnhancement/ Supresión de ruido DeepFilterNet3 (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/ Implementaciones de comandos de la CLI
AudioCLI/ Punto de entrada de la CLI
scripts/ Conversión de modelos (PyTorch → MLX/CoreML), benchmarking
Tests/ Pruebas unitarias y de integración
Examples/ Apps de demostración (PersonaPlexDemo, SpeechDemo)