上一篇 Qwen3-TTS 把「语音 token」当成黑箱,说它是「声音的拼音」——文字先变成一串离散的语音 token,再由声码器还原成波形。那篇讲了主干和训练,却对这串 token 本身一笔带过:它到底怎么造出来的?

这一步的「造币厂」,就是语音 tokenizer(也叫神经音频 codec、语音离散化器)。它是整个 TTS 的地基:tokenizer 一定,上面的语言模型好不好学、能不能边说边出声、还原得像不像,就都定了一大半。这篇把黑箱拆开——从设计上的根本矛盾讲起,一路看 EnCodec、SpeechTokenizer、Mimi、CosyVoice、X-Codec2 到 Qwen3-TTS,看它们各自站在哪、为什么这么选。

也算本站多模态系列里「离散化」这条线的深潜:离散 vs 连续 讲过「声音要先变成离散 token 才能被 LM 生成」,这篇专门拆那台把声音变成 token 的机器。

一、两个主人:语义还是声学

一个语音 tokenizer 要把连续的声波压成一串离散 token,绕不开一个根本矛盾:这串 token 到底该记住什么?

  • 一路是语义 token:只关心「说了什么」。做法通常是拿自监督模型(HuBERT、WavLM 这类)抽特征,再做 k-means 聚类,把每帧归到一个「类别号」。它和音素、内容对得很齐,比特率低、语言模型好学;代价是丢掉了音色、语气、录音环境——你没法只凭它还原出原来那个人的声音。
  • 另一路是声学 token:只关心「听起来怎样」。做法是训一个神经 codec,直接把波形编码、量化、再解码回去。它能高保真重建音色和韵律;代价是和内容没对齐——码里全是「怎么响」,不知道「说了啥」,而且(下文会看到)一帧要吐好几个码本,语言模型不好嚼。
语义 token自监督特征做 k-means / 插进 ASR 编码器✓ 记住「说了什么」:音素、内容✗ 丢掉音色、语气、录音细节强:LM 好学、比特率低弱:还原不出原声例:HuBERT · WavLM · CosyVoice 监督语义声学 token神经 codec,直接压缩波形✓ 留住音色、韵律,能高保真重建✗ 不懂内容,没跟音素对齐强:重建音质高弱:一帧多个码本,LM 难嚼例:SoundStream · EnCodec · DACAudioLM 实测:声学 token 重建好但音素判别差,语义 token 恰好相反→ 现代 tokenizer 想把两者合一(见第三节)
语义 token 记住『说什么』但丢音色,声学 token 留住音色但不懂内容——AudioLM 实测两者强弱恰好相反

这不是随口说的取舍。Google 的 AudioLM 把两种 token 摆在一起测过:声学 token(来自 SoundStream)重建质量好,但「音素判别」很差;语义 token(来自 w2v-BERT)反过来,音素判别极好,却几乎重建不出像样的音频。一个能听、一个能懂,偏偏很难兼得。 后面的故事,基本都是在想办法把这两个主人同时伺候好。

二、两条老路:声学 codec 与语义 SSL

先看这两路各自的代表作。

声学派:神经 codec 的 RVQ 家族。 2021 年 Google 的 SoundStream 立了范式:一个全卷积编码器把波形压成每秒几十帧的向量,再用残差向量量化(RVQ)离散化,最后解码器配 GAN 判别器还原波形。RVQ 是关键——单个码本容量有限,RVQ 就叠一串小码本:第一个量化主体,第二个量化「上一层的残差」,逐层由粗到细。SoundStream 在 24kHz 下每秒 75 帧、可配 8 个码本,覆盖 3–18kbps。

接棒的是 Meta 的 EnCodec(2022,卷积 + LSTM,最多 32 个码本,1.5–24kbps)和 Descript 的 DAC(2023,Snake 激活、码本利用率约 99%,44.1kHz 下约 8kbps)。VALL-E 用的正是 EnCodec:8 个量化器、每个 1024 条目。这些 codec 重建极好,却有个对语言模型不友好的硬伤:一帧要同时吐好几个码本(EnCodec 8 个、DAC 9 个),而单个自回归 LM 一步只能预测一个 token——数量对不上。VALL-E 只好让第一个码本自回归、其余码本另用非自回归模型补;MusicGen 则发明「延迟交错」把多条码本流摊平(这些补丁具体怎么打,第三节末尾细讲)。说到底,多码本是 RVQ codec 和自回归 LM 之间最大的一道坎——两边的结构就对不上:codec 一帧给出好几条并行的码本流,LM 却只会走一条一维序列。上面那些补丁都是绕道,绕不开的东西只有一个:把码本砍少(第五节的主角)。

