语音合成 | 智谱 AI:GLM-TTS 语音合成模型的设计解析
白御青 Lv5

一、研究背景与问题提出

1. TTS 发展现状

TTS 技术已从早期的神经声学模型(如 Tacotron、TransformerTTS)发展为基于 Transformer 的大语言模型(LLM)驱动范式,当前主流技术路线可分为三类:

  • AR:基于神经编解码器(SoundStream、Encodec)的自回归零样本 TTS(如 VALL-E、Spark-TTS)
  • NAR:基于流匹配或扩散模型的非自回归范式(如 E2-TTS、F5-TTS、F5R-TTS)
  • 混合 AR-NAR 架构(如 CosyVoice、FireRedTTS、SeedTTS、Minimax-Speech、IndexTTS2)

2. 现有模型核心痛点

现有 TTS 系统在工业级部署中仍面临五大关键挑战:

  • 【数据】高质量语音克隆需大规模训练数据和长参考录音,低资源场景适用性受限
  • 【情感】情感表达能力不足,要么难以捕捉文本关联的细腻情感,要么依赖复杂的显式情感标签,影响泛化能力
  • 【发音】多音字、生僻字和方言的发音精度欠佳(尤其汉语这类发音变化很丰富的语言)
  • 【RL】强化学习(RL)在 TTS 中的应用不足,存在奖励设计复杂和训练稳定性差的问题
  • 【个性化】个性化的语音适配,依赖高成本的全模型微调,难以规模化部署

二、GLM-TTS 系统设计

GLM-TTS 沿用 CosyVoice 这类 文本到 token 自回归模型 + token 到波形扩散模型 的两阶段架构,仅用 10 万小时训练数据(远少于同类模型的百万级数据量)实现 SOTA 性能,主要工作包括以下六个方面:

1. 文本 Tokenizer 设计

  • 中文去掉了两个字符以上的 token
  • 目的:缩减词汇表中长文本令牌的数量,降低模型学习文本与语音对应关系的复杂度,保障语音合成的稳定性与准确性

2. 优化的 Speech Tokenizer

以 GLM-4-Voice 的 Whisper-VQ Tokenizer 为基础,进行了增强和优化,包括:

  • 帧率从 12.5Hz 提高至 25Hz,词汇量从 16k 扩展至 32k,有效减少发音瑕疵问题,提升了笑声、呼吸声等副语言特征的自然度
  • Tokenizer 内新增基频估计(Pitch Estimator, PE)模块,优化 pitch 建模的准确度,提升克隆语音与参考音频的韵律对齐度
  • 模型采用非因果的架构,移除 chunk 注意力结构和因果卷积,从而提升 ASR 和 PE 模块的精度
  • 扩展训练数据的规模和丰富度,大规模方言数据集和高质量的歌声数据,增强对不同场景的适应性

3. 多奖励 GRPO 强化学习

将 GRPO(Group Relative Policy Optimization)范式应用于 TTS,解决传统 RL 的 reward hacking 和训练不稳定问题。这些强化学习的策略,在预训练和 SFT 都证明是有效的,能够提高发音准确度、音色相似度和整体自然度:

  • 【奖励函数】融合四大核心奖励函数:CER(发音准确率)、SIM(音色相似度)、Emotion(情感自然度)、Laughter(笑声副语言真实度)
  • 【多奖励融合】适配不同奖励分布(数值大小)不同的问题,采用 单个奖励归一化→各奖励之间加权融合→整体分组归一化 的层次化处理策略
  • 【动态采样机制】当 batch 奖励同质化(homogeneous)时,自动重采样(但最多 3 次),平衡训练稳定性与效率
    • 问题一:如何判断 batch 内的奖励是同质化的呢?
    • 问题二:自动重采样次数不应太多,否则会导致负面优化 negative optimization,这里如何理解?
  • 【自适应梯度裁剪】clip 动态调整 ε_high 和 ε_low,设置为与 training_steps 关联的动态变化的数值:
    • 早期收紧,clip 阈值偏小,加强约束防止奖励欺骗 reward hacking
    • 后期放松,clip 阈值放大,支持模型进行更多的 exploration 探索

GLM-TTS 的 GRPO 设计

