mlx-audio MOSS-TTS 实战指南:8B 多码本 TTS 的音色克隆、多说话人对话与流式合成

原创2026-09-15 10:10:012,215 阅读
文章标签:语音音频人工智能本地部署模型推理服务

mlx-audio MOSS-TTS 实战指南:8B 多码本 TTS 的音色克隆、多说话人对话与流式合成

本篇基于 mlx-audio 仓库中 MOSS-TTS 模型模块的官方说明与配套源码,覆盖 5 个受支持检查点(8B MossTTSDelay v1.5/v1.0、MOSS-TTSD-v1.0 对话模型与两代 Local-Transformer 变体)的加载、Python API、CLI 调用、音色克隆、多说话人对话与流式合成的完整用法,并深入到 Qwen3 骨干、多码本(RVQ)延迟模式与 MOSS Audio Tokenizer 解码的工程实现细节。读完后你可以直接在 Apple Silicon 上运行 MOSS-TTS 系列模型,理解其采样参数、prompt 模板结构与流式分块机制,并按需调整生成行为。

支持的模型与选择

mlx-audio 中的 MOSS-TTS 实现位于 mlx_audio/tts/models/moss_tts/,官方说明见 mlx_audio/tts/models/moss_tts/README.md,文档站版本见 docs/models/tts/moss-tts.md。它覆盖 OpenMOSS 的 8B MossTTSDelay v1.5 与 v1.0 模型、MOSS-TTSD-v1.0 对话模型,以及两代 Local-Transformer 变体,全部使用 Qwen3 骨干与对应的多码本音频生成路径,并搭配完整版 MOSS Audio Tokenizer。主 README.md 的模型列表将该系列标注为支持 31 种语言、带音色克隆的 8B 级多语言 TTS。

仓库中受支持的检查点(Hugging Face 仓库 ID,可直接传给 load):

模型 ID 说明 音频 Tokenizer
OpenMOSS-Team/MOSS-TTS-v1.5 8B MossTTSDelay v1.5,延迟模式(delay pattern)生成 OpenMOSS-Team/MOSS-Audio-Tokenizer
OpenMOSS-Team/MOSS-TTS 8B MossTTSDelay v1.0 OpenMOSS-Team/MOSS-Audio-Tokenizer
OpenMOSS-Team/MOSS-TTSD-v1.0 多说话人对话模型([S1]/[S2] 标记) OpenMOSS-Team/MOSS-Audio-Tokenizer
OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5 v1.5 本地 Transformer 变体,支持流式 OpenMOSS-Team/MOSS-Audio-Tokenizer-v2(48 kHz 输出)
OpenMOSS-Team/MOSS-TTS-Local-Transformer v1.0 本地 Transformer 变体(legacy 路径) OpenMOSS-Team/MOSS-Audio-Tokenizer