语义派:自监督特征的 k-means。 另一条路根本不做 codec,而是拿 HuBERT、w2v-BERT、WavLM 这类自监督模型的中间特征,直接 k-means 聚类成离散「语义 token」。HuBERT 每秒 50 帧,聚类数常取 100、500、1000 不等;这些 token 和音素对得很齐,但基本不含音色。

那能不能两个都要?Google 的 AudioLM(2022)就是这么干的:先用 w2v-BERT 的语义 token(25Hz、1024 类)搭起长时结构,保证「说得通顺」;再用 SoundStream 的声学 token(12 层 RVQ)补上音质,保证「听着真」。两套 token、两级建模——能听又能懂,但要维护两条独立的 token 流

三、量化的三种手艺:VQ / RVQ / FSQ

上面反复出现「码本」「量化」,这里花一节讲透。量化是 tokenizer 里唯一真正「离散化」的那一步:编码器每帧吐出一个连续向量,量化负责把它变成一个能进词表的整数编号。原理不难,但有三个绕不过去的坑——VQ、RVQ、FSQ 说白了就是对这三个坑的不同回答。

VQ · 单码本帧向量码本查表1 个 token / 帧简单;容量= 码本大小RVQ · 残差多码本帧向量码本 1(粗)码本 2码本 N(细)残差N 个 token / 帧粗→细逐层逼近,还原好FSQ · 有限标量量化投影到几维,每维四舍五入到固定档位隐式码本 = 各维档位之积不学码本、不塌缩、利用率≈100%单码本(VQ/FSQ)对自回归 LM 最省心——一帧一个 token;RVQ 音质好但要绕开多码本
VQ 一帧一个 token;RVQ 粗到细、一帧 N 个 token;FSQ 不学码本、每维四舍五入到固定档位

VQ:最近邻查表,和它的三个坑

最朴素的做法,像查字典:维护一本码本(K 个可学习的向量),给定编码器输出 z,找离它最近的那个码字,输出这个码字的编号——这就是 token;解码器则拿选中的码字代替 z 往下走。一帧的信息量就是 log₂K 比特(K=1024 → 10 比特)。

麻烦在于,这套东西有三个坑:

  1. argmin 没法求导。 取最近邻这一步导数几乎处处为 0,梯度传不回编码器。解法是直通估计(STE):前向用量化后的值,反向假装量化是恒等函数,把解码器的梯度直接抄给编码器。

    z_q = z + (quantize(z) - z).detach()   # 前向 = quantize(z),反向梯度直通给 z
    
  2. 码本自己怎么学? 要么用一个码本损失把码字拉向编码器的输出,要么用 EMA(滑动平均)更新——SoundStream、EnCodec 走的都是 EMA。同时还要一个承诺损失(commitment loss)反过来把编码器拉向码本,否则编码器到处乱跑、码本永远追不上;EnCodec 里它就是「量化器输入与输出之间的 MSE」。

  3. 码本塌缩。 少数码字被反复选中,其余的从没被选中 → 从没被更新 → 永远是死码:名义上 1024 条,实际可能只活了几十条。补丁一大堆(死码重置、k-means 初始化、码字分裂、熵惩罚)。DAC 的解法比较漂亮:把查表放到低维空间(8 或 32 维)做,再对码字做 L2 归一化(欧氏距离退化成余弦),利用率能拉到约 99%。

记住第三个坑——它就是后面 FSQ 出场的全部理由。

RVQ:容量不够,就叠残差

单码本一帧只有 log₂K 比特:K=1024 就是 10 比特,75 帧/秒也才 750bps,远不够高保真。想要 80 比特/帧?那得 2⁸⁰ 个码字——存不下,也搜不动。容量随比特数指数爆炸,这是单码本的死穴。

RVQ 的解法是级联一串小码本,每层只量化上一层剩下的残差

r₀ = z
for i in 1..N:
    kᵢ = argmin_k ‖r_{i−1} − e⁽ⁱ⁾_k‖   # 第 i 层在自己的码本里找最近的码字
    rᵢ = r_{i−1} − e⁽ⁱ⁾_{kᵢ}           # 减掉,剩下的交给下一层
z_q = Σ e⁽ⁱ⁾_{kᵢ}                      # 重建 = 各层选中码字之和

残差一层比一层小,所以是由粗到细的逐层逼近:第 1 层管大轮廓,后面的层修细节。比特数于是从「指数涨 K」变成「线性叠 N」——N × log₂K。

还有个关键小技巧:量化器 dropout——训练时随机只用前 n 层(n 从 1 到 N 均匀采样)。好处有二:一个模型同时服务多种码率(解码时少用几层就是低码率),而且逼出了层的重要性排序(第 1 层永远在,所以它必须最重要)。SoundStream 首创,EnCodec、DAC 都沿用。

