情感语音合成数据集构建:为Sambert-HifiGan准备训练数据
📌 引言:为何需要高质量的多情感语音数据?
随着语音合成技术从“能说”向“会表达”演进,情感语音合成(Emotional Text-to-Speech, E-TTS)已成为智能客服、虚拟人、有声阅读等场景的核心需求。传统的TTS系统往往语调单一、缺乏情绪变化,难以满足真实交互中的情感传递需求。
在中文场景下,基于ModelScope 的 Sambert-HifiGan 多情感语音合成模型是当前开源社区中效果出色且易于部署的方案之一。该模型不仅能生成自然流畅的语音,还支持通过标签控制情感类型(如高兴、悲伤、愤怒、中性等),实现“带情绪说话”。
然而,要训练或微调这类模型,首要任务是构建一个结构规范、标注清晰、音质优良的多情感中文语音数据集。本文将系统讲解如何为 Sambert-HifiGan 模型准备训练数据,涵盖数据采集、清洗、对齐、标注到最终格式转换的全流程,帮助开发者高效构建自有情感语音能力。
🧱 数据集核心结构与格式要求
Sambert-HifiGan 模型在训练时依赖特定的数据组织方式。其输入数据需满足以下结构:
dataset/ ├── wav/ │ ├── utt_001.wav │ ├── utt_002.wav │ └── ... ├── text.txt └── emotion_label.txt✅ 关键文件说明
| 文件 | 作用 | 格式示例 | |------|------|----------| |wav/| 存放所有单通道、16kHz采样率的.wav音频文件 | PCM 编码,16bit | |text.txt| 文本内容清单 |utt_001|今天天气真好啊| |emotion_label.txt| 情感标签映射 |utt_001|happy|
📌 注意:所有文件名前缀必须一致(如
utt_001),用于跨文件关联。
模型通过三元组(音频路径, 文本, 情感标签)进行监督学习,因此数据一致性至关重要。
🗂️ 第一步:数据采集与语音录制规范
高质量语音数据是合成自然语音的基础。建议采用专业录音设备+安静环境进行录制,避免背景噪声和失真。
录制建议参数:
- 采样率:16kHz(必须)
- 位深:16bit
- 声道数:单声道(Mono)
- 编码格式:WAV(PCM)
情感类别设计(推荐5类)
| 情感标签 | 适用语境 | 示例语气 | |---------|--------|--------| |neutral| 日常陈述 | 平稳、无起伏 | |happy| 喜悦表达 | 节奏快、音调高 | |sad| 悲伤叙述 | 低沉、缓慢 | |angry| 愤怒强调 | 强重音、爆发力 | |surprised| 惊讶反应 | 突然升高、拉长 |
每种情感建议录制不少于1小时的语音数据(约3000条句子),以保证模型充分学习语调模式。
💡 提示:可参考 EmoDB、AISHELL-Emotion 等公开数据集的情感分类标准。
🔍 第二步:文本-语音对齐与强制对齐(Forced Alignment)
原始录音与文本之间存在时间偏移,必须通过强制对齐技术确定每个字/词的起止时间点,用于后续声学特征提取。
我们推荐使用Montreal Forced Aligner (MFA)或WeNet-based 对齐工具实现精准对齐。
使用 MFA 的基本流程:
# 安装 MFA(需Python 3.8+) pip install montreal-forced-aligner # 准备输入目录结构 mfa_align \ ./dataset/wav/ \ ./dataset/text.txt \ mandarin_ns \ ./output_alignment/输出结果包含每个音频的.TextGrid文件,记录了音素级的时间边界。
⚠️ 注意事项: - 中文需使用
mandarin_ns字典(带声调) - 若自定义词汇较多,需扩展发音词典
对齐成功后,可提取更稳定的梅尔频谱特征,提升模型收敛稳定性。
🧹 第三步:数据清洗与质量过滤
并非所有录音都适合用于训练。需对数据进行自动化清洗,剔除低质量样本。
清洗维度包括:
| 维度 | 判断方法 | 处理方式 | |------|--------|--------| | 静音过长 | 使用librosa.effects.split()检测非静音段 | 删除静音占比 >40% 的音频 | | 信噪比低 | 计算 SNR(信噪比) | 剔除 SNR < 20dB 的样本 | | 文本-语音不匹配 | WER(词错误率)评估ASR识别结果 | WER > 30% 视为异常 | | 情感标签偏差 | 人工抽检或情感分类模型打分 | 修正或删除误标样本 |
示例代码:检测静音片段比例
import librosa import numpy as np def is_too_silent(audio_path, threshold=-40, max_silence_ratio=0.4): y, sr = librosa.load(audio_path, sr=16000) # 将dB小于threshold的部分视为静音 rms = librosa.feature.rms(y=y)[0] db = librosa.amplitude_to_db(rms) silent_frames = np.sum(db < threshold) total_frames = len(db) silence_ratio = silent_frames / total_frames return silence_ratio > max_silence_ratio # 批量过滤 for wav_file in os.listdir("dataset/wav"): path = os.path.join("dataset/wav", wav_file) if is_too_silent(path): print(f"Removing silent file: {path}") os.remove(path)清洗后保留的音频应具有良好的可懂度和情感表现力。
🏷️ 第四步:情感标签标准化与标注增强
原始情感标签可能来自主观标注或自动预测,需统一格式并做一致性校验。
推荐标签体系(兼容Sambert-HifiGan):
utt_001|happy utt_002|sad utt_003|neutral ...可选增强策略:
- 半自动标注:使用预训练情感识别模型(如 CNERT、EmoRec)对语音打初筛标签
- 多人标注+投票机制:提升标注可信度
- 上下文感知标注:结合对话历史判断情感倾向(适用于对话式TTS)
📌 建议:建立标注规范文档,明确各类情感的语义边界,减少歧义。
🔄 第五步:数据预处理与特征提取
Sambert-HifiGan 在训练时并不直接使用原始音频,而是依赖预提取的梅尔频谱图(Mel-spectrogram)和语言学特征。
特征提取流程:
- 文本前端处理:
- 分词 + 拼音转换
- 声调标注(zhong1 wen2)
生成音素序列(可选)
声学特征提取:
- 梅尔频谱:
n_mels=80,hop_length=200,win_length=800 - F0(基频)提取:使用 Dio + Stonemask 算法
- 能量特征:帧能量均值归一化
示例代码:提取梅尔频谱
import librosa import numpy as np def extract_mel_spectrogram(wav_path): y, sr = librosa.load(wav_path, sr=16000) mel_spec = librosa.feature.melspectrogram( y=y, sr=sr, n_fft=1024, hop_length=200, win_length=800, n_mels=80, fmin=0, fmax=8000 ) log_mel = librosa.power_to_db(mel_spec, ref=np.max) return log_mel # shape: (80, T) # 保存为.npy文件供训练使用 mel = extract_mel_spectrogram("utt_001.wav") np.save("dump/train/mel/utt_001.npy", mel)这些特征将被缓存至dump/目录,供训练时快速加载。
📦 第六步:构建符合 ModelScope 训练框架的数据管道
ModelScope 的 Sambert-HifiGan 训练脚本通常基于datasets库构建数据集对象。我们需要将原始数据转换为 HuggingFace Dataset 兼容格式。
数据集注册示例(JSONL 格式):
{"utt_id": "utt_001", "text": "今天天气真好啊", "audio": "wav/utt_001.wav", "emotion": "happy", "mel": "dump/mel/utt_001.npy"} {"utt_id": "utt_002", "text": "你为什么要这样做", "audio": "wav/utt_002.wav", "emotion": "angry", "mel": "dump/mel/utt_002.npy"}加载为 Dataset 对象:
from datasets import Dataset import json # 读取jsonl data = [] with open("train.jsonl", "r", encoding="utf-8") as f: for line in f: data.append(json.loads(line)) ds = Dataset.from_list(data) def collate_fn(batch): texts = [b["text"] for b in batch] mels = [np.load(b["mel"]) for b in batch] emotions = [b["emotion"] for b in batch] return {"texts": texts, "mels": mels, "emotions": emotions}此数据管道可无缝接入 ModelScope 的 Trainer 框架。
⚙️ 第七步:适配 Sambert-HifiGan 模型训练配置
完成数据准备后,需修改训练配置文件以启用情感控制功能。
修改config.yaml示例:
model: type: "SambertHifiGan" params: n_vocab: 3000 n_mels: 80 emotion_dim: 5 # 支持5种情感 use_emotion_embedding: true dataset: train: data_dir: "./dump/train/" metadata: "train.jsonl" valid: data_dir: "./dump/valid/" metadata: "valid.jsonl" training: batch_size: 16 epochs: 100 lr: 0.001 save_every: 10000关键参数说明: -emotion_dim: 情感嵌入维度,等于情感类别数 -use_emotion_embedding: 是否开启情感条件输入
训练过程中可通过 TensorBoard 观察损失下降趋势与合成语音质量。
🧪 验证:使用 Flask WebUI 测试微调后的模型
正如项目介绍中所述,集成 Flask 的 WebUI 提供了直观的测试入口。
启动服务后操作流程:
- 打开浏览器访问本地服务地址
- 输入测试文本:“我简直不敢相信!”
- 选择情感模式:
surprised - 点击“开始合成语音”
若模型已正确学习情感表达,则输出语音应具备明显的惊讶语调(音高突升、节奏加快)。
✅ 成功标志:不同情感下同一文本的语调差异显著且符合人类感知预期。
🎯 总结:构建情感语音数据集的关键实践建议
- 数据质量优先:宁缺毋滥,确保每条数据都清晰、准确、情感明确
- 标注一致性保障:制定标准、多人交叉验证,避免主观偏差
- 自动化清洗流程:引入静音检测、SNR评估、WER校验等工具链
- 特征工程不可跳过:精确的F0、能量、梅尔谱是高质量合成的前提
- 端到端验证闭环:从数据→训练→WebUI播放形成完整反馈链
🚀 下一步建议
- 尝试微调现有模型:在官方预训练模型基础上进行少量数据微调,快速验证效果
- 探索细粒度情感控制:引入强度维度(如 happy → happy_level=0.8)
- 构建个性化声音库:结合少量目标人声音频,实现“情感+音色”双可控合成
通过科学构建情感语音数据集,你不仅可以复现 Sambert-HifiGan 的强大能力,更能在此基础上打造真正“有温度”的语音交互体验。