CosyVoice3
Fun-CosyVoice3-0.5B 是一个支持 9 种语言的流式文本转语音模型。它使用三阶段流水线 — LLM token 生成、DiT 流匹配与 HiFi-GAN 声码 — 从文本输入生成自然的 24 kHz 语音。该模型 — 也写作 CosyVoice 3 — 是 FunAudioLLM CosyVoice 系列的最新成员。
支持的语言
| 语言 | 代码 |
|---|---|
| 中文 | chinese |
| 英文 | english |
| 日文 | japanese |
| 韩文 | korean |
| 德文 | german |
| 西班牙文 | spanish |
| 法文 | french |
| 意大利文 | italian |
| 俄文 | russian |
流水线
CosyVoice3 分三个阶段合成语音:
- LLM — Qwen2.5-0.5B 主干从文本生成 FSQ(Finite Scalar Quantization)语音 token
- DiT 流匹配 — 22 层扩散 Transformer 通过 Euler ODE 积分将语音 token 转换为梅尔频谱图
- HiFi-GAN — 神经源滤波器声码器将梅尔频谱图转换为 24 kHz 波形
架构
LLM(Qwen2.5-0.5B)
语言模型以自回归方式生成离散语音 token。运行时提供四种量化变体——4 位、8 位、8-bit-full(int8 LLM + int8 DiT)和 bf16(无量化)——通过 --cosyvoice-variant 按调用选择。
| 参数 | 数值 |
|---|---|
| 层数 | 24 |
| 隐藏维度 | 896 |
| Query 头数 | 14 |
| Key/Value 头数 | 2 (GQA) |
| FSQ 词表 | 6561 |
| 量化 | 4 位 |
DiT 流匹配
扩散 Transformer 通过带无分类器引导的条件流匹配,将语音 token 精炼为梅尔频谱图。
| 参数 | 数值 |
|---|---|
| 层数 | 22 |
| 维度 | 1024 |
| 注意力头 | 16 |
| 条件化 | AdaLN(自适应层归一化) |
| ODE 求解器 | Euler,10 步 |
| CFG 率 | 0.7 |
HiFi-GAN 声码器
神经源滤波器(NSF)声码器,将梅尔频谱图转换为波形。
| 参数 | 数值 |
|---|---|
| 谐波 | 8 |
| 上采样比 | 480x(8 x 5 x 3 x ISTFT 4) |
| ISTFT | n_fft=16,hop=4 |
| 输出采样率 | 24 kHz |
模型权重
| 变体 | LLM | DiT | 大小 | HuggingFace |
|---|---|---|---|---|
4bit (默认) | 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 |
每个 bundle 都包含 LLM、DiT 流匹配解码器、HiFi-GAN 声码器以及 zero-shot 语音克隆所需的 S3-Tokenizer 参考编码器。需要更小的下载/磁盘占用就选较小的 bundle;当 LLM/DiT 的量化噪声成为问题时(长篇合成、语音克隆保真度)请选 bf16。
CLI 用法
.build/release/speech speak "Hallo Welt" --engine cosyvoice --language german -o output.wav
示例
# 英文
.build/release/speech speak "Hello, how are you?" --engine cosyvoice -o hello_en.wav
# 中文
.build/release/speech speak "你好世界" --engine cosyvoice --language chinese -o hello_cn.wav
# 西班牙文
.build/release/speech speak "Hola, buenos días" --engine cosyvoice --language spanish -o hello_es.wav
# 法文
.build/release/speech speak "Bonjour le monde" --engine cosyvoice --language french -o hello_fr.wav
声音克隆
使用 --voice-sample 标志,通过一段简短的参考音频克隆任意声音。CosyVoice3 使用 CAM++ 说话人编码器提取一个 192 维嵌入,用于条件化 DiT 流模型。
# 声音克隆
.build/release/speech speak "Hello in your voice" --engine cosyvoice --voice-sample reference.wav -o cloned.wav
# 跨语言:克隆声音,用德语朗读
.build/release/speech speak "Guten Tag" --engine cosyvoice --voice-sample reference.wav --language german -o german.wav
工作原理
- CAM++ 说话人编码器通过 CoreML(Neural Engine)从参考音频提取 192 维嵌入
- 仿射投影(192 → 80)根据目标音色对 DiT 流匹配解码器进行条件化
- HiFi-GAN 声码器将说话人条件化后的梅尔频谱图转换为 24kHz 音频
说话人编码器
| 属性 | 数值 |
|---|---|
| 模型 | CAM++(Context-Aware Masking++) |
| 嵌入 | 192 维 |
| 后端 | CoreML(Neural Engine,FP16) |
| 大小 | ~14 MB |
| HuggingFace | aufklarer/CamPlusPlus-Speaker-CoreML |
首次使用 --voice-sample 时会自动下载 CAM++ 模型。关于参考音频建议和 Swift API,请参阅声音克隆指南。
多说话人对话
使用内联说话人标签合成多说话人之间的对话。每个说话人通过 --speakers 标志从参考音频文件分配音色。
# 带声音克隆的双说话人对话
.build/release/speech speak "[S1] Hello there! [S2] Hey, how are you?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o dialogue.wav
# 三个说话人
.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
标签中的说话人名称不区分大小写,会与映射键匹配。每次发言之间会插入可配置的静音间隔(默认 0.2 秒)。
| 选项 | 默认 | 描述 |
|---|---|---|
--speakers | 说话人映射:s1=file.wav,s2=file.wav | |
--turn-gap | 0.2 | 发言之间的静音(秒) |
--crossfade | 0.0 | 发言之间的交叉淡化重叠(秒) |
情感与风格标签
通过内联情感标签按段控制说话风格。CosyVoice3 使用 <|endofprompt|> token 之前的文本前缀作为风格指令 — 情感标签会映射为替换该前缀的自然语言指令。
# 情感标签
.build/release/speech speak "(excited) Wow, amazing! (sad) But I have to go..." \
--engine cosyvoice -o emotion.wav
# 与说话人组合使用
.build/release/speech speak "[S1] (happy) Great news! [S2] (surprised) Really?" \
--engine cosyvoice --speakers s1=alice.wav,s2=bob.wav -o combined.wav
# 自由形式的指令标签
.build/release/speech speak "(Speak like a pirate) Ahoy matey!" \
--engine cosyvoice -o pirate.wav
# 全局指令(对所有没有情感标签的段生效)
.build/release/speech speak "Hello world" \
--engine cosyvoice --cosy-instruct "Speak cheerfully" -o cheerful.wav
内置情感标签
| 标签 | 指令 |
|---|---|
happy / excited | 开心且充满兴奋地说话。 |
sad | 以忧郁的语气悲伤地说话。 |
angry | 带着愤怒和强烈的情绪说话。 |
whispers / whispering | 轻柔地悄声低语。 |
laughs / laughing | 一边笑一边说话。 |
calm | 平静、祥和地说话。 |
surprised | 带着惊讶和惊奇说话。 |
serious | 以严肃、正式的语气说话。 |
未知标签会按自由形式指令处理,因此 (Speak in a slow, dramatic voice) 可直接使用。
模型控制令牌(fl_ 令牌)
在内部,CosyVoice3 的 LLM 使用以 fl_ 为前缀的特殊控制令牌,用于在不同模式之间切换(零样本克隆、指令合成、保存说话人等)。这些令牌属于上游 FunAudioLLM 分词器;Soniqo 运行时会根据您使用的 CLI 标志或 Swift API 调用自动发出正确的令牌,因此您无需手动书写它们。
| 控制令牌 | 模式 | 如何从 Soniqo 调用 |
|---|---|---|
<|fl_speaker_clone|> | 从参考音频样本进行零样本声音克隆 | 在 CLI 上传入 --voice-sample reference.wav,或在 Swift API 上设置 voiceSample:。 |
<|fl_speaker_instruct|> | 在默认声音上进行指令或风格条件合成 | 传入 --cosy-instruct "Speak cheerfully",或不带 --voice-sample 使用内联 (happy) 标签。 |
<|fl_speaker_instruct2|> | 在克隆参考声音上进行指令合成 | 在同一次调用中将 --voice-sample reference.wav 与 --cosy-instruct "..."(或内联情绪标签)结合使用。 |
<|fl_save_speaker|> | 持久化说话人嵌入,免去每次重新编码参考音频 | Soniqo CLI 中未直接暴露 — 嵌入按调用计算。如需缓存,请通过 说话人嵌入 模块自行提取 192 维的 CAM++ 向量并向下传递。 |
<|fl_speaker_clone_zh|>, <|fl_speaker_clone_en|>, … | 上游分词器使用的语言特定零样本克隆提示 | 将 --voice-sample 与 --language german|spanish|chinese|... 结合使用。Soniqo 会根据 --language 标志选择正确的语言提示。 |
上表将每个上游 fl_ 控制令牌映射到其 Soniqo 等价物。您无需自己将 fl_ 令牌拼接到提示中 — 传入高级 CLI 标志或 Swift API 参数即可,运行时会自动发出正确的序列:clone → instruct → instruct2 → save_speaker。
采样
LLM 阶段使用如下采样配置:
| 参数 | 数值 |
|---|---|
| Top-k | 25 |
| Top-p | 0.8 |
| 重复感知采样 | 启用(window=10,tau_r=0.1) |
重复感知采样(RAS,源自 VALL-E 2)会惩罚最近 10 个已生成 token 中出现过的 token。这可防止重复的音频伪影并提升输出稳定性。
性能
在 M2 Max 上,CosyVoice3 的 RTF 约为 0.5 — 快于实时。
| 阶段 | 延迟 |
|---|---|
| LLM(已编译) | ~13 ms/token |
| DiT 流匹配 | 370 - 520 ms |
| HiFi-GAN | 50 - 170 ms |
LLM 阶段对自回归循环使用 compile(shapeless: true),消除了跨不同序列长度的重复编译开销。批量翻倍的 CFG 将 DiT 前向次数从 20 减半到 10。