(记住「第 1 层最重要」这个性质——下一节 SpeechTokenizer 把语义蒸馏进的,正是这一层。)

FSQ:干脆不要码本

2023 年 FSQ 的思路很反直觉:坑 2、坑 3 都是「码本要学」惹的祸,那就别学了。它原本是给图像 VQ-VAE 提的通用替代(论文副标题就叫 VQ-VAE Made Simple),整个机制四步说完:

  1. 投影到极低维:把编码器输出线性投影到 D 维,D 通常不到 10——这是和 VQ 最大的直觉反差:VQ 在几百维的空间里找最近邻,FSQ 只留几个维度;
  2. 限幅:每一维过一个 tanh 压进固定区间(论文的写法是 z ↦ ⌊L/2⌋·tanh(z),偶数档位时再加个小平移,细节从略);
  3. 取整:四舍五入——于是第 i 维只能落在 Lᵢ 个整数档位上;
  4. 拼编号:D 个整数按「进位制」拼成一个 id,基是 [1, L₁, L₁L₂, …],像读一个混合进位的数。

拿档位 [8, 5, 5] 举例:某帧投影、限幅、取整后得到 (5, 2, 3),那么 id = 5×1 + 2×8 + 3×40 = 141,词表总大小 8×5×5 = 200。隐式码本就是各维档位的笛卡尔积——一张 8×5×5 的固定网格,token 是网格点的编号。没有表、没有码字、也没有最近邻搜索。

编码器输出 z高维 · 如 512 维(1.3, −0.4, 0.9)投影到 D=3 维连续值(5, 2, 3)整数档位 · L=[8, 5, 5]token id = 141词表 8×5×5 = 200线性投影tanh 限幅+取整进位制id = 5×1 + 2×8 + 3×40 = 141(基 [1, 8, 40]——像读一个混合进位的数)隐式码本=固定网格(2 维截面示意:8 档 × 5 档)各维独立取整每个网格点天然可达——没有一个会「死」码字不再学习:编码器学着把输出摊满网格码本利用率(FSQ 论文实测)VQ · 码本 2¹⁶只用出约 2¹⁰ 个码字(不到 2%);超过 2¹¹ 利用率即跌破 50%FSQ · 网格 2¹⁶≈100% 全用上单码本设计要的正是「又大又用得满」
FSQ 四步流水线:投影到低维 → tanh 限幅 → 取整 → 进位制拼 id。左下:隐式码本是固定网格,每个点天然可达;右下:论文实测,VQ 在 2¹⁶ 码本下只用出约 2¹⁰ 个码字,FSQ ≈100% 全用上

训练上,round 不可导,解法和 VQ 的坑 1 一模一样——同一个 STE:x + sg(round(x) − x),前面那行 Python 换个函数名照用。更妙的是,连承诺损失也省了:tanh 已经把编码器输出捆在固定区间里,它想跑也跑不掉。

坑 3 则从根上消失。VQ 的码字是学出来的——会漂移,没被选中就得不到梯度、沦为死码;FSQ 的「码字」是构造出来的——固定网格点,不动、不需要梯度,自然没有「死」这回事。学习负担整个转给了编码器:码字不用学了,编码器得学会把输出摊满网格。这个差距论文里量过:VQ 的码本一超过 2¹¹,利用率就跌破 50%,再大也用不满 2¹⁰ 个码字;FSQ 到 2¹⁶ 依然≈100%。论文原话:FSQ「不会码本塌缩,也不需要 VQ 那套复杂机械(承诺损失、码本重置、码字分裂、熵惩罚等)」。

想要多大的词表,就加维度、加档位:容量 = 各维档位之积。论文给的启发式是每维至少 5 档,并附了张对照表——2¹⁰ 用 [8,5,5,5],2¹⁶ 用 [8,8,8,5,5,5]。

这也解释了 FSQ 为什么成了语音单码本设计的标配:单码本把全部赌注押在一个码本上,这个码本必须又大、又用得满——恰好 VQ 在这两点上都塌(2¹⁶ 只能用出千把个),FSQ 正好补上。CosyVoice 2/3 的 6561(它论文里的编号公式 μ = Σ h̄ⱼ(2K+1)ʲ 正是那套进位制)、X-Codec2 的 65536、Spark-TTS 的音色 token,都是这么来的。

一条公式,串起全文所有数字

三种手艺讲完,可以收成一条式子:

比特率 = 帧率 × 码本数 × log₂(码本大小)

它几乎能反推出本文提到的每个数字:

帧率码本数log₂K算出来论文值
SoundStream758106,000bps6kbps
Mimi12.5811(K=2048)1,100bps1.1kbps
BigCodec80113(K=8192)1,040bps1.04kbps
MOSS-Tokenizer12.532104,000bps4kbps