从源码结构看,检查点的差异由 config.py 中的 model_type 字段驱动:moss_tts_delay(默认)走延迟模式路径;model_type == "moss_tts_local" 或存在 gpt2_config 时判定为 v1.5 本地 Transformer(is_v15_local_transformer,见 config.py#L59-L73);同时给出 additional_mlp_ffn_hidden_size、local_ffn_hidden_size、local_hidden_size、local_num_layers 四个字段时判定为 legacy 本地 Transformer(is_legacy_local_transformer)。Tokenizer 仓库的默认值也在同一文件中定义:v1.5 本地变体缺省指向 OpenMOSS-Team/MOSS-Audio-Tokenizer-v2,其余指向 OpenMOSS-Team/MOSS-Audio-Tokenizer(见 config.py#L10-L11 与 config.py#L142-L150)。

快速开始:Python API

基本用法——加载模型后调用 generate,取首个 GenerationResult 并写盘:

from mlx_audio.audio_io import write as audio_write
from mlx_audio.tts import load

model = load("OpenMOSS-Team/MOSS-TTS-v1.5", lazy=True)

result = next(model.generate(
    text="Hello, this is MOSS-TTS running on MLX.",
    max_tokens=120,
))
audio_write("output.wav", result.audio, result.sample_rate)

说明:

  • lazy=True 延迟加载权重,适合先构建管线再触发计算;
  • generate 是生成器,max_tokens 限制最大新生成 token 数(源码默认上限为 4096,见下文参数详解);
  • result.audio 为波形 mx.array,result.sample_rate 为采样率(配置默认 24000 Hz,v1.5 本地变体为 48000 Hz),二者可直接配合 mlx_audio.audio_io.write 保存。

音色克隆

传入 ref_audio 即可完成参考音色克隆,参考音频在内部由 MOSS Audio Tokenizer 编码为多码本音频码,注入用户 prompt:

result = next(model.generate(
    text="This is a short cloned voice sample.",
    ref_audio="speaker.wav",
    max_tokens=120,
))
audio_write("cloned.wav", result.audio, result.sample_rate)

CLI 调用

同样的能力可以通过命令行直接触发,入口是 mlx_audio/tts/generate.py 模块:

python -m mlx_audio.tts.generate \
  --model OpenMOSS-Team/MOSS-TTS-v1.5 \
  --text "Hello, this is MOSS-TTS running on MLX." \
  --output_path outputs

多语言与语言提示

对 v1.5 的非英语多语言 prompt,已知语种时建议显式传入 language:

result = next(model.generate(
    text="Bonjour, je voudrais essayer une voix francaise naturelle.",
    language="French",
    max_tokens=120,
))

language 会作为独立字段写入用户指令模板(见下文 prompt 模板一节)。此外,内联停顿标记(如 [pause 3.2s])会原样透传到 v1.5 prompt 中,可用于控制生成节奏。

generate() 参数详解

generate 的完整签名为 generate(text, ref_audio=None, ref_text=None, prompt_audio_codes=None, mode="generation", stream=False, max_tokens=None, **kwargs)(见 moss_tts.py#L1442-L1452)。除官方文档示例中的参数外,kwargs 还可接收一组采样与流式参数。不同模型分支的默认值不同,汇总如下(默认值取自源码中各生成分支的 kwargs.get 回退值):

参数 延迟模式(MossTTSDelay) v1.5 本地 Transformer legacy 本地 Transformer
max_tokens(max_new_tokens) 默认 4096,可被检查点 generation_config.json 覆盖 4096 4096
text_temperature 1.5(可被 generation_config.json 的 temperature 覆盖) 1.0 1.5
text_top_p 1.0 1.0 1.0
text_top_k 50 50 50
audio_temperature(兼容别名 temperature) 1.7 1.7 1.0
audio_top_p(兼容别名 top_p) 0.8 0.8 0.95
audio_top_k(兼容别名 top_k) 25 25 50
audio_repetition_penalty 1.0 1.0 1.1
do_sample 由温度是否为正隐式决定 默认 True 由温度是否为正隐式决定
use_kv_cache —(默认启用 prompt cache) True —(默认启用)
n_vq_for_inference 可截断生效的 RVQ 通道数 必须等于模型配置的 12,否则报错 可截断生效通道数

对应的取参逻辑见 moss_tts.py#L1566-L1649。两点使用注意:

  1. temperature/top_p/top_k 这些通用别名会被路由到音频通道(audio_temperature 优先,回退到 temperature),文本通道始终使用 text_* 前缀参数;
  2. 延迟模式分支还会读取检查点目录下的 generation_config.json(_load_generation_config,见 moss_tts.py#L348-L362),作为各采样参数的缺省来源,显式传入的 kwargs 优先。

mode 支持 generation(含音色克隆,voice_clone/direct 会被归一化为 generation)与 continuation(续写:给定一段参考音频继续生成,只接受单个参考音频与单条 ref_text,见 moss_tts.py#L1483-L1495)。

对话生成:MOSS-TTSD-v1.0

MOSS-TTSD-v1.0 支持在同一轮合成中按 [S1]、[S2] 标记切换说话人:

python -m mlx_audio.tts.generate \
  --model OpenMOSS-Team/MOSS-TTSD-v1.0 \
  --text "[S1] Hello. [S2] Hi, this is MOSS-TTSD running on MLX." \
  --output_path outputs

为每个说话人绑定独立参考音色时,可以重复传入 --ref_audio / --ref_text(顺序对应 S1、S2):

python -m mlx_audio.tts.generate \
  --model OpenMOSS-Team/MOSS-TTSD-v1.0 \
  --text "[S1] This uses the first reference. [S2] This uses the second." \
  --ref_audio speaker_1.wav \
  --ref_text "Reference transcript for speaker one." \
  --ref_audio speaker_2.wav \
  --ref_text "Reference transcript for speaker two." \
  --output_path outputs

其背后机制在 processor.py 的 UserMessage 中:参考列表按说话人下标渲染为 <a href="https://link.gitcode.com/i/6941e155a89d4fc5676251afd36ef8eb" target="_blank">S1]:、[S2]: 前缀加音频占位符 <|audio|>(见 [processor.py#L53-L68),无参考的说话人渲染为 [S{n}]: None。多个连续占位符会被 _merge_consecutive_audio_placeholders 合并,对应的音频码在时间轴上拼接,保证多段参考映射到同一段连续音频块。

v1.5 Local-Transformer 变体与流式合成

v1.5 本地 Transformer 检查点单独加载:

model = load("OpenMOSS-Team/MOSS-TTS-Local-Transformer-v1.5", lazy=True)

该变体的三个关键事实(官方说明 + 源码印证):

  • 使用 OpenMOSS-Team/MOSS-Audio-Tokenizer-v2,输出 48 kHz 采样率;
  • 采用固定 12 码本的 RVQ 深度——n_vq_for_inference 若传入与 12 不同的值会直接抛错(_resolve_v15_fixed_nq,见 moss_tts.py#L581-L588),prompt 构建侧同样有校验(_assert_fixed_nq,processor.py#L692-L699);
  • 本地 Transformer 结构由 GPT-2 风格小 Transformer 实现(local_transformer_layers 默认 1,local_text_head_mode 默认 "full_vocab",use_static_local_kv_cache 默认 True,见 config.py#L39-L44)。

流式生成

目前仅 MOSS-TTS-Local-Transformer-v1.5 支持流式,其余变体传入 stream=True 会抛出 NotImplementedError(见 moss_tts.py#L1528-L1532):

chunks = model.generate(
    text="Hello, this is streamed MOSS local transformer audio.",
    language="English",
    stream=True,
    streaming_interval=2.0,
)

for chunk in chunks:
    play_or_buffer(chunk.audio, chunk.sample_rate)

流式行为的关键实现细节(_generate_v15_local_streaming_results,见 moss_tts.py#L1254-L1397):

  • 音频 Tokenizer v2 的帧率为 12.5 帧/秒,每帧对应 采样率 / 12.5 个采样点(48 kHz 下为 3840 个);
  • 首块默认在生成满 4 帧 RVQ 码后即解码输出(first_chunk_frames,可通过 streaming_first_chunk_frames 调整),用于压低首包延迟;
  • 后续块以 streaming_interval(默认 2.0 秒,换算成 interval × 12.5 帧)为步进输出;
  • 默认开启 streaming_use_codec_session,MLX 路径为每次 generate 调用维护单流式 MOSS-Audio-Tokenizer-v2 解码器会话逐帧解码,无需上游流式 demo 依赖的 SGLang 服务器;关闭会话时回退到批量解码路径,并携带 streaming_context_frames(默认 8 帧)上下文、解码后裁掉上下文部分;
  • 每个 chunk 是一个带 is_streaming_chunk / is_final_chunk 标记的 GenerationResult,最后一个 chunk 标记 is_final_chunk=True。

源码级架构解析

三条并行的模型实现分支

Model.__init__ 根据配置分派三种结构(见 moss_tts.py#L213-L306):

  1. v1.5 本地 Transformer:Qwen3Model 全局骨干 + 每码本独立的 audio_embeddings/audio_lm_heads + GPT2 风格本地 Transformer(local_gpt2_config() 会把 n_positions/n_ctx 设为 n_vq + 1、n_layer 设为 local_transformer_layers)。前向时,全局骨干产出的隐状态与每个已采样码本的嵌入按位置堆叠,送入本地 Transformer 做码本间的自回归细化(_v15_local_forward,见 moss_tts.py#L590-L650);
  2. legacy 本地 Transformer:MosiTTSModel(Qwen3 骨干 + 每通道嵌入表)+ 可学习维度的 MossTTSLocalTransformer,通过 speech_embedding_to_local_mlp 与每通道 local_to_speech_embedding_mlps 做维度桥接,每个通道各有一个 RMSNorm 与 LM head(_local_forward,见 moss_tts.py#L652-L707);
  3. 延迟模式(MossTTSDelay,默认):Qwen3 骨干 + 文本词表嵌入加 n_vq 个扩展音频嵌入(emb_ext),输出 1 + n_vq 个 LM head——第 0 个预测文本/控制 token,其余每个预测一个 RVQ 码本。嵌入方式为各通道嵌入相加(_build_inputs_embeds,见 moss_tts.py#L445-L458)。

所有分支共用 mx.array 形状 [batch, seq, n_vq + 1] 的多通道 token 表示:第 0 列是文本/控制 token 通道,其余各列是一个 RVQ 码本。

延迟模式(delay pattern)如何工作

延迟模式是该系列最核心的机制:RVQ 各码本通道在时间轴上错开 1 帧,使得“同一时间步先定文本控制位、再按通道顺序解码各码本”成为可能。

  • 编码侧:apply_delay_pattern 将 <a href="https://link.gitcode.com/i/99b3c277039ae6247708822de23c7914" target="_blank">frames, n_vq] 的码表沿对角线展开为 [frames + n_vq - 1, n_vq],各通道整体下移([processor.py#L117-L129);
  • 解码侧:生成结束后由 apply_de_delay_pattern 还原(processor.py#L132-L145,在 _decode_generated_audio 中被调用,仅对非本地变体执行,见 moss_tts.py#L1183-L1229);
  • 生成循环:generate_delay_pattern_ids(moss_tts.py#L730-L906)中,文本通道用一组专用控制 token 驱动状态机——audio_start(151652)进入音频段,assistant_gen_slot(151656)逐帧推进,delay_slot(151662)用于码本间的延迟填充,audio_end(151653)退出音频段;音频码本解码时,audio_pad_code(1024)的 logits 被置为 -inf,并按 audio_repetition_penalty 对已生成 token 施加惩罚。所有控制 token ID 的默认值定义在 config.py#L20-L33;
  • 采样原语:sample_token 统一实现了 repetition penalty(对正 logits 除、负 logits 乘)、top-k、top-p 与温度缩放,基于 mx.random.categorical 采样(sampling.py#L67-L91)。

从源码结构看,生成循环对 batch_size != 1 会抛出 NotImplementedError,即当前实现为逐条串行生成。

Prompt 模板与文本预处理

v1.5 用户消息由结构化模板渲染(LocalV15UserMessage,processor.py#L573-L633),字段依次为 Reference(s)、Instruction、Tokens、Quality、Sound Event、Ambient Sound、Language、Text,未提供的字段渲染为 None;延迟模式模板(UserMessage)在 n_vq == 16 且非本地变体时还会附加 Scene 字段(见 processor.py#L172-L174)。因此除了 text、ref_audio、language 外,generate(**kwargs) 还可传入 instruction、tokens、quality、sound_event、ambient_sound、scene 等字段(moss_tts.py 中 user_kwargs 的构造见 moss_tts.py#L1498-L1509)。

进入模板前,文本会先经过 normalize_tts_text(text.py#L33-L46)做上游 v1.5 风格的清理:移除零宽与控制字符、去 Markdown 标记、保护 URL/邮箱/@提及/话题标签/点号 token/文件名等片段不被标点归一化破坏、压缩 CJK 与拉丁字符间的空格、合并重复标点(含 !? 混合折叠)。这解释了为什么 [pause 3.2s] 这类内联标记能安全透传——点号 token 与括号结构都被保护或规范化处理过。

加载钩子与量化策略

  • post_load_hook 从模型目录加载 AutoTokenizer(v1.5 本地变体会额外传 fix_mistral_regex=True,并在旧版 transformers 不识别该参数时回退),同时加载 generation_config.json(moss_tts.py#L324-L358);
  • model_quant_predicate 明确排除音频嵌入相关模块(audio_embeddings、emb_ext、model.embedding_list、audio_tokenizer)不参与量化(moss_tts.py#L371-L379)——从源码结构看,这是为避免多码本嵌入表量化损伤音色还原;
  • 音频 Tokenizer 通过 MossAudioTokenizer.from_model_dir 懒加载,优先查找模型目录内嵌的 tokenizer 权重,找不到时回退到配置中的 audio_tokenizer_pretrained_name_or_path(_ensure_audio_tokenizer,moss_tts.py#L389-L403)。

结果对象与注意事项

generate 产出的 GenerationResult 除 audio、sample_rate 外还携带诊断信息:audio_duration(时字符串)、real_time_factor(音频时长/处理耗时)、prompt 与音频采样吞吐、peak_memory_usage、流式标记(_build_generation_result,moss_tts.py#L1399-L1440),可直接用于监控实时率。

使用限制小结(均以当前仓库实现为准):

  1. v1.5 本地变体 n_vq_for_inference 只能是 12,否则两处都会抛 ValueError;
  2. 流式合成目前仅 MOSS-TTS-Local-Transformer-v1.5 可用,其余变体传 stream=True 报错;
  3. 生成循环不支持 batch(batch_size 必须为 1);
  4. continuation 模式要求提供 ref_audio 或 prompt_audio_codes,且只接受单段参考;
  5. 采样率取决于检查点:配置默认 24000 Hz,v1.5 本地变体经 Tokenizer v2 输出 48000 Hz,写盘时务必使用 result.sample_rate 而非硬编码值。

相关入口与文件索引:模型实现 mlx_audio/tts/models/moss_tts/moss_tts.py、配置 mlx_audio/tts/models/moss_tts/config.py、prompt 处理 mlx_audio/tts/models/moss_tts/processor.py、采样 mlx_audio/tts/models/moss_tts/sampling.py、文本规范化 mlx_audio/tts/models/moss_tts/text.py、CLI mlx_audio/tts/generate.py、官方说明 mlx_audio/tts/models/moss_tts/README.md。

登录后查看全文
mlx-audio