上一篇讲 MOSS-Audio-Tokenizer 时说过:OpenMOSS 把音频 tokenizer 当成大模型来训,铸出了一套「既能听又能懂」的币。币铸好了,接下来自然是问:拿它买什么?
答案是 MOSS-TTS——OpenMOSS(MOSI.AI)与上海创智学院、复旦大学联合发布的语音生成基础模型,也是整个 MOSS-TTS 全家桶的主干。本文材料来自 2026 年 3 月的《MOSS-TTS Technical Report》(arXiv:2603.18090)和官方 GitHub 仓库;报告对应 1.0 版模型,仓库如今已推进到 v1.5,版本差异后文会标注。
先交代论文的立场,它写在引言里,态度相当鲜明。近几年的语音生成为了「既像人又稳定」,方案越堆越厚:中间表示、外挂语义老师、精修阶段、事后对齐……论文说,这些设计各有效果,但每加一个模块,就多一份监督契约、多一类失效模式、多一段延迟预算——模块本身成了 scaling 的阻力。MOSS-TTS 的答案是做减法,只留三样家常菜:
一个高质量音频 tokenizer + 一个自回归 Transformer + 大规模预训练。
tokenizer 把语音变成离散 token 之后,语音合成就成了「预测下一个 token」——和语言模型同一个目标函数,于是语言模型积累的全部经验(数据管线、训练课程、推理引擎、量化部署)都能直接搬过来。这份报告要论证的就是:这条朴素配方,走到底够不够。
一、先把账摆上桌:每秒 12.5 帧 × 32 层的矩阵
快速回顾一下币长什么样(细节见前篇):MOSS-Audio-Tokenizer 把 24kHz 波形压到每秒 12.5 帧,每帧过 32 层 RVQ(残差向量量化)逐层逼近——第 1 层记大概轮廓,后面每层修上一层的残差,越深越细。每层码本 1024 条目,恰好 10 比特,于是全开 32 层就是 12.5 × 32 × 10 = 4kbps,只用前 1 层则是 0.125kbps,随用随取。
对生成模型来说,这意味着一段语音不是一串 token,而是一张表。举个例子,说一句两秒的「你好,我是 MOSS」:
时长 2 秒 → 25 帧(一帧 80ms)
每帧 32 层 RVQ → 25 × 32 = 800 个音频 token
自回归模型只会从左到右写一维序列,现在要它产出二维的表。论文说得直白:核心架构问题不是「要不要自回归」,而是「多流 token 块怎么编排」。 直觉上有两个笨办法,各有各的死法:
- 全部展平:按「第 1 帧 32 层、第 2 帧 32 层……」蛇形排开。依赖关系完整了,但序列长度乘 32——两秒的话 800 步,一小时的播客要 144 万步,训练推理都算不动;
- 一步齐出:每步让 33 个输出头把整帧全部层一次性并行吐出。序列短了,但同一帧内细层看不见粗层——好比伴奏没听到主旋律就下手,层与层各弹各的。
MOSS-TTS 给出的是两条中间路线,也是这份报告最值得看的地方:他们用同一个 tokenizer、同一份数据、同一套预训练配方,把两种编排各训了一个模型,摆在一起对比。用论文自己的话说,是为了「把 token 编排方式本身的影响隔离出来」——开源界少见的严格 A/B。
两条路线共享一个底座设定:每个对齐步预测 33 个通道——1 个文本通道加 32 个音频通道。文本前缀阶段,文本通道吐正常的文字 token;进入音频阶段后,文本通道吐专用的 pad 符号。这样文字和语音装在同一条序列里,一个模型通吃。训练目标是逐头加权的交叉熵:
λ = ( 1 | 3 3 3 | 2 2 | 1 × 27 )
文本 RVQ 1–3 RVQ 4–5 RVQ 6–32
前三层 RVQ 权重给到 3——粗层是骨架,骨架歪了细节无从谈起。
二、弹法一:Delay Pattern,像卡农一样错开进入
把那张 25 × 32 的表想成 32 个声部的乐谱,Delay Pattern(延迟模式,MOSS-TTS 本尊采用,源自 Meta 的 MusicGen)的弹法是轮唱:第 j 层声部比第 j−1 层晚一拍进入。
ã_{j,t} = a_{j, t−(j−1)} # 第 j 层整体右移 j−1 帧
错位之后再从左到右一步步走:第 t 步同时写下「第 1 层的第 t 帧、第 2 层的第 t−1 帧、……、第 32 层的第 t−31 帧」。妙处在于,纵向的帧内依赖被错位变成了横向的历史依赖——当第 5 层要写第 τ 帧时,第 1–4 层的第 τ 帧早在之前几步就写完了,躺在注意力能看见的历史里。层间该有的条件关系一点没丢,序列长度却只从 T 变成 T + 31(两秒的例子:25 步变 56 步,而不是 800 步)。
工程形态也简单得可爱:主干就是一个普通的 decoder-only LLM(Qwen3 系;发布版 8B),输入端 32 张音频 embedding 表查表求和,输出端 33 个线性头并行投影,完事。论文明说,这份「解码路径简单」正是它被选为主力发布架构的原因——好实现、好 scale、好部署,后文会看到 llama.cpp 甚至把 delay 解码原生搬了进去。
代价藏在错位本身:第 1 帧要凑齐全部 32 层,得等到第 32 步——开口之前有 31 步的固定前摇,流式场景下这就是首音延迟的来源。
三、弹法二:Local Transformer,指挥打拍子、乐手扫和弦
Local Transformer(MOSS-TTS-Local-Transformer 采用,血统来自 Moshi 的 RQ-Transformer)不错位,分两级:
- 主干:还是那个 decoder-only LLM,但一步就是一帧——把整帧 33 个通道的 embedding 求和吞进去,吐出一个「全局 latent」,像指挥在这一拍给出的手势;
- 局部 Transformer(轻量的小模型)接过这个手势,在帧内沿深度方向自回归:先写文本通道,再以它为条件写 RVQ 第 1 层,再写第 2 层……33 步把这一帧的「和弦」竖着扫完。
z_{0,t} = x_t # 起手式:主干的全局 latent
z_{j,t} = Emb_{j−1}(y_{j−1,t+1}) # 之后每步以上一层刚写的 token 为条件
层间依赖在这里是显式的条件链,不必绕道历史。好处有三:主干序列长度就是帧数 T(两秒 25 步);第 1 个主干步之后立刻能把第 1 帧 32 层全部解出,首音不用等错位;更重要的是建模效率——论文披露,内部开发中这个架构的逐层 token 损失一直更低,最终只用 1.7B 参数,音色相似度反超 8B 的 Delay 版。代价是每帧内嵌一个 33 步的小循环,稳态解码更重,结构也更复杂。
两种弹法没有全胜者,是一张 tradeoff 菜单:
| Delay Pattern(MOSS-TTS) | Local Transformer | |
|---|---|---|
| 骨架 | 单主干 + 33 个并行头 | 主干 + 帧内小自回归 |
| 主干序列长 | T + 31 | T(每步内嵌 33 步小循环) |
| 首帧出声 | 等 31 步错位铺满 | 第 1 步即可解出 |
| 强项 | 结构简单、可 scale、长文与控制 | 建模效率、音色保持、首音更快 |
| 发布规格 | 8B | 1.7B(v1.5 升到 4B) |
报告自己的用法就体现了这份分工:克隆基准上的音色纪录由 Local Transformer 刷,时长控制、发音控制、一小时超长生成这些「控制与长跑」项目全部由 Delay 版扛。顺带一提,前篇里 tokenizer 报告自带的 CAT-TTS(Temporal + Depth Transformer)走的就是 Local 这一族;那篇的 Progressive Sequence Dropout 也被搬了过来,让生成侧同样支持码率可控。
四、数据流水线:把野生录音洗成教材
配方的第二味药是数据。要把预训练堆到数百万小时,只能去大自然里采:播客、影视剧、广播新闻、解说、网络内容。但野生录音天生不合格——多人混说、背景音乐、没有转写。论文用一条三阶段流水线把它们洗成「单人、干净、文音对齐」的教材,细节密度很高,值得慢读。
预处理阶段:第一步就上神经降噪(MossFormer2-SE-48K),但有个反直觉的细节——降噪后的音频不进训练集,它只是为了让下游的说话人切分和转写更准,最终训练用的还是原始声音。响度做两步归一(先拉到 −20dBFS、增益钳在 ±3dB,再做峰值归一),然后用 DiariZen 做说话人日志。切出来的碎片段有讲究:0.1 秒以下的丢弃,相邻同说话人的段无条件合并——不管中间隔了多久的静音,因为那是说话时的自然停顿,正是要学的东西;单条上限一小时。
过滤阶段:先转写,后把关。转写用的是自家的多语言 ASR 模型 MOSS-Transcribe-Diarize(本站拆解过),输出自带说话人标签和 [music]、[laugh] 这类事件标记。然后三层筛:
- 规则预筛:空转写、同一短语连续复读超过 6 次(ASR 崩溃的可靠信号)、去掉方括号标签后语言内容不足 20%(说明整段基本是噪音或音乐)——直接丢,不浪费后面的推理预算;
- LLM 诊断与修复:大模型先诊断两类致命伤(整段内容重复、句子被截断),中招即丢;过关的做序列化清理——删事件标签、删空说话人标签、修复
[说话人]正文格式,但不许改动识别出来的词。LLM 调用失败的段落直接丢弃,绝不回退到未清洗的转写; - 三道硬闸:音质上要求 DNSMOS > 2.8 且 AudioBox PQ > 6.5——而且打分用的是降噪前的原始音频,否则测的是降噪器的水平而不是录音的水平;语言上让 Whisper 听音频判一个语种、LLM 读转写判一个语种,两边必须一致;长度上按语种设定「每秒字符数」的合法区间——音频远长于文本说明大段是静音,文本远长于音频则是 ASR 幻觉的可靠指纹。
合成阶段:补上三个野生数据给不了的缺口。最关键的是克隆配对:过滤后的语料只有「文本 + 语音」,没有「参考音频 → 目标语音」的结构,模型学不到照着 prompt 换音色。做法是在同一段录音里找同一说话人的其他片段,每段随机裁 5 个不超过 30 秒的窗口,用说话人向量模型(Seed-TTS-eval 同款的 WavLM-Large)逐个打分,挑最像的当 prompt。两个用意都很实在:按「推理时真实会用的短片段」去选 prompt,而不是拿整段音频作代表;随机窗口则逼模型对 prompt 的长短和位置都鲁棒。另外两个补丁是文本侧的:把「Hello??!! are you there」这类脏输入原样喂给模型(音频不动,练抗噪);把整句或部分文字规则替换成带声调拼音或 IPA 音标(音频不动,练发音控制);再补一批单字、单词的超短样本——网上没人对着麦克风念字典,但真实用户经常只合成一个词。
最后的语料构成:英语 53%、中文 42%、其他 30 来种语言合计 5%(最大的西语也只占 1.43%);域上播客独占 54.5%。还有个安排值得划线:每条训练样本都序列化成两个版本——一版在 prompt 里写明目标音频的 token 数,一版写 None。这对格式贯穿全部预训练,于是「指定时长」从第一天起就是模型的原生能力,而不是后期缝上去的补丁。下一节的成绩单会验证这一点。
五、课程表:先学说话,再学控制,最后练长跑
有了币和教材,第三味药是怎么喂。MOSS-TTS 的预训练分四个阶段,学习率走 WSD(warmup–stable–decay)路线:
| 阶段 | 上下文 | 学习率 | 数据 |
|---|---|---|---|
| P1 基础对齐 | 32k | 预热到 2×10⁻⁴ 后恒定 | 只用主语料(干净的文本→语音) |
| P2 能力扩张 | 32k | 恒定 2×10⁻⁴ | 全部子集,克隆配对大幅上采样 |
| P3 质量收敛 | 32k | 线性衰减到 2×10⁻⁶ | 恢复自然配比 |
| P4 长跑扩展 | 64k | 恒定 2×10⁻⁶ | 长音频大幅上采样 |
课程设计有三条原则,每条都值得抄。其一,从最干净、歧义最少的监督起步:P1 只学「文本怎么变成声音」这件主线任务,先把单调对齐和多语言发音映射焊牢,别一上来就让模型分心。其二,难的能力要趁学习率还高时灌进去:克隆是比普通 TTS 更脆的任务,如果拖到后期低学习率时才引入,只能学成边角补丁;在 2×10⁻⁴ 的平台期上采样克隆数据,它才能长成「原生行为」。其三,长上下文最后扩:P4 把窗口从 32k 拉到 64k——按一步一帧折算约 85 分钟音频——此时学习率已经降到 2×10⁻⁶,模型在几乎不动摇短句质量的前提下适应小时级连贯性。这套「先收敛、再扩窗」的节奏,和 LLM 界的长上下文扩展如出一辙。
六、成绩单:音色、时长、发音、一小时
克隆:Continuation 这个冷知识
评测先教了一个概念。零样本克隆有两种喂参考音频的姿势:
- Clone:老老实实把参考音频作为显式的 reference 输入;
- Continuation:把参考音频连同它的转写一起拼在待合成文本前面,让模型「接着往下说」。
Seed-TTS-eval 上的成绩(摘录自原文 Table 3;WER/CER 为错词/错字率、越低越好,SIM 为说话人相似度、越高越好):
| 系统 | 参数量 | 开源 | 英 WER ↓ | 英 SIM ↑ | 中 CER ↓ | 中 SIM ↑ |
|---|---|---|---|---|---|---|
| Seed-TTS | – | ❌ | 2.25 | 76.2 | 1.12 | 79.6 |
| MiniMax-Speech | – | ❌ | 1.65 | 69.2 | 0.83 | 78.3 |
| CosyVoice3 | 0.5B | ✅ | 2.02 | 71.8 | 1.16 | 78.0 |
| VoxCPM | 0.5B | ✅ | 1.85 | 72.9 | 0.93 | 77.2 |
| Qwen3-TTS | 1.7B | ✅ | 1.50 | 71.45 | 1.33 | 76.72 |
| MOSS-TTS(Delay 8B)Clone | 8B | ✅ | 1.92 | 69.31 | 1.46 | 76.21 |
| MOSS-TTS(Delay 8B)Continuation | 8B | ✅ | 1.84 | 70.86 | 1.37 | 76.98 |
| Local Transformer Clone | 1.7B | ✅ | 1.87 | 71.74 | 1.33 | 77.24 |
| Local Transformer Continuation | 1.7B | ✅ | 1.93 | 73.28 | 1.44 | 79.62 |
读表法沿用论文的提醒:错词率一旦压到 2 附近就进入「ASR 噪声区」——作者人工复核发现,这个区间里剩下的错误大多是评测用 ASR 自己听岔了,不是模型真念错了。真正拉开差距的是音色相似度,而这里有两条干净的规律:Continuation 恒稳压 Clone——原生的「语音续写」比专门的克隆格式更能锚定音色,这是离散自回归范式白送的玩法;Local Transformer 恒稳压 Delay——1.7B 的中英 SIM 双双做到开源最高(79.62 / 73.28),中文一项甚至以 79.62 对 79.60 微超闭源的 Seed-TTS,英文距其 76.2 还有约 3 个点。这正是第三节那张 tradeoff 菜单的实测注脚。
多语言方面,直接拿预训练模型上 CV3-Eval 克隆子集裸测(没有为基准做任何专项训练):德、西、意、俄已经与强基线相当,日、韩、法还有明显差距——低资源语种覆盖也被论文列进下一步最重要的方向。
时长控制:0.7% 的相对误差
机制在第四节埋过了:prompt 里写 tokens=N,模型就把音频长度控制在 N 帧。换算极其好记——1 秒 = 12.5 帧,README 的真实示例就是给同一段英文分别指定 tokens=325 和 tokens=600,得到约 26 秒和 48 秒两个版本。实测相对误差(Delay 8B):
| 目标时长档 | 平均相对误差 |
|---|---|
| 3–10 秒 | ≈ 1.5% |
| 10 秒–1 分钟 | ≈ 0.36% |
| 1–10 分钟 | ≈ 0.36% |
| 10–30 分钟 | ≈ 0.67% |
| 整体 | ≈ 0.7%(中位数 0.28%) |
拿中间档折算:要一段 60 秒的配音,写 tokens=750,平均落点误差只有 0.2 秒上下——广告配音、视频对轨这类「卡秒」需求直接可用。且再强调一次:这全部来自纯预训练,没有任何专门的时长微调阶段——是第四节「两版序列化」的数据设计换来的。
发音控制:把声调攥在自己手里
拼音与 IPA 输入同样是数据合成阶段练出来的。README 里的真实示例排在一起很有意思:
text_3 = "nin2 hao3,qing3 wen4 nin2 lai2 zi4 na3 zuo4 cheng2 shi4?" # 全句拼音,声调正确
text_4 = "nin2 hao3,qing4 wen3 nin2 lai2 zi4 na4 zuo3 cheng4 shi3?" # 对照组:声调故意换掉
text_5 = "您好,请问您来自哪 zuo4 cheng2 shi4?" # 汉字与拼音混排
text_6 = "/həloʊ, meɪ aɪ æsk wɪtʃ sɪti juː ɑːr frʌm?/" # 英文走 IPA 音标
text_4 那组「错误声调」不是手滑——模型会老老实实照错的念,恰恰证明发音的控制权真的交到了拼音手里。多音字、人名、术语这类 ASR 和前端的老大难,从此可以在输入侧一锤定音。内部评测里,被替换片段的中文错字率低到 1.00%(局部替换)和 1.65%(整句拼音),英文 IPA 是 4.32% 和 5.84%——论文的措辞是「已经实用」。
一小时长文:瓶颈不是念错字,是「渐渐不像你」
最后是压轴项目:从短句一路生成到约一小时,会发生什么?内部评测集按文本长度分六档(中文最长档 10000+、英文 50000+),中英 × Clone/Continuation 各测一遍。结论分两半:
内容侧基本扛住了。中文 Continuation 模式下,即使最长档的错字率也只有 1.86%;英文难得多,最长档两种模式都明显劣化(WER 17.49 / 29.52)。
音色侧才是真瓶颈。把逐 3 秒窗口的说话人相似度沿时间画出来,所有曲线都在缓慢下坠——模型不是突然念错,而是渐渐忘了自己在模仿谁。中文 Clone 模式的最长档在尾段明显塌陷,换成 Continuation 曲线立刻收紧拉平——最长档也能贴住其他档超过 30 分钟;英文整体坠得更早更快。论文的总结很清醒:超长生成已经「可运行」,但主导失效模式是沿时间累积的音色漂移,而非词句错误——这也是他们列出的下一步主攻方向。
(tokenizer 本身的重建成绩这里就不重复了,一句话:0–4kbps 全区间压着开源同行走,细节见前篇第四节。)
七、全家福:一套币,六个工位
报告只写了主线模型,但仓库里是一整个家族——同一套 token 上分化出的不同工种:
| 模型 | 架构 | 规格 | 干什么的 |
|---|---|---|---|
| MOSS-TTS(v1.5) | Delay | 8B | 旗舰单人 TTS:克隆、长文、时长/发音控制 |
| MOSS-TTS-Local-Transformer(v1.5) | Local | 1.7B(4B) | 轻量流式,音色最强;v1.5 换 tokenizer v2,原生 48kHz 立体声 |
| MOSS-TTSD v1.0 | Delay | 8B | 多说话人对话/播客;主观评测胜过豆包、Gemini 2.5 Pro 的 TTS |
| MOSS-VoiceGenerator | Delay | 1.7B | 无参考音频,纯文字描述凭空设计音色 |
| MOSS-SoundEffect(v2.0) | Delay(v2 为 DiT + Flow Matching) | 8B(1.3B) | 音效生成,48kHz、最长 30 秒 |
| MOSS-TTS-Realtime | Realtime | 1.7B | 语音 agent 专用:多轮上下文增量合成,首字节 180ms |
| MOSS-TTS-Nano | 自回归 | 0.1B | 4 个 CPU 核实时流式,48kHz 立体声克隆 |
全部 Apache 2.0。v1.5 一代还带来几件顺手的小工具:31 个语种(可显式传语言标签)、长参考短文本克隆、跟随标点的韵律,以及行内停顿标记——我今天学习了一首中国的古诗,它的名字是[pause 3.2s]静夜思!,停 3.2 秒,报幕感直接写进文本。
部署生态则是「结构简单」路线的红利兑现,三条路各有分工:llama.cpp 走 torch-free 路径(Q4_K_M 量化的 GGUF 主干 + ONNX 版 tokenizer,8GB 显存就能跑 8B,官方还维护了把多通道 embedding、多头输出和 delay 解码直接写进 llama.cpp 的 first-class 分支);SGLang-Omni 提供 OpenAI 兼容的 /v1/audio/speech 端点,是目前唯一支持 Local 架构的后端;vLLM-Omni 覆盖 Delay、Realtime、Nano 三种架构。日常调用长这样(节选改写自官方 README):
from transformers import AutoModel, AutoProcessor
repo = "OpenMOSS-Team/MOSS-TTS-v1.5"
processor = AutoProcessor.from_pretrained(repo, trust_remote_code=True)
model = AutoModel.from_pretrained(repo, trust_remote_code=True).to("cuda")
conversations = [
[processor.build_user_message(text="今天天气不错。")], # 直接合成
[processor.build_user_message(text=text, reference=[ref_wav])], # 零样本克隆
[processor.build_user_message(text=text, tokens=325)], # 时长控制:325 帧 = 26 秒
[processor.build_user_message(text="nin2 hao3,qing3 wen4 …")], # 拼音控制
[processor.build_user_message(text=text_fr, language="French")], # 语言标签(v1.5)
]
batch = processor(conversations, mode="generation")
outputs = model.generate(**batch, max_new_tokens=4096)
audio = processor.decode(outputs) # 音频 token → 波形,由 MOSS-Audio-Tokenizer 还原
克隆、时长、发音、语言,全都是往同一个 build_user_message 里加字段——控制信号在 token 域里表达,这正是离散路线「控制显式且可组合」的直观体现。
结语:三个收束
- 这是 tokenizer 报告的下半场,合起来才是完整论证。 前篇证明币能铸好,这篇证明币真能花:token 质量够高时,语音合成退化成语言建模,LLM 的全部基础设施——数据管线、WSD 课程、长上下文扩展、量化推理——原地通用。两份报告合讲一个论点:语音生成的进步来自数据质量、规模与架构简洁,而不是更精巧的级联。
- A/B 的价值大于任何单项冠军。 同 tokenizer 同数据只换 token 编排,Delay 换来简单与长跑,Local 换来效率与音色(1.7B 反超 8B)——这不是一场分胜负的比赛,是给全行业标定的一张 tradeoff 菜单。全家桶两条架构并行发布、评测各扛一摊,就是这张菜单的产品化。
- 控制能力是数据设计「白送」的,短板也标得诚实。 时长控制来自两版序列化、发音控制来自拼音/IPA 替换、抗脏输入来自文本加噪——全在预训练里长成原生行为,没有一个是后期补丁。而超长生成的音色漂移、小语种的差距,论文没有藏,直接写成了下一步的路标。配方朴素,账本透明,这大概是「基础模型式」技术报告该有的样子。
参考
- MOSS-TTS Technical Report(arXiv:2603.18090,本文主角)
- 官方代码仓库(OpenMOSS/MOSS-TTS)(全家桶模型卡、用法示例与部署后端的出处)
- HuggingFace 模型合集(全系权重,Apache 2.0)
- 当造币厂也开始 scaling:深入浅出 MOSS-Audio-Tokenizer(本站前篇:本文所有 token 的铸造工艺)
- 给声音造一张词表:深入浅出语音 tokenizer(RVQ、多码本与语言模型的恩怨,前置知识)
- 把 90 分钟会议塞进一次生成:深入浅出 MOSS Transcribe Diarize(数据流水线里负责转写的那位)
- 一直在听,也一直在说:深入拆解 Moshi(Local Transformer 的 RQ-Transformer 血统来源)
- 让文字开口:深入浅出 Qwen3-TTS(评测表里最强的开源对手)
- Simple and Controllable Music Generation(MusicGen)(arXiv:2306.05284,Delay Pattern 的出处)
- Seed-TTS(arXiv:2406.02430,Seed-TTS-eval 基准的出处)