于是全篇的取舍,都能落到三个旋钮上:帧率、码本数、码本大小。想要音质,三个都想往大拧;想让 LM 好学,帧率就得低(序列短)、码本数就得少(最好是 1,一帧一个 token)——于是只剩码本大小能加(所以 X-Codec2 敢用 65536),或者干脆把 tokenizer 本身做大(所以 MOSS 用 16 亿参数换质量)。

SoundStream 论文里有个特别直观的例子:同样是 6kbps,你可以选「8 个码本 × 1024」、「16 × 32」、甚至「80 × 2」——比特率一模一样,对 LM 的友好度却天差地别。量化这门手艺的全部张力,就在这一句里。

天差地别在哪?先算 token 总量(= 帧率 × 码本数):8×1024 每秒产 600 个 token,80×2 每秒 6000 个——同一个 4096 token 的上下文窗口,前者装得下 6.8 秒音频,后者只装 0.68 秒。再看单个 token 的含金量:1024 条目的 token 一个值 10 比特,抓得住一帧的粗轮廓;2 条目的一个只值 1 比特,LM 花一整步前向、只为预测一次抛硬币,而且第 1 层码本再也扛不住粗轮廓,「先建好第 1 层」的那类设计(马上会见到)全没了抓手。说到底,码本做大费的只是查表内存,流数做多费的却是步数、延迟和上下文——这 80 比特该折进码本大小,而不是流数。至于每帧欠下的这笔账到底怎么还,下一小节细算。

追问:LM 一步只出一个 id,N 个码本怎么办

读到这里你可能会问:自回归 LM 的一步,天生就是「一个隐状态 → 一个 softmax → 一个 id」,那 RVQ 一帧的 N 个 id 到底怎么生成?

先排除一个想当然的答案:把 N 个 id 打包成一个「联合 token」不行——词表会变成码本大小的 N 次方(1024⁸ 是 10²⁴ 量级),softmax 铺不开。所以只能是 N 个各自的分布,每个在自己的码本词表上。但这 N 个 id 之间又有依赖(第 2 层是第 1 层的残差),也不能天真地并行各采各的。业界给出了四种解法:

① 摊平成一条帧 1 的码本 1..N帧 2 的…帧 3 的…依赖关系完整但序列长 N 倍、慢 N 倍(理论基线,没人真这么干)② 延迟交错 · MusicGen码本 1码本 2 晚一拍码本 3 晚两拍深色=同一帧预测码本 2 时,同帧码本 1 已在上文步数不变,轻微近似③ 先自回归,再并行填 · VALL-E第 1 层:主 LM 逐个吐第 2..N 层:NAR 一次性填先写完大纲,再统一上色第二段不再是流式④ 主干+深度小模型 · MTP / Moshi主干:只出第 0 层小模块同步内补出残差层主干仍是一步一 id,深度轴交给小模型保住流式(Qwen 12Hz 首包 97ms 靠它)码本数 = 每帧欠几笔账:①用时间还,②错位摊,③④转给另一个模型——单码本则让账根本不产生
一步一个 id 的 LM 应付一帧 N 个码本的四种办法:摊平(慢 N 倍)、延迟交错(MusicGen)、先自回归再并行填(VALL-E)、主干+深度小模型(Qwen 的 MTP、Moshi 的 Depth Transformer)
  1. 摊平:把「帧 1 码本 1、帧 1 码本 2……帧 2 码本 1……」排成一条序列,LM 老老实实一步一个。依赖关系完整,但序列长 N 倍、慢 N 倍——75Hz × 8 码本 = 每秒 600 步,基本没人真这么干,只当理论基线。
  2. 延迟交错(MusicGen):一步用 N 个头并行出 N 个分布,但把各条码本流错开一拍——第 k 层码本晚 k 步。这样预测某帧的码本 2 时,同帧的码本 1 已经在上一步生成、进了上下文,用一个小小的时间差近似补回帧内依赖。步数不变,代价是轻微近似。
  3. 先自回归,再并行填(VALL-E):主 LM 只自回归生成第 1 层(粗轮廓——量化器 dropout 逼出的「第 1 层最重要」在这儿兑现),其余 7 层交给一个非自回归模型,拿着完整的第 1 层序列一次性填出来。像先写完大纲再统一上色;代价是第二段不再流式。
  4. 主干+深度小模型(Qwen3-TTS 的 MTP、Moshi 的 Depth Transformer):主干每步只预测第 0 层,旁边挂一个小模块,在同一步内沿「深度」方向把其余残差层补出来——Qwen3-TTS 叫它 MTP(多 token 预测),Moshi 则是一个小号 Depth Transformer 配大号 Temporal Transformer,还叠了一手「声学延迟」(声学 token 比语义 token 晚 1–2 步,生成更稳)。主干仍是标准的一步一 id,多码本的负担卸给了小模型,流式也保住了——12Hz 那条线 97ms 首包就是这么来的。