本文在 GRPO 上的改进,实际就是 DAPO 的两点改进策略:Clip-Higher 和 Dynamic Sampling

  1. Clip-Higher

    • 问题:使用 GRPO 算法进行大规模 LLM 强化学习训练时,出现熵崩溃现象
      • 随着训练步数增加,策略熵(反映模型输出多样性的指标)快速下降,导致部分样本的生成响应几乎完全一致
      • 本质问题是:模型过早陷入 “确定性策略”,丧失了探索新 token 组合的能力,会阻碍模型性能的进一步提升
    • 问题的原因分析:
      • GRPO/PPO 这类针对重要性采样系数,Clip 会限制策略更新的 “信任区域”,避免因为更新幅度过大导致训练不稳定
      • clip 的传统做法是设置固定的对称裁剪范围
      • 上裁剪阈值(1+ε_high)会严重限制低概率 token 的概率提升,导致模型无法探索新 token 组合,引发输出的同质化和熵崩溃
    • 解决方案:
      • 将裁剪范围的下限(εlow)和上限(εhigh)分别看待—— 通过调整两个阈值的取值,分别平衡 “训练稳定性” 和 “探索能力”:
        • 提升上阈值 ε_high:给低概率 token 的概率增长 “松绑”,让模型有机会提升探索性 token 的权重;
        • 保持下阈值 ε_low 较小:避免高概率 token 的概率被过度压制(若ε_low 过大,高概率 token 可能直接被裁剪,导致采样空间崩溃)
    • 最终结论:ε_high 的值比 ε_low 设置更高一些
  2. Dynamic Sampling
    DAPO 中的 dynamic sampling:
    随着 GRPO 训练进程推进,越来越多 prompt 的生成样本,呈现 “全对” 状态(即所有采样响应均与标准答案等价)。这种现象会直接引发两大关键问题,严重制约训练效果:

    • 有效样本持续缩减:由于 “全对” 样本的组内奖励无差异(均为 1),经组内奖励归一化计算后优势值为 0,无法提供有效梯度信号,导致每个训练批次中真正能参与模型更新的样本数量不断下降
    • 训练稳定性显著恶化:有效样本不足会造成批次梯度的波动幅度加剧(梯度方差增大),不仅让训练过程更易震荡,还会直接延缓模型收敛速度,降低整体训练效率。

    “动态采样” 策略的核心思路:

    • 通过精准筛选样本,确保每一批次的训练数据都能提供有效梯度信号,从而优化训练效率与稳定性
    • 其核心逻辑为:在训练批次构建阶段,对初始采样的 prompt(按组级别)进行严格筛选 —— 直接过滤掉 “全对(准确率 = 1)” 和 “全错(准确率 = 0)” 的无效样本,仅保留 “部分对、部分错(0 < 准确率 < 1)” 的有效样本(一个 prompt 对应一组样本)
    • 通过持续采样 - 筛选的循环,直至批次被有效样本完全填满,确保模型每一次参数更新都能获得有价值的梯度引导
  3. 延伸问题:如何判断 batch 内的奖励是同质化的呢?

4. 基于 LoRA 的高效微调

优化 LoRA 微调范式,实现低资源高效语音定制:

  • 仅微调 15% 核心骨干参数(约 100 个 epoch),即可达到全模型微调的语音相似度和自然度
  • 数据需求降至 1 小时高质量单说话人音频,训练成本较全微调降低了 80%
  • 避免大规模数据测试和复杂数据匹配,提升小批量、高需求场景下的定制稳定性

5. 发音精准控制(Phoneme-in 机制)

这部分和 IndexTTS / CosyVoice2&3 采用类似的策略:针对汉语多音字、生僻字难题,设计 混合音素 + 文本 输入方案:

  • 混合模态训练:
    • 标准字符(非多音字和生僻字)以 0.2 概率触发音素转换,发生音素转换时,比例按照 0-0.5 随机采样
    • 复杂字符(多音字和生僻字)来保留文本的形式
  • 推理阶段:先通过 G2P 模块生成完整音素序列,自动替换根据字符对应的音素,兼顾到发音的精度与韵律自然度
  • 词典配置:构建多音字和生僻字专用词典,支持基于业务需求的动态扩展,来决定哪些字需要改成音素进行推理

Phoneme-in 存在的问题

这类音素替换的方案,其实仍然存在两类问题:

  • 发音层面:训练阶段只针对标准字符(非多音字和生僻字)进行音素替换,但实际上不少音素可能是只在多音字/生僻字上会遇到
  • 语义/韵律层面:上述替换方案的训练和推理是不匹配的
    • 训练阶段替换的都是非多音字和生僻字,但是推理阶段替换的是多音字和生僻字,两者不匹配,应该会导致韵律上的次优/变差
    • 团队目前使用的 pho-enh-mask 方案,也只解决了「语义/韵律」层面的问题,发音层面如果不完善替换策略,也会有相同的问题。

