Higgs Audio v3 TTS:基于 Qwen3 与 MLX 的多码本对话式语音合成实战指南
Higgs Audio v3 TTS:基于 Qwen3 与 MLX 的多码本对话式语音合成实战指南
Higgs Audio v3 TTS 是 mlx-audio 中一款基于 Qwen3 骨干网络的对话式语音合成(TTS)模型,核心能力包括融合多码本(fused multi-codebook)音频 token 生成、内联控制 token、多语言语音合成与零样本声音克隆。本文以 docs/models/tts/higgs_audio_v3.md 为骨架,结合仓库源码与测试,系统讲解 CLI / Python 两套调用方式、声音克隆(含预编码与批量复用)、内联控制 token,以及延迟模式采样与多码本融合等底层机制,读完即可在 Apple Silicon 上跑通完整链路并理解其工作原理。
模型概览与核心特性
Higgs Audio v3 TTS 是 bosonai/higgs-audio-v3-tts-4b 的 MLX 实现,具有以下关键特性:
- Qwen3 骨干:语言与音频统一建模,文本 backbone 直接复用 Qwen3Model(见 model.py)。
- 融合多码本音频 token:通过单一
multimodal_embedding将 8 个码本(codebook)的音频 token 融合为隐藏向量,再经线性头直接输出多码本 logits。 - 内联控制 token:情感(emotion)、韵律(prosody)、音效(sfx)等控制符可直接写入输入文本。
- 多语言与零样本声音克隆:通过参考音频 + 转写文本(transcript)实现克隆,支持单参考与多参考。
从源码看模型结构
模型配置集中在 config.py:
| 配置项 | 默认值 | 含义 |
|---|---|---|
text_config.hidden_size |
2560 | Qwen3 backbone 隐藏维度 |
text_config.num_hidden_layers |
36 | 层数 |
text_config.vocab_size |
151936 | 文本词表大小 |
audio_num_codebooks |
8 | 音频码本数量 |
audio_codebook_size |
1026 | 单码本词表大小 |
audio_boc_token_id |
1024 | 码本开始(begin-of-codebook)token |
audio_eoc_token_id |
1025 | 码本结束(end-of-codebook)token |
use_delay_pattern |
True | 是否使用延迟模式(delay pattern) |
sample_rate |
24000 | 输出采样率 24 kHz |
模型加载时的识别线索在 init.py:上游权重中的 model_type: higgs_multimodal_qwen3 与路径模式 higgs_audio_v3 / higgs-audio-v3 都会被自动映射到本实现。
快速开始:CLI 一行合成
安装 mlx-audio 后,直接使用 TTS 生成入口 python -m mlx_audio.tts.generate:
python -m mlx_audio.tts.generate \
--model bosonai/higgs-audio-v3-tts-4b \
--text "Hello from Higgs Audio v3 on MLX."
默认在 outputs/ 目录下写出 WAV 文件(audio_000.wav 等)。常用参数如下(定义见 generate.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
--model |
必填 | 模型 repo id 或本地路径 |
--text |
无 | 要合成的文本;不传则从 stdin 或交互输入读取 |
--output_path |
None |
输出目录,不传则写当前目录 |
--file_prefix |
audio |
输出文件名前缀 |
--audio_format |
wav |
输出格式(如 wav、flac) |
--temperature |
0.7 |
采样温度 |
--top_p |
0.9 |
核采样阈值 |
--top_k |
50 |
顶层采样数量 |
--ref_audio / --ref_text |
无 | 参考音频路径与转写文本,可重复传多个 |
--stt_model |
whisper-large-v3-turbo | 若缺 ref_text,用于自动转写参考音频 |
--play / --stream / --save |
关 | 播放 / 流式生成 / 保存流式音频 |
--verbose |
关 | 打印时长、tokens-per-sec、实时率等统计 |
注意:CLI 层会通过 _model_accepts_ref_text 探测模型是否支持 ref_text 参数(generate.py)。若用户只给了 --ref_audio 而未给 --ref_text,框架会自动调用 STT 模型转写参考音频作为克隆所需的对齐文本,这也是 --stt_model 参数存在的意义。
Python API:加载、生成与结果字段
Python 侧推荐从 mlx_audio/tts/utils.py 的 load 入口加载模型(它会自动识别 higgs_multimodal_qwen3 类型并实例化 higgs_audio_v3 的 Model):
from mlx_audio.tts.utils import load
from mlx_audio.audio_io import write as audio_write
model = load("bosonai/higgs-audio-v3-tts-4b")
for result in model.generate(
text="Hello from Higgs Audio v3 on MLX.",
ref_audio="reference.wav",
ref_text="Reference transcript.",
temperature=1.0,
max_new_tokens=2048,
):
audio_write("output.wav", result.audio, result.sample_rate)
generate 是生成器,每个 result 为 GenerationResult,字段包括:
audio/sample_rate:MLX 音频数组(24 kHz)与采样率;audio_duration:格式化时长(HH:MM:SS.mmm);token_count:生成的延迟行(delayed rows)数量;real_time_factor:实时率(合成耗时 / 音频时长);prompt:tokens、completion_tokens、tokens-per-sec;audio_samples:samples、samples-per-sec;processing_time_seconds与peak_memory_usage(峰值显存,GB)。
generate 参数速查
| 参数 | 默认值 | 说明 |
|---|---|---|
text |
必填 | 目标文本 |
ref_audio / ref_text |
None |
参考音频(路径或数组)及其转写文本 |
ref_audio_codes / ref_audio_codes_list |
None |
预编码的参考音频码,跳过重新编码 |
references |
None |
ReferenceCodes 或 {"codes"/"audio", "text"} 字典列表 |
max_new_tokens / max_new_frames / max_tokens |
2048 |
生成上限,按优先级取第一个非空值 |
temperature |
1.0 |
采样温度 |
top_p / top_k |
None |
核采样 / 顶层采样,None 表示不启用 |
seed |
None |
随机种子(设置后调用 mx.random.seed) |
fade_in_ms / fade_out_ms |
30.0 / 15.0 |
首尾淡入淡出时长,用于抑制首帧瞬态 |
stream |
False |
流式标记(本模型当前不实现流式) |
一个使用细节:ref_audio 与 ref_audio_codes 互斥,同时传入会抛 ValueError: Use either ref_audio or ref_audio_codes, not both(model.py);ref_text 的数量必须与参考音频一一对应。
零样本声音克隆
克隆分为三步:准备参考音频 → 编码为音频码 → 生成。
1. CLI 方式(单参考 / 多参考)
单参考:
python -m mlx_audio.tts.generate \
--model bosonai/higgs-audio-v3-tts-4b \
--text "Have a nice day and enjoy the sunshine." \
--ref_audio reference.wav \
--ref_text "Reference transcript."
多参考时重复 --ref_audio / --ref_text 即可(action="append",见 generate.py):
python -m mlx_audio.tts.generate \
--model bosonai/higgs-audio-v3-tts-4b \
--text "Let's keep the same voice across this line." \
--ref_audio speaker_1.wav \
--ref_text "First reference transcript." \
--ref_audio speaker_2.wav \
--ref_text "Second reference transcript."
若多个 ref_text 但缺少 ref_audio,CLI 会报错要求成对提供(generate.py)。
2. Python 方式:encode 一次,复用多次
同一参考音色要在多个生成任务中复用时,可先用 encode_reference_audio 编码一次,之后把预编码码直接传给 ref_audio_codes,完全跳过参考音频编码环节:
reference_codes = model.encode_reference_audio("reference.wav")
for result in model.generate(
text="This skips reference audio encoding.",
ref_audio_codes=reference_codes,
ref_text="Reference transcript.",
temperature=1.0,
):
audio_write("output.wav", result.audio, result.sample_rate)
从源码看,encode_reference_audio 的流程是(model.py):
- 将参考音频统一重采样到模型采样率(24 kHz)、转单声道并归一化,短于 1 秒会右端补零到 1 秒;
- 调用 Higgs 声学 tokenizer 的
encode得到原始码本码(raw codes); - 通过
apply_delay_pattern套用延迟模式,填充 BOC/EOC 标记,返回可直接拼接进 prompt 的延迟码。
配套测试 test_higgs_audio_v3.py 验证了「编码结果 == 原始码 + 延迟模式」,并断言传入 ref_audio_codes 时 codec 的 encode 不会被再次调用(L262-L276)。
3. 批量生成复用同一参考
batch_generate 支持一个预编码参考服务多条文本,结果通过 sequence_idx 区分:
reference_codes = model.encode_reference_audio("reference.wav")
texts = [
"The first line uses the cloned voice.",
"The second line is generated in the same batch.",
]
for result in model.batch_generate(
texts=texts,
ref_audio_codes=reference_codes,
ref_text="Reference transcript.",
temperature=1.0,
):
audio_write(f"output_{result.sequence_idx}.wav", result.audio, result.sample_rate)
batch_generate 返回 BatchGenerationResult,除 sequence_idx 外同样携带 token_count、audio_duration、processing_time_seconds 等统计。实现上会把多条 prompt 左侧 padding 对齐后一次前向(model.py),并复用 BatchKVCache;测试 test_batch_generate_reuses_shared_reference_audio 验证共享参考时 codec 只编码一次,且批量结果与串行结果在 token_count、samples 上完全一致(L407-L439)。
注意事项:
- 参考音频建议选用 5~15 秒的干净人声(仓库示例脚本 examples/higgs_audio_clone_demo.py 的文档注释同样建议该时长范围),
ref_text必须是参考片段逐字转写文本,否则克隆对齐会不稳定; - 语音、速度、音调类参数在本模型中不可用:
supports_tts_batch规定stream、voice、instruct、speed≠1.0、pitch≠1.0、gender≠male均不支持(model.py),批量 API 中传入会直接抛ValueError。
内联控制 token
上游模型支持把控制 token 直接写进输入文本,例如:
<|emotion:amusement|><|prosody:expressive_high|>That was unexpected. <|sfx:laughter|>Hehe.
用法要点:
emotion(情感)、prosody(韵律)、sfx(音效)等 token 由上游 tokenizer 提供,必须与模型支持的取值一致;- 对音效标签,需按上游指引在标签后附带对应的文字拟声词(如示例中的
Hehe),便于模型对齐生成; - 这些 token 会被 tokenizer 直接编码进文本序列。从 prompt.py 可以看到,prompt 由
<|tts|>起始,参考段以<|ref_text|>/<|ref_audio|>组织,随后<|text|>包裹目标文本,最后以<|audio|>收尾——控制 token 属于<|text|>段的一部分,随文本一起编码。
批量 / 连续批处理机制
除一次性 batch_generate 外,模型还通过 continuous_batching.py 的 HiggsAudioV3BatchSession 支持持续入队的批处理会话:
- 事件模型:
TTSBatchOptions(含max_batch_size、max_tokens、temperature、top_p、top_k等,见 continuous.py)配置会话,TTSBatchItem入队,step()推进一个解码步并产出TTSBatchEvent; - 动态调度:
available_slots决定能接纳多少新请求,每个step()先推进活跃请求、再吸纳待处理请求,且每 50 步执行一次mx.clear_cache()控制显存; - 优雅终止:请求解码完毕或达到
max_tokens即产出done=True的事件;cancel(sequence_id)支持按序列号移除请求并同步裁剪 KV cache(continuous_batching.py)。
测试 test_continuous_batch_session_matches_serial 验证了连续批处理输出与串行生成逐 token、逐样本一致。
生成机制与源码剖析
融合多码本嵌入与线性头
音频码不走独立 embedding 表,而是把 8 个码本平铺成一个超大嵌入表:multimodal_embedding 尺寸为 audio_num_codebooks * audio_codebook_size × hidden_size。编码时对每个码本施加 codebook_idx * audio_codebook_size 的偏移后取嵌入并求和(model.py),解码 logits 则由同一个嵌入表转成线性头后 reshape 为 <a href="https://link.gitcode.com/i/47d01120a9941368227ec47de085a701" target="_blank">num_codebooks, codebook_size]([L152-L158)。测试 test_fused_embedding_and_head_shapes 直接验证了该融合求和逻辑。
延迟模式:ramp-in 与 wind-down
多码本音频解码采用 SGLang 兼容的延迟模式(delayed pattern),核心在 generation.py:
apply_delay_pattern:把原始码<a href="https://link.gitcode.com/i/c0c0b0e9b129316336a337623080849c" target="_blank">T, N]展开为延迟行[T+N-1, N],第 k 个码本整体右移 k 步,左侧缺口用 BOC token 填充([L24-L39);reverse_delay_pattern:解码完成后逆向还原为原始码(L42-L56),测试 test_delay_pattern_round_trip 保证两者可无损往返;- 采样状态机
HiggsSamplerState:delay_count控制前 N 步的码本逐个“点亮”(后续码本强制输出 BOC);首个码本命中 EOC 后进入eoc_countdown = N-2的收尾倒计时,保证各码本同步结束(step),对应测试 test_ramp_in_forces_later_codebooks_to_boc 与 test_eoc_wind_down。
采样策略
sample_independent / sample_batch(generation.py)在每个解码步对全部码本独立采样:先按温度缩放 logits,再依次施加 top-k 与 top-p 裁剪,最后 mx.random.categorical 采样;当 temperature <= 1e-5 或 top_k == 1 时退化为贪心 argmax。
解码与后处理
生成结束后,_decode_audio(model.py)将收集到的延迟行 stack、reverse_delay_pattern 还原、经 HiggsAudioTokenizer.decode 直接得到波形(<a href="https://link.gitcode.com/i/92d1ba8a56302b4703dae77b51663e98" target="_blank">T, 8] → 约 T*960 个样本,见 [higgs_audio.py),随后按 fade_in_ms=30 / fade_out_ms=15 施加首尾线性淡入淡出以抑制瞬态(L353-L367)。
模型转换、量化与加载细节
如需把上游 PyTorch 权重转为 MLX 格式或做量化,可使用仓库的转换入口 mlx_audio.convert(参数见 convert.py):
python -m mlx_audio.convert \
--hf-path bosonai/higgs-audio-v3-tts-4b \
--mlx-path mlx_model \
--quantize \
--q-bits 4
要点:
--hf-path接受 HuggingFace repo id,--mlx-path指定输出目录(默认mlx_model),--quantize/--q-bits/--q-group-size/--q-mode控制量化;- 模型自带的
model_quant_predicate(model.py)会跳过multimodal_embedding,只量化nn.Linear与nn.Embedding权重,避免损伤音频嵌入精度; - 权重重命名逻辑在
sanitize(L112-L135):上游的tied.embedding.text_embedding.*、body.layers.*、body.norm.*映射到 MLX 的backbone.*,tied.embedding.modality_embeddings.0.embedding.*映射到multimodal_embedding.*,音频头相关权重会被剔除,对应测试 test_sanitize_maps_source_keys; - 类型识别测试 test_loader_remapping 与 test_higgs_v3_upstream_model_type_resolves_to_local_implementation 确认
higgs_multimodal_qwen3会稳定解析到higgs_audio_v3实现。
加载模型时,post_load_hook(model.py)会自动装配三件套:文本 tokenizer(读取 tokenizer.json)、HiggsAudioV3PromptBuilder、以及 Higgs 声学 codec——若模型目录下存在 audio_tokenizer/ 子目录则走 from_pretrained,否则直接从主 TTS 检查点中按 tied.embedding.modality_embeddings.0.model.* 前缀抽取 codec 权重(higgs_audio.py)。因此克隆用的参考音频编码完全在 MLX 侧完成,不依赖任何外部框架。
许可与使用限制
- 上游模型采用 Boson Higgs Audio v3 Research and Non-Commercial License,仅供研究与非商业用途,商用前请查阅原模型卡与许可证文件确认合规要求;
- 本实现依赖 Apple Silicon(MLX 框架),不支持 CPU 之外的通用 GPU 环境;
- 当前版本
stream=True的批量流式未实现(batch_generate会抛NotImplementedError),且voice/instruct/speed/pitch等通用 TTS 参数在本模型上不可用,克隆音色统一走ref_audio+ref_text路径。