收个账:码本数 = 每帧欠几笔账。①用时间还账,②用错位摊账,③④把账转给另一个模型——而单码本设计干脆让每帧只欠一笔,账本身消失了。「单量化器天然契合 LLM 自回归」那句话,说的就是这个。

三家同台:谁赢在哪,近两年谁在用

拆完机制、算完账,最后把三家摆上同一张桌:

VQRVQFSQ
码本哪来的学出来的学出来的,N 层构造出来的,固定网格
一帧产出1 个 tokenN 个 token1 个 token
容量想变大只能加 K,指数死穴叠层,线性涨乘档位,随意拼
塌缩大码本必塌每层码本小,缓解没有「死码」这回事
训练附件STE、承诺损失、EMA、死码重置……同左,另加量化器 dropout只剩 STE
音质天花板低(一帧 log₂K 比特封顶)最高(层数管够)中(靠大词表和强解码器补)
对自回归 LM友好,单流有隔阂,N 流要摊友好,单流

表格之外,三家还各守一项别家拿不走的优势:

VQ 赢在「贴身」。 码字是学出来的,训练自然把它们搬去数据扎堆的地方——和 k-means 同一个道理:哪里样本密,哪里码字就密。同样大小的词表,理论上它失真最低;FSQ 的网格是均匀铺死的,不管数据长什么样。所以只要词表不太大、塌缩压得住,VQ 依然是默认选项——尤其在语义 token 这个岗位上:语义离散化本质是分类,码字就是类中心,边界本来就该学。

RVQ 赢在「天花板」。 容量线性叠层,音质要顶格,只有它顶得上去;「由粗到细」还白送两件礼物:第 1 层天然最重要——语义蒸馏(下一节)和「主干只管第 0 层」的生成设计(上一小节的③④)全挂在这一点上;量化器 dropout 又让一个模型同时服务几档码率。要高保真、要流式、还要给 LM 留抓手,三样都点头的只有 RVQ。

FSQ 赢在「省心,且用得满」。 没有码本就没有塌缩,附件全免;更要紧的是大词表敢真开大、也真用得满。单码本设计把全部赌注押在一个码本上,这个码本必须又大又满——接得住这一注的只有 FSQ。最干净的对照来自 CosyVoice 自家换代:一代 4096 的 VQ 码本,二代论文披露实际只用活 963 条(利用率 23%);二代换成 FSQ 6561,一条不剩全用满。同一家、同一个岗位、前后两代,高下立判。

再看近两年(2024 下半年起)的阵营点名——三家都活得很好,只是站的岗位越分越开:

  • VQ 家:守住语义,也有人带补丁硬上。 监督语义这条线的常客——智谱 GLM-4-Voice(2024)把单个 VQ 插进 Whisper 编码器、拿 ASR 数据有监督训练,12.5Hz、词表 16384(代回前面那条公式:12.5 × 14 比特 = 175bps),2025 年的 Kimi-Audio 直接沿用;Spark-TTS(2025)的语义流也是单 VQ(8192、50Hz)——有意思的是它语义走 VQ、音色走 FSQ,一个系统同时雇两家。也有人靠 DAC 式补丁把码本硬做大:MagiCodec(2025)单 VQ 开到 131072(2¹⁷);Meta 则在 2026 年把「单 VQ + 扩散解码」的 tokenizer 规模化到 16 亿参数——VQ 65536、12.5Hz、只要 200bps。塌缩没杀死 VQ,只是逼它带着补丁上场。
  • RVQ 家:高保真与流式对话的主场。 Mimi 快成了半个生态:除了 Moshi,Sesame 的 CSM、Kyutai 的同传模型 Hibiki 都在用(CSM 的生成端正是上一小节的④:主干管第 0 层,深度小模型补其余);SNAC(2024)给 RVQ 加上多尺度——三层各自只有 12/23/47Hz——成了 Orpheus-TTS 的前端;再加一排 12.5–25Hz 的统一 codec:Baichuan-Audio、MOSS 系的 XY-Tokenizer(12.5Hz、8 层,后来才换成自家 32 层的 MOSS-Audio-Tokenizer)、小米 MiMo-Audio 的 1.2B Transformer tokenizer(25Hz、8 层,和 MOSS 同一路「把 codec 做大」的打法)。
  • FSQ 家:单码本的新船票,票面几乎都印它。 X-Codec2/Llasa(2025)之后衍生出 NeuCodec(2025,还专门论证 FSQ 的码对传输误码天然鲁棒);CosyVoice 2/3(2024/2025)把 FSQ 的底座从 SenseVoice 换到 MinMo,词表一直是 6561;Stability 的 Stable Codec(2024)用纯 Transformer codec 配 6 维 FSQ 做到 400bps;NVIDIA 连押两代——LFSC(2024,21.5Hz)到 NanoCodec(2025,12.5Hz、最低 0.6kbps)。连近亲都上了船:TaDiCodec(2025)用 BSQ(二值球面量化,同样不学码本)做到单码本、6.25Hz、0.0875kbps——每秒仅 6.25 个 token。