6. 增强的声码器(Vocos2D Vocoder)

重构传统的 Vocos 声码器,提升频率子带建模能力。Vocos2D 与原始 Vocos 详细对比表如下:

对比维度 原始 Vocos 具体表现 Vocos2D 具体表现
频率处理架构 采用 1D 卷积,处理整个频率帧 采用 2D 卷积,引入逐频率嵌入,聚焦频率子带建模
模型结构设计 纯 1D 卷积,没有直接关联原始输入的 shortcut 连接 基于 ConvNeXt 改造,新增输入 Mel 频谱的 shortcut 连接,输入增加了频域 embedding
损失函数构成 频谱 L1 损失 + MPD 的 Hinge 损失 + MRD 的 Hinge 损失 频谱 L1 损失 + MRD 的 Hinge 损失,移除了 MPD
☆ 新增判别器增强(DA,discriminator augmentation),相当于对判断器进行数据增强,比如音量/相位等调整,提高判别器的泛化性,注意 DA 的梯度只会影响判断器,不影响生成器
• 包含随机响度调整(±6dB)、随机样本偏移、随机相位旋转三种可微分变换
训练数据范围 以普通语音数据为主 融合了高质量开源唱歌语音数据
支持输出采样率 适配 16kHz 等窄频 支持 32kHz 高质量宽带
关键性能指标(客观) NISQA=3.16,UTMOS=1.87,Ab. Aes.-PQ=7.56 NISQA=3.40,UTMOS=1.91,Ab. Aes.-PQ=7.64
关键性能指标(主观) MOS=3.58 MOS=4.16

三、数据处理流水线

构建工业化级数据处理流程,保障训练数据质量,步骤如下:

  1. 标准化与粗粒度分割:统一为 WAV 格式,VAD 技术提取有效语音片段并拼接为 10 分钟长音频
  2. 源分离与去噪:采用 MelBand Roformer 分离背景音,再用自研的去噪模型抑制残余噪声 → 相当于走了两个模型
  3. 说话人分割与拼接:基于 pyannote.audio 实现多说话人分离,幅度归一化后拼接至 40 秒
  4. 严格质量过滤:WER 阈值控制在 5% 以内(中文用 Paraformer/SenseVoice,英文用 Whisper/Reverb)
  5. 标点优化:基于文本 - 语音的强制对齐结果,根据预设的阈值调整标点位置,具体操作:

步骤1:计算 “发音阈值”(Pronunciation Threshold)—— 确定 “停顿是否需要标点” 的标准

  • 计算逻辑:基于第一步获取的 “所有字符发音时长”,先统计两个关键值:
    • 均值(Mean):所有字符发音时长的平均值(反映 “正常字符发音的平均长度”);
    • 方差(Variance):所有字符发音时长的离散程度(反映 “不同字符发音时长的差异大小”);
  • 最终阈值 = 均值 + 2.6× 方差;
  • 通俗理解:阈值是 “正常字符发音时长的合理上限”—— 若两个相邻字符之间的间隔时长超过这个阈值,说明这段间隔是 “刻意的停顿”(而非正常发音的自然间隔),需要用标点标记;若未超过,则属于 “自然发音间隔”,无需标点。
  • 示例:假设某段文本中字符发音时长的均值为 0.15 秒,方差为 0.02 秒,则阈值 = 0.15 + 2.6×0.02 = 0.15 + 0.052 = 0.202 秒 —— 若 “苹果” 和 “也” 之间的间隔为 0.3 秒(超过 0.202 秒),则需要加逗号;若 “面包” 和 “喝了” 之间的间隔为 0.18 秒(未超过),则不加标点。

步骤2:按 “字符间隔时长” 优化标点 —— 修正文本标点,匹配语音停顿

  • 核心规则:遍历转录文本中所有 “相邻字符对”,计算它们在音频中的实际间隔时长(即前一个字符发音结束到后一个字符发音开始的时间差),再与第二步的阈值对比:
    • 若间隔时长 ≥ 阈值:说明存在 “需要标记的停顿”—— 若原文本已有标点(如逗号、句号),则保留标点;若原文本无标点,则添加对应标点(根据停顿长度选择逗号 / 句号,长停顿用句号,短停顿用逗号);
    • 若间隔时长 < 阈值:说明属于 “自然发音间隔”—— 若原文本有多余标点(如不必要的逗号),则删除标点;若原文本无标点,则保持无标点;
  • 最终效果:让文本的标点完全匹配语音的停顿节奏,解决 “文本标点与语音停顿脱节” 的问题,为 TTS 模型提供 “文本 - 语音节奏一致的高质量训练数据”。

