Architecture
TTS natif par instructions
Compilez le SDK natif depuis les sources de main. Homebrew et les autres distributions CLI précompilées peuvent ne pas encore inclure ces moteurs.
Implémentation (PR #541): main
Bundles MLX publiés: aufklarer/FireRedTTS3-Instruct-MLX-fp32 · aufklarer/MOSS-VoiceGenerator-MLX-bf16
FireRedTTS3-Instruct — FireRedTTS3TTS: FireRedTTS3-Instruct conserve les poids Float32 du modèle et du décodeur. Il renvoie l’audio complet en mémoire : omettez --stream. --language accepte les alias anglais et chinois. Une limite de génération produit une erreur plutôt qu’un succès tronqué.
MOSS-VoiceGenerator — MossVoiceGeneratorTTS: MOSS-VoiceGenerator conserve les poids de langage BF16 et le codec de synthèse FP32. Utilisez --stream pour le PCM progressif. Omettez --language et précisez la langue dans --instruct. La fin vide les seize livres de codes.
Les champs texte et instruction sont limités chacun à 32 768 octets UTF-8. Le prompt d’entrée complet, modèle inclus, doit tenir dans 4 096 tokens après rendu. Les entrées dépassant une limite sont rejetées.
Le suivi des instructions n’a pas encore été noté. Les mesures sur textes courts décrivent la configuration testée ; la certification de régression de latence reste non concluante.
Breeze TTS 2 · BreezeTTS
Synthèse vocale en anglais et chinois avec création de voix, clonage et direction à partir d’un enregistrement de référence, et audio en streaming (MLX BF16/8-bit, 24 kHz ; recherche et usage non commercial).
speech speak "The quick brown fox jumps over the lazy dog." --engine breeze \
--instruct "A clear, calm English narrator." --stream -o design.wav--breeze-model-id:aufklarer/Breeze-TTS-2-MLX-8bit--breeze-bundle-dir--breeze-cache-limit-mib--breeze-reference-text--breeze-temperature:0.9--breeze-top-k:50--breeze-top-p:1--breeze-cfg-scale:4--breeze-max-frames:750--breeze-seed:42--first-chunk-frames:3--chunk-frames:25
Moteur natif pour Apple · PocketTTS
PocketTTS ajoute la synthèse native CoreML à speech-swift. Toutes les étapes utilisent uniquement le CPU par défaut. La voix anglaise Alba diffuse 1 920 échantillons à 24 kHz par bloc, soit 80 ms.
speech-swift est organisé comme un package Swift modulaire avec des protocoles partagés, des modules de modèles indépendants et une CLI unifiée. Toute l'inférence s'exécute sur l'appareil en utilisant MLX (GPU Metal) ou CoreML (Neural Engine).
Graphe de dépendances des modules
┌──────────┐
│ AudioCLI │ (point d'entrée)
└────┬─────┘
│
┌──────┴──────┐
│ AudioCLILib │ (commandes)
└──────┬──────┘
│
┌─────────┬───────┼───────┬──────────┬──────────────┐
│ │ │ │ │ │
┌────┴───┐ ┌──┴──┐ ┌──┴──┐ ┌─┴────┐ ┌───┴────┐ ┌──────┴───────┐
│Qwen3ASR│ │Qwen3│ │Cosy │ │Perso-│ │Speech- │ │ Speech- │
│Parakeet│ │ TTS │ │Voice│ │naPlex│ │ VAD │ │Enhancement │
└────┬───┘ └──┬──┘ └──┬──┘ └──┬───┘ └───┬───┘ └──────┬───────┘
│ │ │ │ │ │
└────────┴───────┼───────┴─────────┘ │
│ │
┌──────┴──────┐ │
│ Qwen3Common │ (couches partagées) │
└──────┬──────┘ │
│ │
┌──────┴──────┐ │
│ AudioCommon │ ◄──────────────────────┘
└─────────────┘ (protocoles, E/S audio)Budget du cache de tampons MLX
Les modèles MLX partagent un plafond par défaut de tampons réutilisables de min(2 GiB, physical RAM / 4), du chargement des poids à la fin de leur durée de vie. Les budgets inférieurs de l’appelant, y compris MLX.Memory.cacheLimit = 0, et les budgets propres aux modèles existants sont préservés. Ce plafond concerne les tampons inactifs ; les poids actifs, les caches KV et la mémoire totale du processus peuvent le dépasser. MLX réduit le cache lors des allocations ; le dernier tampon libéré peut donc le faire dépasser temporairement le budget jusqu’à l’allocation suivante.
unload() libère l’enregistrement du modèle ; les modèles sans cette méthode le libèrent à leur destruction. Le dernier propriétaire restaure le budget de l’appelant ; les déchargements précédents préservent les plafonds des modèles restants. Les chemins utilisant uniquement CoreML n’enregistrent aucun budget MLX.
MOSS Transcribe Diarize
MossTranscribe renvoie des segments horodatés attribués aux locuteurs via des backends natifs CoreML et MLX. CoreML utilise un état fixe de 1 024 tokens pour les enregistrements courts. MLX emploie un contexte dynamique de 131 072 tokens, des poids de décodeur affine INT5/INT8 et des caches KV FP16/INT8 optionnels. Les deux runtimes sont hors ligne et autorégressifs, sans streaming.
VoiceChat 11B
Tâche et référence : speech-to-speech duplex ; SALM-Duplex: Efficient and Direct Duplex Modeling for Speech-to-Speech Language Model (Interspeech 2025), cité par la fiche VoiceChat amont de NVIDIA.
Runtime complet, M5 Pro 48 Go, Release, cadence live de 80 ms : l'INT5 avec têtes protégées atteint environ 8.69 Go de RSS maximal ; trois RTF contrôlés du pipeline complet ont donné 0.96, 0.96 et 0.99. Les performances INT8 optimisées n'ont pas encore été remesurées.
VoiceChat implémente le chemin audio-à-audio MLX natif complet : perception FastConformer causale, canaux duplex texte/fonction Nemotron-H, décodeur EAR-TTS autonome conditionné par le texte avec huit itérations MaskGIT et codec neuronal à 22,05 kHz. Le streaming conserve des caches bornés d'attention et de convolution causale par couche, tandis que la fenêtre live stable de huit trames du codec utilise un graphe compilé. Chaque trame d'entrée de 80 ms produit une décision de langage, 31 codes RVQ et exactement 1 764 échantillons de sortie. Le chargeur exige un bundle complet encoder/ + llm/ + tts/ et refuse les anciens exports limités à la compréhension. INT5 maintient désormais un RTF global sous 1 sur le M5 Pro testé, bien que la marge p95 par trame reste faible.
Backends d'inférence
| Backend | Matériel | Modèles |
|---|---|---|
| MLX | GPU Metal | Qwen3-ASR, Qwen3-TTS, Breeze TTS 2, 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, Nemotron 3 Diarization, FireRedTTS3-Instruct, MOSS-VoiceGenerator |
| CoreML | CPU / GPU / Neural Engine (ANE) | Encodeur Qwen3-ASR (hybride), Parakeet TDT, Parakeet EOU streaming, Omnilingual ASR 300M, Kokoro-82M, Qwen3.5-Chat (optionnel), diarisation Sortformer, DeepFilterNet3, Silero VAD (optionnel), WeSpeaker (optionnel), MOSS Transcribe Diarize, SpeechBrain ECAPA LID, Nemotron 3 Diarization |
| Accelerate | CPU (SIMD) | Prétraitement audio (STFT, mel, FFT), traitement du signal |
Format des poids de modèles
Les modèles MLX utilisent le format safetensors avec une quantification 4 bits ou 8 bits (taille de groupe 64). Les modèles CoreML utilisent le format compilé .mlmodelc. Les scripts de conversion dans scripts/ convertissent depuis des checkpoints PyTorch.
Cohere et Voxtral proposent aussi des bundles MLX INT5 affines. MLX ne prend pas en charge INT7 affine ; INT8 est l’option de meilleure qualité prise en charge.
| Modèle | Paramètres | Quantification | Taille sur disque |
|---|---|---|---|
| Qwen3-ASR 0.6B (MLX) | ~600M | 4 bits / 8 bits | 680 Mo / 1,0 Go |
| Qwen3-ASR 0.6B (CoreML) | ~186M (encodeur) | INT8 | ~180 Mo |
| Qwen3-ASR 1.7B (MLX) | ~1,7B | 4 bits / 8 bits | 2,1 Go / 3,2 Go |
| Parakeet-TDT 0.6B (CoreML) | ~600M | INT8 | 500 Mo |
| 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 Mo |
| Omnilingual-ASR-CTC 300M (CoreML) | 326M | INT8 | 312 Mo |
| Omnilingual-ASR-CTC 300M (MLX) | 326M | 4 bits / 8 bits | 193 Mo / 342 Mo |
| Omnilingual-ASR-CTC 1B (MLX) | 1,01B | 4 bits / 8 bits | 549 Mo / 1006 Mo |
| Omnilingual-ASR-CTC 3B (MLX) | ~3B | 4 bits / 8 bits | 1,71 Go / 3,16 Go |
| Omnilingual-ASR-CTC 7B (MLX) | ~7B | 4 bits / 8 bits | 3,55 Go / 6,63 Go |
| 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 bits / 8 bits | 979 Mo / 1,4 Go |
| Qwen3-ForcedAligner 0.6B (CoreML) | ~600M | INT4 / INT8 | 630 Mo / 1,0 Go |
| Qwen3-TTS 0.6B (MLX) | ~600M | 4 bits / 8 bits | 1,7 Go / 2,4 Go |
| Qwen3-TTS 1.7B (MLX) | ~1,7B | 4 bits / 8 bits | 3,2 Go / 4,8 Go |
| CosyVoice3 0.5B (MLX) | ~500M | LLM 4 bits | ~1,2 Go |
| IndexTTS2 expanded bundle (MLX) | 1.5B-class | FP16 + auxiliary models | ~4.8 GB |
| Kokoro-82M (CoreML) | 82M | INT8 (1 bucket) | ~89 Mo |
| Qwen3.5-Chat 0.8B (MLX) | ~800M | INT4 | 418 Mo |
| Qwen3.5-Chat 0.8B (CoreML) | ~800M | INT8 | 981 Mo |
| PersonaPlex 7B (MLX) | ~7B | 4 bits / 8 bits | 4,9 Go / 9,1 Go |
| VoiceChat 11B (MLX) | ~11B | INT5 / INT8 | 8.56 GB / 12.11 GB |
| Pyannote VAD (MLX) | ~1,49M | float32 | ~5,7 Mo |
| Silero VAD v5 | ~309K | float32 | ~1,2 Mo (MLX et CoreML) |
| p99 turn-1-mini | 5.3M | Float32 | 22 MB (CoreML) |
| VAP (otoSpeech) | 5.8M | Float32 | 39 MB (CoreML) / 40 MB (ONNX) |
| WeSpeaker ResNet34 | ~6,6M | float32 | ~25 Mo (MLX et CoreML) |
| SpeechBrain ECAPA VoxLingua107 | 21.25M | FP16 | ~40.6 MiB (MLX) / ~40.8 MiB (CoreML) |
| ReDimNet2-B6 | 12,3M | float16 | ~25 Mio (CoreML) |
| Pyannote Community-1 (CoreML) | 8.35M | float32 + native VBx | ~32 MB |
| Nemotron 3 Diarization (CoreML / MLX) | 100M | INT8 | ~100 MB per backend |
| Sortformer (CoreML) | — | float16 | ~50 Mo |
| DeepFilterNet3 (CoreML) | ~2,1M | FP16 | ~4,2 Mo |
| LocalVQE v1.4-AEC (CoreML + C++) | 200K + 2 742 | FP16 + FP32 | ~732 Ko |
Initialisation des modèles MLX
QuantizedLinear.preQuantized crée des tableaux provisoires de zéros pour les couches linéaires quantifiées chargées depuis un checkpoint, évitant les poids aléatoires et leurs graphes temporaires de quantification. withThrowawayRandomState sépare l’initialisation en virgule flottante destinée à être supprimée de la chaîne de clés aléatoires de l’appelant. Les chargeurs de modèles composites isolent chaque composant : T5 et EnCodec de MAGNeT, T5Gemma et SAME-L de Stable Audio 3, et le codec Mimi de CSM. Les embeddings quantifiés de CSM utilisent toujours l’initialiseur amont et conservent sa limitation connue concernant la durée de vie du graphe d’initialisation.
Optimisations de performance
- MLX compile() — Fusion de noyaux pour les boucles autorégressives. Talker utilise
compile(shapeless: true), Code Predictor utilisecompile(shapeless: false)avec des tailles de cache fixes. - Bibliothèque de shaders Metal — Le metallib pré-compilé évite environ 5× de surcoût de compilation JIT. Compilé via
scripts/build_mlx_metallib.sh. - Décodage de codec par chunks — Le décodeur TTS traite l'audio par chunks de 25 trames avec chevauchement de contexte de 10 trames pour éviter les timeouts GPU.
- CFG à batch doublé — Le DiT de CosyVoice3 divise par deux les passes de flow matching en groupant conditionnel + inconditionnel ensemble.
- RoPE fusionné — Utilise
MLXNN.RoPEadossé à un noyau Metal plutôt qu'une rotation manuelle. - Fusion BN — La normalisation par batch de WeSpeaker est fusionnée dans les poids Conv2d au moment de la conversion.
Traitement audio
Toutes les E/S audio utilisent du PCM Float32. Le rééchantillonnage interne gère la conversion de format :
| Modèle | Taux attendu | Format |
|---|---|---|
| Qwen3-ASR | 16 kHz | Mono Float32 |
| Cohere Transcribe 2B | 16 kHz | Mono Float32 |
| Voxtral Mini 3B | 16 kHz | Mono Float32 |
| Qwen3-TTS | 24 kHz en sortie | Mono Float32 |
| CosyVoice3 | 24 kHz en sortie | Mono Float32 |
| Kokoro-82M | 24 kHz en sortie | 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 |
Structure des sources
Sources/
AudioCommon/ Protocoles partagés, E/S audio, capture de la
sortie système (SystemAudioTap), téléchargeur
HuggingFace, SentencePieceModel (lecteur protobuf)
MLXCommon/ Utilitaires MLX : chargement des poids, aides QuantizedLinear,
aide d'attention multi-tête SDPA, budget Metal
Qwen3Common/ Composants de modèle partagés (cache KV, RoPE, quantification)
Qwen3ASR/ Qwen3-ASR parole vers texte
ParakeetASR/ Parakeet TDT parole vers texte (CoreML)
ParakeetStreamingASR/ Dictée streaming Parakeet EOU 120M (CoreML)
OmnilingualASR/ Meta wav2vec2 + CTC, 1 672 langues
(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 texte vers parole
FireRedTTS3TTS/ FireRedTTS3-Instruct (MLX, Float32)
MossVoiceGeneratorTTS/ MOSS-VoiceGenerator (MLX, BF16 + FP32)
CosyVoiceTTS/ CosyVoice3 texte vers parole
KokoroTTS/ Kokoro-82M texte vers parole (CoreML)
Qwen3Chat/ Chat LLM embarqué Qwen3.5-0.8B (MLX + CoreML)
PersonaPlex/ PersonaPlex parole-à-parole
SpeechVAD/ VAD (Silero + Pyannote), diarisation, empreintes de locuteur
SpeechLanguageID/ Identification de la langue parlée (SpeechBrain ECAPA, MLX + CoreML, 107 étiquettes)
SpeechEnhancement/ Suppression de bruit 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)
GLiNER/ GLiNER2.5-Decide classification + entity spans (MLX, INT8/FP16/FP32)
AudioCLILib/ Implémentations des commandes CLI
AudioCLI/ Point d'entrée CLI
scripts/ Conversion de modèles (PyTorch → MLX/CoreML), benchmarking
Tests/ Tests unitaires et d'intégration
Examples/ Applications de démonstration (PersonaPlexDemo, SpeechDemo)GLiNER2.5-Decide : classification et segments d’entités natifs en MLX (poids INT8, FP16 ou FP32) ; pas de Python à l’inférence.
⚠ Translation out of date — English guide. The new Clef section below awaits translation.
Clef-flash: development preview of local text decisions (9B, affine 4-bit MLX), with a joint schema head and a separate output-embedding prior.
MOSS-TTS-Nano
Synthèse vocale en streaming et clonage avec CoreML, audio stéréo 48 kHz et blocs de 80 ms.
MossTTSNanoModel sérialise les requêtes et crée un état CoreML neuf par énoncé. synthesize et synthesizeStream conservent la stéréo ; SpeechGenerationModel renvoie un mixage mono. Passez language: nil. Le flux se termine par un marqueur final vide.
macOS 15+ / iOS 18+ ; quatre modèles compilés totalisant 367,6 Mo. Le prompt, la référence et les trames demandées partagent 1 024 lignes de contexte. Le dépassement du contexte ou de maxFrames avant la fin naturelle provoque une erreur. CPU par défaut ; gpu autorise CPU+GPU. Les graines PCG64 sont compatibles avec NumPy ; les écarts numériques entre backends peuvent modifier la sortie.
Gestion facultative des modèles
SpeechRuntime fournit un chargement partagé, une admission FIFO annulable et une exécution sérialisée. Qwen3ASRRuntime sélectionne MLX ou CoreML complet par descripteurs explicites ; les API natives et options CLI restent disponibles.
Le serveur conserve un permis pendant toute la requête, y compris la sortie en streaming, avec jusqu’à 32 requêtes en attente. Les échecs ASR produisent des erreurs HTTP ou des événements d’erreur WebSocket ; les transcriptions vides valides restent des succès. La lecture conserve les échantillons excédentaires. Les modèles en cache et l’audio en attente occupent toujours de la mémoire.
Voxtral TTS
Voxtral 4B TTS 2603 fonctionne localement sur Apple Silicon via le module VoxtralTTS : 20 voix prédéfinies, neuf langues et une sortie mono à 24 kHz.
VoxtralTTS → 26-layer LM → 3-layer acoustic transformer → 24 kHz PCMVoix prédéfinies uniquement ; le clonage à partir d’un audio de référence est indisponible. Le SDK, la CLI, WebSocket et HTTP PCM émettent l’audio pendant la génération. Le texte complet doit être fourni au départ. Les poids sont sous licence CC BY-NC 4.0.
Fish Audio Drama 3
La prise en charge native expérimentale de Drama 3 en MLX est disponible via FishAudioDrama3Model. Un modèle MoE de 35 milliards de paramètres à attention hybride, un décodeur audio temporel et le codec Fish DAC produisent un son mono à 44,1 kHz. Le modèle 4 bits a réussi les tests audio et de reconnaissance indépendante pour la génération à partir de texte, le clonage avec référence et la sortie CLI sur Apple M5 Pro. Les variantes 8 bits et BF16 restent à valider.
Le mode par défaut balanced libère les tampons MLX inactifs au-delà de 512 MiB entre les étapes. Le plafond partagé s’applique aussi pendant la durée de vie du modèle et préserve les budgets inférieurs de l’appelant ; aucun de ces contrôles ne limite la mémoire totale du processus. --fish-drama3-memory-mode unrestricted ou memoryOptions: .unrestricted charge les poids à l’avance et ignore le nettoyage entre étapes, mais conserve le plafond de durée de vie.
La génération de texte seul diffère le chargement de 794.4 MiB de poids de l’encodeur de référence. Le premier encodage les charge et les conserve ; gardez codec.safetensors disponible jusque-là. Les codes de référence précalculés n’ont pas besoin de l’encodeur.
FishAudioTTS: FishAudioDrama3Model · backbone.model.* · semantic_head.* · tower.* · codec.safetensors
Créé avec Fish Audio. Les paquets conservent la Community License et NOTICE.
Le streaming PCM est disponible via generateStreaming, generateStream et --stream. Un bloc contient par défaut 3 trames du codec, soit environ 139 ms d’audio. Le découpage automatique des textes longs et l’entrée progressive de texte restent indisponibles.
Chaque dictionnaire de codes de la tour utilise 4 096 valeurs de jeton. Le décodage Fish DAC en mémoire comme en flux ramène les codes résiduels dans la plage des dictionnaires résiduels de 1 024 entrées du codec. Les dictionnaires de codes renvoyés conservent les valeurs originales de la tour.
Les dimensions rotatives non valides sont rejetées avant le chargement des poids du modèle.