地盘就此划清:音质天花板归 RVQ,单码本的新船票归 FSQ,VQ 守着语义 token 和小词表的自留地。 谁也没淘汰谁,因为岗位本来就不同。

一句话记住这节:单码本(VQ 或 FSQ)一帧只吐一个 token,对自回归 LM 最省心;RVQ 音质好,但要额外想办法摊平多码本。 这条「LM 友好度」的线,会贯穿后面所有的新设计。

四、关键一招:把语义塞进第 0 个码本

AudioLM 那种「两套 token」终归啰嗦。2023 年的 SpeechTokenizer 想了个漂亮主意:还是一个 RVQ codec,但训练时逼第一个码本去对齐语义——让 RVQ 第一层的输出去「蒸馏」HuBERT 的语义特征(最大化两者的余弦相似度)。于是第一层码本管「说什么」,剩下的层管「怎么响」。一个 codec,第 0 层是拼音,后面几层是录音。(编号习惯各家不同:SpeechTokenizer 叫它 RVQ-1,Qwen 叫「第 0 层码本」——说的都是同一个,最先、也最「懂内容」的那一层。)

〜〜〜波形编码器码本 0 | 语义码本 1 | 声学码本 2 | 声学码本 N | 声学第 0 层蒸馏对齐 WavLM / HuBERT | 其余层 RVQ 残差补声学LM 先啃第 0 层 → 先懂「说什么」音色细节交给后面的残差层SpeechTokenizer:RVQ-1 蒸馏 HuBERT | Mimi:1 语义+7 声学·流式 | Qwen 12Hz:1 语义+15 声学把语义塞进第 0 个码本:一个 codec 同时当「拼音」和「录音」
把语义塞进第 0 个码本:第一层蒸馏对齐 WavLM/HuBERT 管语义,其余 RVQ 残差层补声学——LM 先啃第 0 层就先懂了内容

这一招后来成了主流。Kyutai 的 Mimi(用在对话模型 Moshi 里,2024)就是它的现代版:12.5Hz、一共 8 个码本 = 1 个语义(蒸馏自 WavLM)+ 7 个声学 RVQ,全因果、可流式,码率才 1.1kbps。语义放第 0 层的好处很直接:语言模型先把第 0 层的语义序列建好,就先抓住了「内容」这条主线,音色细节交给后面的残差层去补。

(眼熟吗?上一篇 Qwen3-TTS 的 12Hz tokenizer——1 个语义 + 15 个声学——正是这门手艺。第六节我们再回到它。)

五、新潮流:更低的帧率、更少的码本

把这条线拉直,最近两年的语音 tokenizer 明显朝两个方向走,动机都是让自回归 LM 更好生成:帧率越低、码本越少,token 序列就越短、越像「写字」,LM 逐个往外蹦时就越省力。

方向一:把码本砍到 1 个。 既然多码本是摩擦,干脆只留一个。WavTokenizer(2024)用单个 VQ、每秒才 40–75 个 token(码本 4096),却宣称在 0.9kbps 上就超过了 DAC 在 9kbps 的音质。X-Codec2(2025,被 Llasa 用作 TTS 前端)走得更彻底:用 FSQ 单码本(大小 65536),把语义和声学特征拼在一起、一次量化成一个 token——Llasa 论文的原话是,单量化器「天然契合大模型从左到右的自回归机制」。BigCodec 也是单码本(VQ 8192、80Hz)。单码本 = 一帧一个 token = 一条能像文字一样建模的流。

方向二:帧率压到 12.5Hz,但把 tokenizer 做大。 另一些工作保留多码本、主攻低帧率。除了 Mimi,2026 年的 MOSS-Audio-Tokenizer 很有代表性:一个 16 亿参数、纯 Transformer(不用卷积)的 codec,在 300 万小时音频上从头训,12.5Hz、32 层 RVQ、码率可变(0.125–4kbps),流式,还统一了语音 / 音效 / 音乐。它不走单码本,而是用「低帧率 + 大模型」换质量。