四、实验结果与性能验证

注意:训练数据只用了 10 万小时,LLM 模型参数量为 1.5B。

1. Speech Tokenizer 实验

2. SeedTTS-Eval 评测

  • 英语训练数据不到一半,但是论文认为英文效果相对来说也是不错的

3. 强化学习评测

3.1 两种策略的有效性验证
  • Clip-Higher:ε_high 设置为 0.3,ε_low 设置为 0.2
  • Dynamic Sampling:advantage 数值为 0 的情况,最多采样三次
3.2 Clip-Higher 不同数值的效果
  • ε_high 数值越大,EMO 情感合成效果越好,但是 WER 后续也会变高
3.3 增加笑声的 reward function
  • 引入了一种笑声奖励机制,具体规则总结如下:若输入文本包含两个及以上连续的笑声词汇(如 “哈”“嘿” 等),且笑声检测模型识别出对应的笑声片段,则执行以下奖励判定:

    • 这里的奖励值(0 或 1)是给强化学习模型的 “反馈信号”——奖励值为 1 表示模型做对了,会被鼓励继续这么生成;奖励值为 0 表示模型没做好,会被引导调整优化。
    • 情况 1:奖励值 = 1(最优结果)当 ASR 系统把生成的笑声片段转录为 “deletion(空字符串)” 时,奖励设为 1
      • 通俗理解:对于合成出来的语音,ASR 系统 “听不出这段声音是哪个具体文字”,说明生成的是自然无意义的笑声(不是清晰的 “哈” 字发音),完全符合预期,给模型最高奖励。
    • 情况 2:奖励值 = 0(待优化结果)当 ASR 系统把笑声片段准确转录为对应的文本(如把生成的笑声转成 “哈哈”)时,奖励设为 0
      • 通俗理解:对于合成出来的语音,ASR 能识别出文字,说明生成的笑声太像 “朗读文字”,不够自然,模型得不到奖励
  • 疑惑:

    • 这里的 reward function 奖励值,其实只能保证合成的笑声不是机械的「哈哈」,但是并不能保证一定能合成笑声
    • 如果是其他杂七杂八的声音,但是也不会被 ASR 识别出来,就白训练了
    • 此外,现在的 ASR 模型对于笑声的识别可能也会相对「容易」,即使是比较自然类似真人的笑声,也有可能被识别出来汉字
    • 在评测指标里,论文并没有真实人工来判断合成的笑声效果怎么样,EMO 指标变好不一定有相关性?

4. Phoneme-In 音素混合评测

5. Vocos2D 评测

五、借鉴点 Takeaways

1. 针对性的 Tokenizer 优化策略

  • 语音 Tokenizer 提升帧率(12.5Hz→25Hz)、扩展词汇量(16k→32k),新增基频估计模块,强化副语言特征(笑声、呼吸)与韵律对齐度
  • 采用非因果架构,移除 chunk 注意力与因果卷积,提升 ASR 和基频建模精度

2. GRPO/DAPO 在 TTS 中的创新适配

  • 多奖励 GRPO 策略:融合发音、音色、情感、笑声四大奖励,解决传统 RL 奖励单一问题;
  • 层次化奖励融合:单奖励归一化→加权融合→分组归一化,适配不同奖励数值分布;
  • Clip-Higher 改进:分离梯度裁剪上下阈值(ε_high>ε_low),缓解熵崩溃,平衡稳定性与探索性;
  • 动态采样机制:过滤 “全对 / 全错” 无效样本,保留有效梯度样本,提升训练效率。

3. 声码器的针对性重构与性能提升

  • 提出 Vocos2D 声码器:2D 卷积替代 1D 卷积,聚焦频率子带建模;新增 Mel 频谱 shortcut 与频域 embedding,增强特征关联;
  • 优化损失函数:移除 MPD,新增判别器数据增强(DA),提升泛化能力;
  • 支持 32kHz 宽带输出,主观 MOS 从 3.58 提升至 4.16,客观指标(NISQA/UTMOS)显著优化。

4. 副语言特征(笑声)的精细化建模

  • 设计独特笑声奖励函数:以 ASR 转录结果为判定依据,笑声片段被转录为 “空字符串”(自然无意义笑声)时奖励 1,被准确转录为文本(机械朗读感)时奖励 0,针对性解决合成笑声不自然问题。