
简介本资源是面向歌声合成方向研究者与深度学习工程师的高质量多模态数据集专为训练和验证基于神经网络或HMM的端到端歌声合成模型而构建。包内共502个文件涵盖100首完整歌曲的WAV无损人声录音、MIDI精确旋律与节奏结构、歌词文本TXT及音节级时长标注CSV另含元信息JSON与系统隐藏文件971.99MB压缩包结构清晰各模态数据严格对齐便于直接用于声学建模、音高预测、时长建模等关键任务。已有836人学习下载适用于语音合成进阶实践、多语言含韩语歌声建模探索及HMM与深度学习融合方法验证。用户可直接加载MIDI歌词时长标注构建输入特征以WAV为目标进行监督训练快速启动Tacotron/WaveNet/Transformer等主流架构的复现与优化工作。 搞歌声相关项目的人看到100首歌声数据集含midi 歌词 标注时长 wav这种压缩包第一反应通常不是兴奋而是警惕。因为我见过太多人拿到类似资源后解压一看wav文件是有了midi也对得上但歌词标注的txt里全是乱码时长标注跟音频实际长度差了十万八千里最后只能自己重新洗一遍数据。数据集本身是歌声合成、音乐信息检索、音高分析这些方向最基础也最关键的资产但能不能直接用跟文件齐不齐完全是两回事。这篇就把我从验收、清洗到接入训练管线的一整套处理方式拆开讲给准备拿这套数据动手的朋友一个完整的参考。先说这100首歌的数据集到底意味着什么。100首wav按每首平均三分钟算音频总时长大概是5到6个小时这个体量对音色克隆、单曲翻唱这类小尺度任务来说是够的对从零训练歌声合成模型则只能算小型起步集。真正值钱的不是音频数量而是后半句——midi、歌词、标注时长。这三个东西代表着每一个音符的起点终点、每一句歌词对应的时间位置、旋律的量化表达全都有了。这意味着你拿到的不是一堆裸音频而是一套打了索引的素材库。1. 四层文件结构梳理wav、midi、歌词文本、时长标注分别解决什么问题很多刚接触音频数据集的人容易把文件清单理解成文件种类然后默认每一首歌都应该四件套齐全。但实际整理过数据的人都知道一个来自网络分享的数据包最常出现的状况就是四种文件数量对不上有的歌有midi没歌词有的歌有wav没标注这时候不能一股脑全删得先搞清楚每一层文件在整条流水线里扮演什么角色。1.1 wav最容易被高估的一层wav是歌声的原始载体也是所有人拿到包之后第一个去听的东西。但很多人忽略了一个关键问题wav里录的到底是纯人声干声还是带伴奏的完整混音这两种东西对后续处理的影响天差地别。如果是纯干声那你可以直接拿去做音色训练、提取音高、做歌词对齐如果带伴奏你就必须先做一次人声分离质量还未必有保证。所以拿到wav文件我不会急于听而是先看一眼波形图和频谱。纯人声的频谱通常在中低频段有明显的共振峰结构高频衰减比较自然伴奏则常有低频打击乐和宽频带锯齿感。这一步用Audacity或者Python里的librosa都能快速完成不需要多高深的技能但能帮你省掉后面几个小时的弯路。1.2 midi歌声旋律的量化骨架midi文件在歌声数据集里的作用经常被新手当成用来放伴奏的这是误解。midi记录的是一串音符事件音高、起始时间、持续时间、力度甚至歌词在某些标准里也能挂进去。它是歌声旋律的量化表达跟wav里实际唱出来的声音之间是谱面和演奏的关系。拿着midi你能干什么比如做音高对比把midi音符转成F0参考曲线然后跟wav里提取出来的实际基频做对齐一来可以验证wav里唱的是不是跟谱面一致二来可以作为训练歌声合成模型的音高标签。这也是为什么很多对齐模型需要midi作为先验输入——它能帮你把歌词、音符、音频三者拉到一个时间坐标系里。1.3 歌词文本从听感到可计算的桥梁歌词文本单独看只是一堆字但跟midi、时长标注合在一起就成了音素级别标注的原材料。比如中文歌词需要考虑字到音素的映射需要一个分词注音工具把我们拆成wo3 men5英文歌词则需要考虑连读和弱读日文还得处理假名和罗马音。没有歌词文本后续训练TTS或歌声合成模型时你就只能手工补标那个工作量是灾难级的。这套数据集号称带歌词我建议先确认是纯文本文件还是LRC格式还是挂在midi里的歌词事件。不同来源处理成本差异很大纯文本最灵活LRC自带时间信息但解析容易踩编码坑midi里的歌词事件要靠mido自己抽取。1.4 时长标注整包数据里真正的灵魂时长标注本质上是一张时间-内容映射表。最简单的形态是每句歌词的起止时间再细一点是每个字的起止时间最细可以做到音素级别。标注格式常见的有JSON、CSV、TextGrid这几种但不管格式怎么变核心字段离不开三样起始时间、结束时间、对应的文本内容。我拿到数据集后的第一个习惯就是找这份标注文件。因为它的质量直接决定了这个数据包是素材还是训练集。如果时长标注只是粗略标到句子级别那你要做字级对齐就得再跑一遍强制对齐工具如果标到了音素级别那几乎可以直接喂给声学模型。下面一节重点讲讲标注里常见的几种对齐粒度和它们各自适合干什么。2. 时长标注体系拆解为什么对齐质量决定模型上限很多做音频的同行都有过这种经历调音高、调共振峰、调混响折腾半天模型效果上不去最后发现是训练数据的标签本身就对不齐——该从0.5秒开始的音符标到了0.8秒该持续1.2秒的韵母只标了0.3秒。模型再强喂进去的是错位标签出来的预测必然一团糟。这就是为什么我一直强调时长标注是数据集的upper bound标注对齐到什么精度模型就只能学到什么精度。2.1 三种对齐粒度句子级、字级、音素级先说句子级标注。它的格式一般长这样我们都已经尽力了 | 3.420 | 7.135。这种标注只能告诉你这句话从哪开始在哪结束适合用来做歌曲段落切分、歌词滚动显示但没法直接支撑音高预测和音素时长建模。你要是想训练一个能逐字合成歌声的模型光靠这个粒度远远不够。字级标注是大多数翻唱和歌声合成项目能接受的最低门槛我 | 3.420 | 3.781、们 | 3.781 | 4.205。每个字起止时间清清楚楚配合带音调的拼音标注就能用于SoVITS这类模型的音素对齐效果比整句级别的强一个数量级。代价是标注成本直线上升纯人工标一首三分钟的歌光字边界就要耗掉半小时以上。音素级标注是上限w|o3 | 3.420 | 3.550、m|en5 | 3.550 | 4.205。它把每个字拆成声母韵母连每个音素持续多少毫秒都标出来了。这类数据可以直接用于DiffSinger、Vocaloid类声学模型的训练因为模型需要知道每个音素应该唱多长。但音素级标注成本极高100首歌全标到这一档已经是一个专业团队干几周的活。2.2 从标注错误率看数据质量为什么loss降不下来先查标注热搜词里有个说法很到位错误标注会导致数据标注模型训练集loss降不下来。这句话我太有体会了。训练集里如果混了10%的对齐错误样本刚开始训练看不出问题到了后面就会一直有个顽固的loss尾巴怎么调参数都压不下去。不是模型容量不够是它在强行拟合一批标签本身自相矛盾的样本。所以在接进训练管线之前我会对时长标注做一次合理性审计每句的结束时间必须大于起始时间相邻两句的时间不能大量重叠或出现明显空档每句时长跟音频实际长度的差值应在容忍范围。这一套规则用Python写个脚本十几分钟就能跑完却能提前过滤掉最脏的那批数据。按我的经验一个网上下载的数据集能一次通过这种审计的比例经常不到七成。2.3 标注格式的兼容与归一不同来源的数据集时长标注的格式五花八门有JSON数组有CSV三列有TextGrid分层甚至还有塞在MIDI歌词事件里的。接进自己的项目之前我会统一转成同一种中间格式最省心的做法是JSON每首歌一个文件[ { start: 3.42, end: 3.781, text: 我, phonemes: [{phone: w, start: 3.42, end: 3.55}, {phone: o3, start: 3.55, end: 3.781}] } ]这个结构足够灵活既能表达句子级也能表达音素级后面切音频、对齐、训练都不用再关心源格式长什么样。归一化这一步虽然无聊但它是整个数据管线里最值得花时间的地方——统一了格式后面所有脚本才能复用。3. 数据验收从文件名到波形图的逐级体检我不相信任何网上分享的数据集到手即用。这个标题里写的是100首歌声数据集但实际操作里100这个数字很可能有水份——可能是曲目编号有重复可能是某首歌的wav文件损坏成0字节也可能是midi文件其实是民乐改编版。所以拿到压缩包的第一时间我的动作是解压、列清单、体检而不是急着跑模型。3.1 文件级清单检查先在解压后的根目录跑一遍全文件清单看看整体目录结构长什么样find . -type f | sed s/.*\.// | sort | uniq -c这个命令能快速统计出每种后缀的文件数量。理想的四件套应该是100个wav、100个midi、至少100份歌词文本、100份标注文件。如果数量对不上比如只有93个标注文件那就需要把缺的曲子列出来单独处理而不是假装没看见。数量对得上的前提下再看命名是否成体系最常见的坑是wav叫track01.wavmidi却叫chinese_song_01.mid没有统一ID后面做文件匹配的时候就会很痛苦。3.2 音频级体检采样率、声道数、真实时长文件完整度过关后接下来对wav挨个体检。这里我习惯用一个ffprobe脚本批量导出音频信息for f in wavs/*.wav; do ffprobe -v quiet -show_entries formatduration -show_entries streamcodec_name,sample_rate,channels \ -of csv $f | sed s|^|$f,| done跑完你就能得到一张csv表里面是每首歌的时长、采样率、声道数。然后对着检查这100首的采样率是不是统一如果是44.1kHz就有训练的时候要重采样的意识如果混着48kHz和44.1kHz训练之前必须统一声道如果有些是立体声有些是单声道得想清楚处理策略。另一个检查点是时长标称3分钟的歌实际长度却只有30秒这种文件大概率是被截断或者转码出错了。如果条件允许我还会抽几首用librosa画出波形和频谱确认不是噪音或静音文件。一个容易被忽略的细节是很多网上下载的数据包wav头部信息正常但实际音频段被截断了用人工听一张张验太累但用波形图看能量分布一眼就能揪出来。3.3 midi与歌词的交叉核对midi文件最容易出的问题是人声主旋律轨和伴奏轨混在一起。一个标准的歌曲midi往往有好几条轨钢琴、贝斯、鼓、主旋律。而歌声数据集里我们要的通常只有主旋律轨。拿到midi后我会用mido把轨道列出来看看每条轨道的音符密度和音域import mido mid mido.MidiFile(song.mid) for i, track in enumerate(mid.tracks): notes [msg for msg in track if msg.type note_on and msg.velocity 0] if notes: pitches [n.note for n in notes] print(fTrack {i}: {len(notes)} notes, pitch range {min(pitches)}-{max(pitches)})主旋律轨通常音符数跟歌词字数接近音域也不会跨到超低音区。如果某条轨的音符数远超歌词字数那多半是伴奏里的分解和弦。这个交叉核对不需要做得多精细目的只是确认你后面用的midi是歌声的主旋律而不是伴奏的千军万马。歌词文本好不好用主要看编码。中文歌词最常见的坑是UTF-8被错误识别成GBK打开以后满屏乱码。我一般用file命令先看编码再写个小脚本统一转成UTF-8。另外还要确认歌词是否带注音或音调标记纯汉字和带拼音的数据集在使用难度上完全不是一个档次的。3.4 时长标注的抽样人工复查机器能检查的只有格式和逻辑但端点标注是否真正落在语音边界上机器暂时还判断不了只能人工听。抽样复查的姿势是从100首里随机抽5首用Python读取标注里的前10个字的时间然后用ffmpeg把音频按时间切出来一段段听。ffmpeg -i song.wav -ss 3.42 -to 3.781 -c copy output_chunk.wav如果切出来的每段音频能跟标注文字一一对应那代表标注质量有一定保证如果经常出现切到半个音、句子错位、或者文字和音频对不上那这批数据的标注就得重新评估考虑是否放弃这5首还是扩大到全量检查。我遇到过一个数据集前面30首标注问题不大从第31首开始全是偏移的估计是标注到一半换人干活了后面就彻底放飞。4. 接进训练管线音频标准化与midi解析的实操细节数据验收通过之后才能进入正式的预处理。这部分的目标非常明确把wav和midi转成模型能直接消费的张量歌词文本转成带音素的符号序列把时长标注转成对齐矩阵。每个细节都会影响最终模型效果所以我每条链路都要说得具体一点。4.1 音频标准化采样率统一与去静音训练歌声相关模型音频采样率的默认选择通常是22050Hz或24000Hz。100首歌如果原生是44.1kHz直接用librosa重采样也行但数据量一大我会改用ffmpeg速度快不少ffmpeg -i input.wav -ar 22050 -ac 1 -acodec pcm_s16le output.wav这一条命令完成三件事采样率转22050Hz、转单声道、编码转16位PCM。转换之前建议先看看数据里有没有已经是单声道的文件统一处理成单声道可以避免训练时声道不匹配。去静音这步得小心歌曲首尾的呼吸声和极短的气口不一定要全切掉我只去掉时长超过0.5秒且能量接近0的长静音段保留开头的人声进场前一小段防止切太狠破坏句间连贯性。4.2 midi解析把音符事件变成F0曲线训练歌声合成或做音高对比时midi里的音符是不能直接用的需要把它转成帧级F0参考。MIDI音符编号转频率的公式是f 440 * 2^((n - 69) / 12)这个对应关系是很多算法的基础。我在处理时会用一个固定hop_size比如512对应22050Hz下约23ms一帧。关键细节在音符边界跟帧边界不完全对齐。midi里记录的是起始tick数和持续tick数要结合Tempo变化换算成秒再映射到帧索引。这里最容易踩的坑是忽略速度变化如果歌曲中途有rubato或变速段直接用固定bps去换算后面的音符全部对不上。正确的做法是遍历midi里的Tempo事件逐段计算累计时间import mido import numpy as np mid mido.MidiFile(song.mid) tempo 500000 # 默认120BPM对应的微秒/拍 current_time 0 note_frames [] for msg in mid: current_time mido.tick2second(msg.time, mid.ticks_per_beat, tempo) if msg.type set_tempo: tempo msg.tempo elif msg.type note_on and msg.velocity 0: # 音符起始时间记录下来note_off再记录结束 note_frames.append((current_time, msg.note))这段代码把Tempo变化考虑进去遇到变速段才能得到基本准确的绝对时间。把音符序列映射到帧号之后常见的选择是取每帧的音高作为该帧的F0参考值没有音符覆盖的帧标记为静音或无音高段。这个音高参考谱是后面跑时长对齐、音高准确性评估的基础。4.3 歌词与标注进训练标签准备好音频和midi之后下一步是把歌词文本映射成训练标签。首先做字到音素的切分。中文可以用pypinyin或者更专用的G2P工具英文可以用espeak-ng这类日语就得用到pykakasi或OpenJTalk。拿音素序列跟时长标注里的文本比对确认每个字的音素个数和标注里的颗粒度对得上。训练歌声合成模型时一个常见需求是生成frame-level的标签序列每一帧属于哪个音素。实现思路是把标注的每个字区间平铺出来按帧时间戳判断每一帧落在哪个区间然后填上对应的音素索引。如果标注是句级而非字级就得先借助强制对齐工具比如Montreal Forced Aligner或基于Whisper的对齐方案把句级标注细化到字级这一步成本高但跳不过。4.4 标准化后的数据集目录组织几十个小时的音频和几百份标注文件如果不重命名、不归档用起来随时会翻车。我通常会把标准化后的数据组织成下面这种结构raw/ # 原始文件只读备份 processed/ wavs/ # 统一采样率单声道的音频 mids/ # 解析后的音符序列npy格式 labels/ # frame级标签npy格式 metadata.json # 全量索引曲名、歌手、时长、标注来源metadata.json是整个数据集的入口每一行记录一首歌的所有文件路径、时长、字数、标注粒度。这样不管后面写训练脚本还是做数据筛选都只需要读这一个文件不用反复去翻原始目录。我还会顺手把检查脚本的输出结果存一份csv方便后面做数据子集划分时参考。5. 拿这套数据能干什么歌声合成、MIR研究与衍生应用数据洗好了、管线通了接下来才是享受成果的时候。这套wavmidi歌词标注四件套能支撑的方向比很多人想象的要宽。5.1 歌声合成与音色克隆最直接的应用是拿去训练或微调歌声合成模型。用SoVITS这类工具做单曲音色克隆100首数据里随便挑几首同一歌手的歌就够了具体看音色相似度要求。如果你想跑更完整的DiffSinger那需要的是音素级别标注这套数据如果只做到字级就得先行补标音素。实际操作里我建议不要一上来就把100首全扔给模型训练。先挑30首质量最高的跑通整个训练流程看loss能不能正常下降、合成效果是否稳定。确认链路没问题了再把剩余数据按质量梯度逐步加进去。这种递进式训练远比第一次就灌100首出了问题不知道从哪查起要省时间。5.2 音乐信息检索与对齐研究对做MIR方向的人来说midi时长标注本身就是金矿。可以拿它训练歌声音符起始点检测模型用midi音符作为ground truth也可以做歌声与midi的对齐评测基准比较不同对齐算法在真实唱歌数据上的表现歌词标注还能支撑歌词音素识别、歌声语音识别等任务。这类任务的关键在于评测时千万不能用训练集里的歌否则模型背答案都能背出高分。建议把100首分成训练、验证、测试三份比例可以按8:1:1测试集里的歌在训练时彻底不见。很多公开数据集的悲剧就是划分不当导致论文指标虚高复现时集体翻车。5.3 歌词滚动字幕与卡拉OK我最近给一个视频项目做自动歌词字幕发现这套数据里的时长标注稍微改一改就能直接用来生成卡拉OK滚字。原理不复杂从标注里拿到每句或每字的起止时间按时间顺序输出LRC格式字幕或者渲染成带高亮的字幕文件。如果你只想做效果演示不需要训练模型这可能是最快见效的玩法。5.4 作为预训练数据的小规模扩展100首歌单独训练可能不够但它可以作为预训练语料用来初始化模型参数然后再用目标歌手的少量数据微调。这在TTS和SVS里是常见的迁移学习思路先用大规模数据学怎么唱歌的通识再用小数据学这个歌手的音色。你在网上找到的其他音频数据只要统一转成同样的采样率、同一种标签格式就能跟这批数据合并扩充训练集扩大数据量的同时还能摊平标注噪声。6. 我实际踩过的坑编码、漂移、多轨与伴奏残留最后这部分是每次处理音频数据都绕不开的四个实战坑。我不保证每一条都会出现在你这份数据上但提前知道怎么处理能少走不少弯路。6.1 中文歌词编码UTF-8和GBK的修罗场网上下载的数据歌词txt文件最常见的死法是用GBK编码保存被Python按UTF-8读取结果全是\ufffd替换字符。更隐蔽的是前几个文件是UTF-8后面某几个变GBK整体读一遍下来半途报错。应对方法读文本之前先用chardet或charset-normalizer探测编码探测到非UTF-8就转码。还有个更粗暴但实用的土办法直接检查文件头是不是UTF-8的BOM有BOM的按UTF-8-sig读没有BOM的再走detect流程。实际处理时我建议统一转成UTF-8无BOM输出覆盖原文件或另存一份避免后面每个脚本都重做一次编码判断。6.2 时长标注漂移标注员中途换人不是段子标注漂移指的是同一首歌里前半部分标注偏早、后半部分标注偏晚或者整首歌所有的标签都整体向后偏移了200毫秒。这种问题靠抽样听很难发现因为单听一个字感觉差不多但把整首歌的字边界连起来对比midi音符立刻就能看出整段错位。定位漂移的方式是把标注的每字结束时间跟midi的音符起始时间做差画出偏差分布。如果偏差曲线在中段出现跳变或者整体呈线性递增基本就是漂移。处理办法取决于漂移类型整体偏移直接加固定修正量逐段漂移则要用分段映射校正把标注时间映射到midi时间轴。比较严重的可以直接把那几首排除训练集不值得浪费时间去修。6.3 midi多轨与主旋律选择我前面提过midi文件多轨的问题再补充一个细节即使只有一轨也未必是主旋律有些midi会把人声旋律和主奏乐器放在同一轨音符数量多且密集。选择主旋律轨时我一般结合歌词字数判断——歌词有多少个字主旋律音符就大概有多少个相差超过50%就说明选错了。有个实用的辅助手段把各轨的音符转成MIDI可视化直接在DAW或者Python的pretty_midi里画出钢琴卷帘。人类看一眼就能分辨哪条是主旋律尤其是音高跨度大、节奏跟着歌词走的基本就是。筛轨这件事别偷懒用错轨道会导致后面的音高标签全错而这种错误不会体现在loss上只会体现在最终合成的声音离谱上。6.4 wav里还残留伴奏或和声即使是标着干声的wav也经常混着轻微伴奏、和声或者混响尾巴。这不能全怪数据分享者录音条件、后期处理方式都会影响。对训练歌声模型来说伴奏残留会干扰音高提取导致标注的F0和实际音频不匹配。最粗暴的解决方式是用开源的分离工具跑一遍人声分离UVR5或者Demucs都行把分离出来的纯人声再跟原音色对比一下损失小就采用损失大就放弃或者减权重。如果只是少量伴奏残留也可以用高通滤波和动态压缩稍微改善但这治标不治本对训练数据干净度要求高的话分离几乎是必经步骤。处理音频数据这件事说到底没有一劳永逸的标准答案每个数据包的毛病都不一样。但有一件事是共通的把验收和清洗当回事后面训练才会顺省了前面的功夫迟早会在调试模型的时候加倍还回来。我每次拿到新的歌声数据集哪怕看起来再规整也会按这套流程从头到尾走一遍就当是给自己省心。本文还有配套的精品资源点击获取