CosyVoice3
Fun-CosyVoice3-0.5B est un modèle de synthèse texte-vers-parole en streaming pour 9 langues. Il utilise un pipeline en trois étapes — génération de tokens par LLM, flow matching DiT et vocodage HiFi-GAN — pour produire une parole naturelle à 24 kHz à partir de texte. Le modèle — également orthographié CosyVoice 3 — est le dernier-né de la famille CosyVoice de FunAudioLLM.
Langues prises en charge
| Langue | Code |
|---|---|
| Chinois | chinese |
| Anglais | english |
| Japonais | japanese |
| Coréen | korean |
| Allemand | german |
| Espagnol | spanish |
| Français | french |
| Italien | italian |
| Russe | russian |
Pipeline
CosyVoice3 synthétise la parole en trois étapes :
- LLM — le backbone Qwen2.5-0.5B génère des tokens de parole FSQ (Finite Scalar Quantization) à partir du texte
- Flow matching DiT — un Diffusion Transformer à 22 couches convertit les tokens de parole en spectrogrammes mel via intégration d'ODE par Euler
- HiFi-GAN — vocodeur Neural Source Filter qui convertit les spectrogrammes mel en formes d'onde à 24 kHz
Architecture
LLM (Qwen2.5-0.5B)
Le modèle de langage génère des jetons de parole discrets de manière autorégressive. Le runtime propose quatre variantes de quantification — 4-bit, 8-bit, 8-bit-full (LLM int8 + DiT int8) et bf16 (non quantifié) — sélectionnables via --cosyvoice-variant.
| Paramètre | Valeur |
|---|---|
| Couches | 24 |
| Dimension cachée | 896 |
| Têtes de requête | 14 |
| Têtes clé/valeur | 2 (GQA) |
| Vocabulaire FSQ | 6561 |
| Quantification | 4 bits |
Flow matching DiT
Le Diffusion Transformer raffine les tokens de parole en spectrogrammes mel à l'aide du conditional flow matching avec guidage sans classifieur.
| Paramètre | Valeur |
|---|---|
| Couches | 22 |
| Dimension | 1024 |
| Têtes d'attention | 16 |
| Conditionnement | AdaLN (Adaptive Layer Norm) |
| Solveur ODE | Euler, 10 étapes |
| Taux CFG | 0,7 |
Vocodeur HiFi-GAN
Un vocodeur Neural Source Filter (NSF) qui convertit les spectrogrammes mel en formes d'onde.
| Paramètre | Valeur |
|---|---|
| Harmoniques | 8 |
| Ratio de sur-échantillonnage | ×480 (8 × 5 × 3 × ISTFT 4) |
| ISTFT | n_fft=16, hop=4 |
| Fréquence d'échantillonnage de sortie | 24 kHz |
Poids du modèle
| Variante | LLM | DiT | Taille | HuggingFace |
|---|---|---|---|---|
4bit (défaut) | int4, group=64 | bf16 | ~1,2 Go | aufklarer/CosyVoice3-0.5B-MLX-4bit |
8bit | int8, group=64 | bf16 | ~1,4 Go | aufklarer/CosyVoice3-0.5B-MLX-8bit |
8bit-full | int8, group=64 | int8, group=64 | ~1,6 Go | aufklarer/CosyVoice3-0.5B-MLX-8bit-full |
bf16 | bf16 | bf16 | ~2,1 Go | aufklarer/CosyVoice3-0.5B-MLX-bf16 |
Chaque bundle inclut le LLM, le décodeur DiT en flow-matching, le vocoder HiFi-GAN et l'encodeur de référence S3-Tokenizer nécessaire au clonage vocal zero-shot. Choisissez les bundles plus petits pour réduire le téléchargement et l'espace disque ; choisissez bf16 si le bruit de quantification LLM/DiT pose problème (synthèse longue forme, fidélité du clonage).
Utilisation en CLI
.build/release/speech speak "Hallo Welt" --engine cosyvoice --language german -o output.wav
Exemples
# Anglais
.build/release/speech speak "Hello, how are you?" --engine cosyvoice -o hello_en.wav
# Chinois
.build/release/speech speak "你好世界" --engine cosyvoice --language chinese -o hello_cn.wav
# Espagnol
.build/release/speech speak "Hola, buenos días" --engine cosyvoice --language spanish -o hello_es.wav
# Français
.build/release/speech speak "Bonjour le monde" --engine cosyvoice --language french -o hello_fr.wav
Clonage vocal
Clonez n'importe quelle voix à partir d'un court échantillon audio de référence avec l'option --voice-sample. CosyVoice3 utilise l'encodeur de locuteur CAM++ pour extraire un embedding à 192 dimensions qui conditionne le modèle de flow DiT.
# Clonage vocal
.build/release/speech speak "Hello in your voice" --engine cosyvoice --voice-sample reference.wav -o cloned.wav
# Inter-langue : cloner la voix, parler en allemand
.build/release/speech speak "Guten Tag" --engine cosyvoice --voice-sample reference.wav --language german -o german.wav
Fonctionnement
- L'encodeur de locuteur CAM++ extrait un embedding à 192 dimensions à partir de l'audio de référence via CoreML (Neural Engine)
- Une projection affine (192 → 80) conditionne le décodeur de flow matching DiT sur la voix cible
- Le vocodeur HiFi-GAN convertit le spectrogramme mel conditionné par le locuteur en audio à 24 kHz
Encodeur de locuteur
| Propriété | Valeur |
|---|---|
| Modèle | CAM++ (Context-Aware Masking++) |
| Embedding | 192 dimensions |
| Backend | CoreML (Neural Engine, FP16) |
| Taille | ~14 Mo |
| HuggingFace | aufklarer/CamPlusPlus-Speaker-CoreML |
Le modèle CAM++ est téléchargé automatiquement à la première utilisation de --voice-sample. Consultez le guide Clonage vocal pour des conseils sur l'audio de référence et l'API Swift.
Dialogue multi-locuteurs
Synthétisez des conversations entre plusieurs locuteurs à l'aide de balises de locuteur en ligne. Chaque locuteur se voit attribuer une voix à partir d'un fichier audio de référence via l'option --speakers.
# Dialogue à deux locuteurs avec clonage vocal
.build/release/speech speak "[S1] Hello there! [S2] Hey, how are you?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o dialogue.wav
# Trois locuteurs
.build/release/speech speak "[A] Welcome. [B] Thanks! [C] Glad to be here." \
--engine cosyvoice --speakers a=host.wav,b=guest1.wav,c=guest2.wav -o panel.wav
Les noms de locuteurs dans les balises ne sont pas sensibles à la casse et sont mis en correspondance avec les clés du mapping. Un silence configurable (0,2 s par défaut) est inséré entre les tours.
| Option | Par défaut | Description |
|---|---|---|
--speakers | Mapping des locuteurs : s1=file.wav,s2=file.wav | |
--turn-gap | 0.2 | Silence entre les tours (secondes) |
--crossfade | 0.0 | Chevauchement en fondu enchaîné entre les tours (secondes) |
Balises d'émotion et de style
Contrôlez le style de parole par segment à l'aide de balises d'émotion en ligne. CosyVoice3 utilise le préfixe de texte avant le token <|endofprompt|> comme instruction de style — les balises d'émotion correspondent à des instructions en langage naturel qui remplacent ce préfixe.
# Balises d'émotion
.build/release/speech speak "(excited) Wow, amazing! (sad) But I have to go..." \
--engine cosyvoice -o emotion.wav
# Combinées aux locuteurs
.build/release/speech speak "[S1] (happy) Great news! [S2] (surprised) Really?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o combined.wav
# Instruction libre en tant que balise
.build/release/speech speak "(Speak like a pirate) Ahoy matey!" \
--engine cosyvoice -o pirate.wav
# Instruction globale (s'applique à tous les segments sans balise d'émotion)
.build/release/speech speak "Hello world" \
--engine cosyvoice --cosy-instruct "Speak cheerfully" -o cheerful.wav
Balises d'émotion intégrées
| Balise | Instruction |
|---|---|
happy / excited | Parler joyeusement et avec enthousiasme. |
sad | Parler tristement avec un ton mélancolique. |
angry | Parler avec colère et intensité. |
whispers / whispering | Parler dans un murmure doux et délicat. |
laughs / laughing | Parler en riant. |
calm | Parler calmement et paisiblement. |
surprised | Parler avec surprise et étonnement. |
serious | Parler d'un ton sérieux et formel. |
Les balises inconnues sont transmises telles quelles comme instructions libres : (Speak in a slow, dramatic voice) fonctionne directement.
Jetons de contrôle du modèle (jetons fl_)
En interne, le LLM de CosyVoice3 utilise des jetons de contrôle spéciaux — préfixés par fl_ — pour basculer entre les modes (clonage zero-shot, synthèse avec instruction, sauvegarde d'un locuteur, etc.). Ces jetons font partie du tokenizer FunAudioLLM upstream ; le runtime Soniqo émet automatiquement le bon jeton en fonction de l'option CLI ou de l'appel à l'API Swift que vous utilisez, vous n'avez donc jamais à les écrire à la main.
| Jeton de contrôle | Mode | Comment l'invoquer depuis Soniqo |
|---|---|---|
<|fl_speaker_clone|> | Clonage vocal zero-shot à partir d'un échantillon audio de référence | Passez --voice-sample reference.wav à la CLI, ou définissez voiceSample: sur l'API Swift. |
<|fl_speaker_instruct|> | Synthèse conditionnée par instruction ou style avec une voix par défaut | Passez --cosy-instruct "Speak cheerfully" ou utilisez une balise inline (happy) sans --voice-sample. |
<|fl_speaker_instruct2|> | Synthèse avec instruction combinée à une voix de référence clonée | Combinez --voice-sample reference.wav avec --cosy-instruct "..." (ou une balise d'émotion inline) dans le même appel. |
<|fl_save_speaker|> | Persiste l'embedding d'un locuteur pour le réutiliser sans réencoder l'audio de référence à chaque appel | Non exposé directement dans la CLI Soniqo — les embeddings sont calculés à chaque appel. Pour les mettre en cache, extrayez vous-même le vecteur CAM++ à 192 dimensions via le module Embeddings de locuteur et transmettez-le. |
<|fl_speaker_clone_zh|>, <|fl_speaker_clone_en|>, … | Indices de clonage zero-shot spécifiques à la langue utilisés par le tokenizer upstream | Combinez --voice-sample avec --language german|spanish|chinese|.... Soniqo sélectionne l'indice de langue correct à partir de l'option --language. |
Le tableau ci-dessus mappe chaque jeton de contrôle upstream fl_ à son équivalent Soniqo. Vous n'avez jamais besoin d'insérer vous-même des jetons fl_ dans votre prompt — passez les options CLI de haut niveau ou les arguments de l'API Swift, et le runtime émettra la séquence correcte : clone → instruct → instruct2 → save_speaker.
Échantillonnage
L'étape LLM utilise la configuration d'échantillonnage suivante :
| Paramètre | Valeur |
|---|---|
| Top-k | 25 |
| Top-p | 0,8 |
| Repetition Aware Sampling | Activé (fenêtre=10, tau_r=0,1) |
Repetition Aware Sampling (RAS), venu de VALL-E 2, pénalise les tokens apparus dans les 10 derniers tokens générés. Cela évite les artefacts audio répétitifs et améliore la stabilité de la sortie.
Performance
Sur un M2 Max, CosyVoice3 atteint un RTF d'environ 0,5 — plus rapide que le temps réel.
| Étape | Latence |
|---|---|
| LLM (compilé) | ~13 ms/token |
| Flow matching DiT | 370 - 520 ms |
| HiFi-GAN | 50 - 170 ms |
L'étape LLM utilise compile(shapeless: true) pour la boucle autorégressive, ce qui élimine le coût de recompilation pour des longueurs de séquence variables. Le CFG à batch doublé divise par deux le nombre de passes DiT (de 20 à 10).