顺带提一路「监督语义」的分支:阿里 CosyVoice 把量化器直接插进一个 ASR 编码器(而不是自监督特征),于是 token 天生就对齐内容(所以叫「监督语义」,区别于 HuBERT 那种自监督)。CosyVoice 1 是单码本 VQ(4096);CosyVoice 2 换成 FSQ、25Hz、码本 6561 且利用率 100%。这一路的特点是:语义对齐好、单码本、天生适合喂给 LM。

六、案例:Qwen3-TTS 的两把刀

有了这张全景,再看上一篇 Qwen3-TTS 的选择就清楚了:它没做一个「全能」tokenizer,而是给两个场景各配一把刀,正好落在地图的两个位置。

  • Qwen-TTS-Tokenizer-25Hz:单码本(大小 32768)、25Hz,站在 Qwen2-Audio 上两阶段训练(先在 ASR 任务上续训、插入 VQ 层,再接 mel 解码器重建);波形还原用「分块 DiT + flow matching」这套扩散解码,首包约 138–150ms。它偏「单码本语义 + 扩散还原」,主攻长文本自然度。
  • Qwen-TTS-Tokenizer-12Hz:16 层多码本 = 1 个语义(蒸馏自 WavLM)+ 15 个声学 RVQ、12.5Hz,用 GAN 训练,全因果、配一个轻量因果 ConvNet 解码器,首包 97ms。它就是第四节那门「语义塞进第 0 层」的手艺,主攻实时。

放回地图上:25Hz 那把刀站在「单码本、中等帧率、扩散解码」,12Hz 那把刀站在「低帧率、统一 RVQ、流式」——一个像 CosyVoice 的单码本语义路子,一个像 Mimi 的统一码本路子。两把刀,恰好各借了一条潮流。

追问:FSQ 这么好,怎么两把刀都没用它

第三节把 FSQ 夸得不轻——零塌缩、零附件、大词表全用满,单码本的新船票几乎都印它的名。可回头看这两把刀:25Hz 是单码本的可学习 VQ(32768),12Hz 是 RVQ——FSQ 一票没投。为什么?

先说明:技术报告从头到尾没提 FSQ 一个字,也没解释量化器选型,下面是从设计约束反推的答案。但推起来很顺,正好把第三节那张桌子的道理当场用一遍。

12Hz 这把,根本不在 FSQ 的主场。 老规矩先代公式:16 个码本、每层 2048(11 比特),一帧 176 比特、合 2.2kbps——要用 GAN 直接重建波形、还要轻量因果解码器流式跑,每帧的信息量必须堆到这个量级。FSQ 单码本一帧撑死十几比特(开到 65536 也才 16 比特,12.5Hz 下只有 200bps),差着一个数量级:不是量化器不行,是「单码本」这个形态在这个岗位上撑不住。那在 RVQ 的每一层里把 VQ 换成 FSQ 呢?也不划算——每层才 2048 = 2¹¹,正在 VQ 的舒适区里;FSQ 论文自己的曲线是小码本端 VQ 略优,FSQ 的优势要过了这个门槛才兑现。何况整套设计吃死了「第 1 层最重要」:WavLM 蒸馏挂在第 0 层、MTP 主干只管第 0 层,这个粗到细的排序是 RVQ 残差结构白送的——FSQ 各维平权,给不了。

25Hz 这把,确实站在 FSQ 的主场,但 VQ 手里有张 FSQ 没有的牌。 单码本 32768,和 CosyVoice 2/3、X-Codec2 站在同一格——那几位都选了 FSQ,Qwen 偏偏选 VQ。合理的解释有三层。其一,这个量化器是插进预训练好的 Qwen2-Audio 里做监督语义 token 的:学习式码本可以自己搬到预训练特征扎堆的地方(第三节说的「贴身」),FSQ 却要先把特征投到不足 10 维、tanh 压扁、再逼编码器把输出摊满均匀网格——对一个想尽量保留的预训练底座,这刀动得更狠。其二,语义 token 本质是分类,码字就是类中心,边界本来就该学出来(Spark-TTS 是旁证:同一个系统,语义流用 VQ、音色 token 用 FSQ)。其三,FSQ 的头号卖点「大词表不塌」,如今 VQ 靠补丁也拿得到:低维查表、L2 归一化、死码重置伺候好之后,2¹⁴ 以上的大 VQ 近两年一串成功案例(GLM-4-Voice 的 16384、MagiCodec 的 131072)。别忘了 FSQ 论文给自己的定位是「匹配 VQ、但更简单」——不是超过。病能治好,药就不是必吃的;吃了还得付「网格不贴身」的药费。

反面也得诚实:CosyVoice 2 在同一格里选 FSQ 同样成功,还顺手治好了一代 23% 利用率的病。所以这不是对错题,是取舍题——同在阿里,一个团队选了省心的网格,一个团队赌自己的 VQ 训得住(报告没公布利用率,这个「训得住」严格说也是推断)。第三节末尾那句「谁也没淘汰谁,因为岗位本来就不同」,在这两把刀上当场兑了现。

