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

LangueCode
Chinoischinese
Anglaisenglish
Japonaisjapanese
Coréenkorean
Allemandgerman
Espagnolspanish
Françaisfrench
Italienitalian
Russerussian

Pipeline

CosyVoice3 synthétise la parole en trois étapes :

  1. LLM — le backbone Qwen2.5-0.5B génère des tokens de parole FSQ (Finite Scalar Quantization) à partir du texte
  2. Flow matching DiT — un Diffusion Transformer à 22 couches convertit les tokens de parole en spectrogrammes mel via intégration d'ODE par Euler
  3. 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ètreValeur
Couches24
Dimension cachée896
Têtes de requête14
Têtes clé/valeur2 (GQA)
Vocabulaire FSQ6561
Quantification4 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ètreValeur
Couches22
Dimension1024
Têtes d'attention16
ConditionnementAdaLN (Adaptive Layer Norm)
Solveur ODEEuler, 10 étapes
Taux CFG0,7

Vocodeur HiFi-GAN

Un vocodeur Neural Source Filter (NSF) qui convertit les spectrogrammes mel en formes d'onde.

ParamètreValeur
Harmoniques8
Ratio de sur-échantillonnage×480 (8 × 5 × 3 × ISTFT 4)
ISTFTn_fft=16, hop=4
Fréquence d'échantillonnage de sortie24 kHz

Poids du modèle

VarianteLLMDiTTailleHuggingFace
4bit (défaut)int4, group=64bf16~1,2 Goaufklarer/CosyVoice3-0.5B-MLX-4bit
8bitint8, group=64bf16~1,4 Goaufklarer/CosyVoice3-0.5B-MLX-8bit
8bit-fullint8, group=64int8, group=64~1,6 Goaufklarer/CosyVoice3-0.5B-MLX-8bit-full
bf16bf16bf16~2,1 Goaufklarer/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

  1. L'encodeur de locuteur CAM++ extrait un embedding à 192 dimensions à partir de l'audio de référence via CoreML (Neural Engine)
  2. Une projection affine (192 → 80) conditionne le décodeur de flow matching DiT sur la voix cible
  3. Le vocodeur HiFi-GAN convertit le spectrogramme mel conditionné par le locuteur en audio à 24 kHz

Encodeur de locuteur

PropriétéValeur
ModèleCAM++ (Context-Aware Masking++)
Embedding192 dimensions
BackendCoreML (Neural Engine, FP16)
Taille~14 Mo
HuggingFaceaufklarer/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.

OptionPar défautDescription
--speakersMapping des locuteurs : s1=file.wav,s2=file.wav
--turn-gap0.2Silence entre les tours (secondes)
--crossfade0.0Chevauchement 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

BaliseInstruction
happy / excitedParler joyeusement et avec enthousiasme.
sadParler tristement avec un ton mélancolique.
angryParler avec colère et intensité.
whispers / whisperingParler dans un murmure doux et délicat.
laughs / laughingParler en riant.
calmParler calmement et paisiblement.
surprisedParler avec surprise et étonnement.
seriousParler 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ôleModeComment l'invoquer depuis Soniqo
<|fl_speaker_clone|>Clonage vocal zero-shot à partir d'un échantillon audio de référencePassez --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éfautPassez --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éeCombinez --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 appelNon 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 upstreamCombinez --voice-sample avec --language german|spanish|chinese|.... Soniqo sélectionne l'indice de langue correct à partir de l'option --language.
Si vous portez depuis FunAudioLLM/CosyVoice

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ètreValeur
Top-k25
Top-p0,8
Repetition Aware SamplingActivé (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.

ÉtapeLatence
LLM (compilé)~13 ms/token
Flow matching DiT370 - 520 ms
HiFi-GAN50 - 170 ms
Compilation

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).