CosyVoice3
Fun-CosyVoice3-0.5B es un modelo de texto a voz con streaming en 9 idiomas. Utiliza un pipeline de tres etapas — generación de tokens con LLM, DiT flow matching y vocoder HiFi-GAN — para producir voz natural a 24 kHz a partir de una entrada de texto. El modelo — también escrito CosyVoice 3 — es la última versión de la familia CosyVoice de FunAudioLLM.
Idiomas soportados
| Idioma | Código |
|---|---|
| Chino | chinese |
| Inglés | english |
| Japonés | japanese |
| Coreano | korean |
| Alemán | german |
| Español | spanish |
| Francés | french |
| Italiano | italian |
| Ruso | russian |
Pipeline
CosyVoice3 sintetiza voz en tres etapas:
- LLM — El backbone Qwen2.5-0.5B genera tokens de voz FSQ (Finite Scalar Quantization) a partir del texto
- DiT Flow Matching — Un Diffusion Transformer de 22 capas convierte los tokens de voz en espectrogramas mel mediante integración ODE de Euler
- HiFi-GAN — Un vocoder Neural Source Filter convierte los espectrogramas mel en formas de onda a 24 kHz
Arquitectura
LLM (Qwen2.5-0.5B)
El modelo de lenguaje genera tokens de habla discretos de forma autoregresiva. El runtime se distribuye en cuatro variantes de cuantización — 4-bit, 8-bit, 8-bit-full (LLM int8 + DiT int8) y bf16 (sin cuantizar) — seleccionables vía --cosyvoice-variant.
| Parámetro | Valor |
|---|---|
| Capas | 24 |
| Dimensión oculta | 896 |
| Cabezas de consulta | 14 |
| Cabezas de clave/valor | 2 (GQA) |
| Vocabulario FSQ | 6561 |
| Cuantización | 4 bits |
DiT Flow Matching
El Diffusion Transformer refina los tokens de voz hasta obtener espectrogramas mel mediante flow matching condicional con classifier-free guidance.
| Parámetro | Valor |
|---|---|
| Capas | 22 |
| Dimensión | 1024 |
| Cabezas de atención | 16 |
| Condicionamiento | AdaLN (Adaptive Layer Norm) |
| Solver ODE | Euler, 10 pasos |
| Tasa CFG | 0.7 |
Vocoder HiFi-GAN
Un vocoder Neural Source Filter (NSF) que convierte espectrogramas mel en formas de onda.
| Parámetro | Valor |
|---|---|
| Armónicos | 8 |
| Ratio de upsample | 480x (8 x 5 x 3 x ISTFT 4) |
| ISTFT | n_fft=16, hop=4 |
| Frecuencia de muestreo de salida | 24 kHz |
Pesos del modelo
| Variante | LLM | DiT | Tamaño | HuggingFace |
|---|---|---|---|---|
4bit (predeterminado) | int4, group=64 | bf16 | ~1.2 GB | aufklarer/CosyVoice3-0.5B-MLX-4bit |
8bit | int8, group=64 | bf16 | ~1.4 GB | aufklarer/CosyVoice3-0.5B-MLX-8bit |
8bit-full | int8, group=64 | int8, group=64 | ~1.6 GB | aufklarer/CosyVoice3-0.5B-MLX-8bit-full |
bf16 | bf16 | bf16 | ~2.1 GB | aufklarer/CosyVoice3-0.5B-MLX-bf16 |
Cada bundle incluye el LLM, el decodificador DiT con flow matching, el vocoder HiFi-GAN y el codificador de referencia S3-Tokenizer necesario para el clonado de voz zero-shot. Elige bundles más pequeños para menor descarga/espacio en disco; elige bf16 cuando el ruido de cuantización del LLM/DiT sea un problema (síntesis de forma larga, fidelidad de clonado).
Uso de la CLI
.build/release/speech speak "Hallo Welt" --engine cosyvoice --language german -o output.wav
Ejemplos
# English
.build/release/speech speak "Hello, how are you?" --engine cosyvoice -o hello_en.wav
# Chinese
.build/release/speech speak "你好世界" --engine cosyvoice --language chinese -o hello_cn.wav
# Spanish
.build/release/speech speak "Hola, buenos días" --engine cosyvoice --language spanish -o hello_es.wav
# French
.build/release/speech speak "Bonjour le monde" --engine cosyvoice --language french -o hello_fr.wav
Clonación de voz
Clona cualquier voz a partir de una muestra breve de audio de referencia usando el flag --voice-sample. CosyVoice3 utiliza el encoder de hablante CAM++ para extraer un embedding de 192 dimensiones que condiciona el modelo DiT flow.
# Voice cloning
.build/release/speech speak "Hello in your voice" --engine cosyvoice --voice-sample reference.wav -o cloned.wav
# Cross-language: clone voice, speak in German
.build/release/speech speak "Guten Tag" --engine cosyvoice --voice-sample reference.wav --language german -o german.wav
Cómo funciona
- El encoder de hablante CAM++ extrae un embedding de 192 dimensiones a partir del audio de referencia mediante CoreML (Neural Engine)
- Una proyección afín (192 → 80) condiciona el decodificador DiT flow matching con la voz objetivo
- El vocoder HiFi-GAN convierte el espectrograma mel condicionado al hablante en audio a 24 kHz
Encoder de hablante
| Propiedad | Valor |
|---|---|
| Modelo | CAM++ (Context-Aware Masking++) |
| Embedding | 192 dimensiones |
| Backend | CoreML (Neural Engine, FP16) |
| Tamaño | ~14 MB |
| HuggingFace | aufklarer/CamPlusPlus-Speaker-CoreML |
El modelo CAM++ se descarga automáticamente la primera vez que se usa --voice-sample. Consulta la guía de Clonación de voz para obtener consejos sobre el audio de referencia y la API de Swift.
Diálogo multi-hablante
Sintetiza conversaciones entre varios hablantes usando etiquetas de hablante en línea. A cada hablante se le asigna una voz a partir de un archivo de audio de referencia mediante el flag --speakers.
# Two-speaker dialogue with voice cloning
.build/release/speech speak "[S1] Hello there! [S2] Hey, how are you?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o dialogue.wav
# Three speakers
.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
Los nombres de hablante en las etiquetas no distinguen entre mayúsculas y minúsculas y se emparejan con las claves del mapeo. Entre turnos se inserta un intervalo de silencio configurable (por defecto 0.2s).
| Opción | Por defecto | Descripción |
|---|---|---|
--speakers | Mapeo de hablantes: s1=file.wav,s2=file.wav | |
--turn-gap | 0.2 | Silencio entre turnos (segundos) |
--crossfade | 0.0 | Solapamiento de crossfade entre turnos (segundos) |
Etiquetas de emoción y estilo
Controla el estilo de habla por segmento mediante etiquetas de emoción en línea. CosyVoice3 utiliza el prefijo de texto anterior al token <|endofprompt|> como instrucción de estilo — las etiquetas de emoción se mapean a instrucciones en lenguaje natural que reemplazan este prefijo.
# Emotion tags
.build/release/speech speak "(excited) Wow, amazing! (sad) But I have to go..." \
--engine cosyvoice -o emotion.wav
# Combined with speakers
.build/release/speech speak "[S1] (happy) Great news! [S2] (surprised) Really?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o combined.wav
# Freeform instruction as tag
.build/release/speech speak "(Speak like a pirate) Ahoy matey!" \
--engine cosyvoice -o pirate.wav
# Global instruction (applies to all segments without emotion tags)
.build/release/speech speak "Hello world" \
--engine cosyvoice --cosy-instruct "Speak cheerfully" -o cheerful.wav
Etiquetas de emoción integradas
| Etiqueta | Instrucción |
|---|---|
happy / excited | Habla con alegría y entusiasmo. |
sad | Habla con tristeza y un tono melancólico. |
angry | Habla con enfado e intensidad. |
whispers / whispering | Habla con un susurro suave y delicado. |
laughs / laughing | Habla mientras te ríes. |
calm | Habla con calma y serenidad. |
surprised | Habla con sorpresa y asombro. |
serious | Habla con un tono serio y formal. |
Las etiquetas desconocidas se pasan como instrucciones de formato libre, así que (Speak in a slow, dramatic voice) funciona tal cual.
Tokens de control del modelo (tokens fl_)
Internamente, el LLM de CosyVoice3 utiliza tokens de control especiales — con prefijo fl_ — para alternar entre modos (clonación zero-shot, síntesis con instrucciones, guardar un hablante, etc.). Estos tokens forman parte del tokenizador upstream FunAudioLLM; el runtime de Soniqo emite el correcto automáticamente según la opción de CLI o la llamada a la API Swift que utilice, así que nunca los escribe a mano.
| Token de control | Modo | Cómo invocar desde Soniqo |
|---|---|---|
<|fl_speaker_clone|> | Clonación de voz zero-shot a partir de una muestra de audio de referencia | Pase --voice-sample reference.wav en la CLI, o establezca voiceSample: en la API Swift. |
<|fl_speaker_instruct|> | Síntesis condicionada por instrucción o estilo con una voz por defecto | Pase --cosy-instruct "Speak cheerfully" o utilice una etiqueta inline (happy) sin --voice-sample. |
<|fl_speaker_instruct2|> | Síntesis con instrucción combinada con una voz de referencia clonada | Combine --voice-sample reference.wav con --cosy-instruct "..." (o una etiqueta de emoción inline) en la misma llamada. |
<|fl_save_speaker|> | Persiste la incrustación de un hablante para reutilizarla sin reencodificar el audio de referencia en cada llamada | No se expone directamente en la CLI de Soniqo — las incrustaciones se calculan por llamada. Para almacenarlas, extraiga el vector CAM++ de 192 dimensiones usted mismo a través del módulo de Incrustaciones de hablante y páselo adelante. |
<|fl_speaker_clone_zh|>, <|fl_speaker_clone_en|>, … | Pistas de clonación zero-shot específicas de cada idioma usadas por el tokenizador upstream | Combine --voice-sample con --language german|spanish|chinese|.... Soniqo selecciona la pista de idioma correcta a partir de la opción --language. |
La tabla anterior asigna cada token de control upstream fl_ a su equivalente en Soniqo. Nunca necesita insertar tokens fl_ en su prompt — pase las opciones de alto nivel de la CLI o los argumentos de la API Swift y el runtime emitirá la secuencia correcta: clone → instruct → instruct2 → save_speaker.
Sampling
La etapa de LLM utiliza la siguiente configuración de sampling:
| Parámetro | Valor |
|---|---|
| Top-k | 25 |
| Top-p | 0.8 |
| Repetition Aware Sampling | Activado (window=10, tau_r=0.1) |
Repetition Aware Sampling (RAS), de VALL-E 2, penaliza los tokens que aparecieron entre los últimos 10 tokens generados. Esto evita artefactos de audio repetitivos y mejora la estabilidad de la salida.
Rendimiento
En un M2 Max, CosyVoice3 alcanza un RTF de aproximadamente 0.5 — más rápido que tiempo real.
| Etapa | Latencia |
|---|---|
| LLM (compilado) | ~13 ms/token |
| DiT Flow Matching | 370 - 520 ms |
| HiFi-GAN | 50 - 170 ms |
La etapa LLM usa compile(shapeless: true) para el bucle autorregresivo, lo que elimina la sobrecarga de recompilación al variar la longitud de la secuencia. El CFG con batch duplicado reduce a la mitad el número de pasadas forward del DiT, de 20 a 10.