七、一张地图,和写在最后

把这一路的名字摆到同一张图上——横轴帧率、纵轴每帧码本数——脉络就出来了:

单码本一行 · 一帧一个 token码本多单码本帧率高帧率低帧率(token/秒)——越往右越低,序列越短低帧率却仍多码本把 tokenizer / 模型做大的一路↘ 右下角最贴合 AR LMEnCodec · DAC声学 · 8–32 码本SpeechTokenizerMimi1 语义+7 声学Qwen 12HzMOSS-TokenizerBigCodecWavTokenizer · X-Codec2CosyVoice 2Qwen 25Hz
语音 tokenizer 地图:横轴帧率(越右越低)、纵轴每帧码本数(越上越多)。趋势朝右下走——更低帧率、更少码本,越贴合自回归 LM

再用一张表收束(数字均来自各自的论文 / 官方仓库):

tokenizer年份帧率量化语义/声学谁在用
SoundStream202175HzRVQ(8)声学AudioLM
EnCodec202275HzRVQ(≤32)声学VALL-E、MusicGen
DAC2023~86HzRVQ(9)声学通用 codec
w2v-BERT 语义202125Hz(AudioLM 用法)k-means语义AudioLM
SpeechTokenizer2023~50HzRVQ(8,第 1 层蒸馏语义)统一开源研究 codec
Mimi202412.5Hz1 语义 + 7 声学统一·流式Moshi
WavTokenizer202440–75/s单 VQ(4096)统一通用 codec
BigCodec202480Hz单 VQ(8192)声学通用 codec
X-Codec2202550/s单 FSQ(65536)统一Llasa
CosyVoice 2202425Hz单 FSQ(6561)监督语义CosyVoice
MOSS-Tokenizer202612.5HzRVQ(32)统一·流式MOSS 音频
Qwen 25Hz202625Hz单码本(32768)语义为主Qwen3-TTS
Qwen 12Hz202612.5Hz1 语义 + 15 声学统一·流式Qwen3-TTS

三个值得记住的收束:

  1. tokenizer 是 TTS 的地基。 它定了上面的语言模型好不好学、能不能边说边出声、还原得像不像——选错了地基,主干再大也补不回来。
  2. 主线是「统一」和「更省」。 一是把语义和声学揉进一套 token(语义放第 0 层),让一个 codec 既能懂又能听;二是把帧率压低、码本砍少(甚至到 1 个),让自回归 LM 生成得更顺。
  3. 没有免费午餐,所以有人干脆配两把刀。 单码本省心但音质天花板低,多码本音质好却难喂 LM,低帧率快却要更大的模型——每一处都是取舍。Qwen3-TTS 的两个 tokenizer,就是把这份取舍摆到明面上的答卷。

这也和本系列一以贯之的那句话呼应:离散 vs 连续 说「理解用连续、生成用离散」,Qwen3-TTS 说「一个全能表示满足不了所有目标,就给不同场景各配一个」。语音 tokenizer 这台造币厂,正是这句话最细的注脚。

参考

「三家同台」一节点名的近期工作:

  • GLM-4-Voice(arXiv:2412.02612,Whisper 编码器 + 单 VQ 的监督语义 tokenizer,12.5Hz、词表 16384;Kimi-Audio 沿用)
  • Spark-TTS(arXiv:2503.01710,语义流单 VQ 8192 + 音色 token FSQ 4096)
  • MagiCodec(arXiv:2506.00385,单 VQ 码本开到 131072)
  • Scaling Speech Tokenizers with Diffusion Autoencoders(arXiv:2602.06602,Meta,单 VQ 65536 + 扩散解码,12.5Hz、200bps,tokenizer 做到 16 亿参数)
  • SNAC(arXiv:2410.14411,多尺度 RVQ,Orpheus-TTS 的前端)
  • MiMo-Audio(arXiv:2512.23808,1.2B Transformer tokenizer,25Hz、8 层 RVQ)
  • CosyVoice 3(arXiv:2505.17589,FSQ 底座从 SenseVoice 换到 MinMo)
  • Stable Codec(TAAE)(arXiv:2411.19842,Transformer codec + 6 维 FSQ,400bps)
  • NanoCodec(arXiv:2508.05835,NVIDIA,FSQ、12.5Hz;前作 LFSC 见 arXiv:2409.12117)
  • NeuCodec(arXiv:2509.09550,论证 FSQ 码对传输误码天然鲁棒)
  • TaDiCodec(arXiv:2508.16790,BSQ 单码本、6.25Hz、0.0875kbps)