[工具] 给 GPT-SoVITS 加了一套批量推理工作流
最近在鼓捣《魔法少女的魔女审判》的 mod,除了写剧本和 mod 化以外,主要的工作就是配音。配音主要是使用 GPT-SoVITS 基于原版语音进行训练之后进行推理,但是 GPT-SoVITS 自带的 WebUI 只能一句一句的推理,仓库里自带的批量推理脚本也是个半成品。我一开始简单写了一个脚本用来做批量推理,发现由于参考音频的存在,导致批量推理不仅限于写个 for-loop,更重要的是如何选取参考音频,否则配出来的效果实在是太过于抽象了。
因此我在上游 GPT-SoVITS 的基础上 fork 了一份,加了一整套批量推理 + 情感模型初筛 + 人工复核的工作流,仓库地址:https://github.com/AsaChiri/GPT-SoVITS。这篇文章就来介绍一下怎么用这套工具。
这东西到底解决了什么问题?
熟悉 GPT-SoVITS 的朋友应该都知道,这玩意推理的时候需要给每一句话指定一个参考音频,参考音频的音色和情绪很大程度上决定了输出的效果,因此给每一条待推理的文本选择合适的参考音频就是最重要的工作。开心的台词当然要用开心的参考,难过的台词要用难过的参考,不然出来的语气全是错的。让人手动从几百条里一条一条挑,属实不太现实,眼睛都要花了。我也不想亲自开麦克风录音,有这个水平我不去当 CV? 不过情感模型不一定靠谱。根据群友的反馈,top-1 的结果不一定令人满意,因此在这个基础上又增加了一个人工复核的环节,让情感模型选择出 topK, 由人工决定使用哪一个。
先准备点东西
要让这套工具跑起来,你需要准备两样东西:一份角色配置,一份输入清单。
角色配置 inputs/speaker_config.yaml 告诉工具你有哪些角色、每个角色的 GPT/SoVITS 权重放在哪里、每个角色的参考音频库(也是一个标准的 GPT-SoVITS 数据 .list 文件)在哪里。格式大概长这样:1
2
3
4
5
6
7
8
9
10
11speakers:
alisa:
gpt_path: GPT_weights_v2ProPlus/alisa-e15.ckpt
sovits_path: SoVITS_weights_v2ProPlus/alisa_e8_s456.pth
ref_list: inputs/alisa.list
ref_audio_dir: inputs/
hiro:
gpt_path: GPT_weights_v2ProPlus/hiro-e15.ckpt
sovits_path: SoVITS_weights_v2ProPlus/hiro_e8_s2184.pth
ref_list: inputs/hiro.list
ref_audio_dir: inputs/
每个角色的 ref_list 其实可以直接使用训练集。所以本质上不需要你再额外整理什么东西。
输入清单 inputs/mod_input/*.list 就是你要合成的台词,格式和训练数据的 .list 完全一致:音频路径|角色名|语言|文本。每行一句,大概像这样:1
2
3output/scene01/001.wav|alisa|ja|おはよう、今日もいい天気ね。
output/scene01/002.wav|hiro|ja|……うるさいな。
output/scene01/003.wav|alisa|ja|もう、せっかく挨拶したのに!
第一列是输出 wav 的相对路径(工具最后会按这个路径把合成结果写到输出目录里,所以你提前把文件结构设计好即可),第二列的角色名要对得上 yaml 里的 key。可以准备好几个 .list 文件放在一起处理,工具会按 glob 一起读。
打开 WebUI
准备好之后,双击仓库根目录下的 go-batch-webui.bat,或者手动执行:1
runtime\python.exe -I webui_batch_inference.py zh_CN
浏览器会自动打开 http://localhost:9870。整个 UI 就三个 Tab——配置、审阅试运行结果、帮助,对应三个步骤,非常好找。下面我就顺着流程讲一遍。
第一步:配置输入
打开之后先停在 配置 标签页,这里基本就是一堆配置框。需要填的其实没几个:
输入列表通配符 就是输入清单的 glob 路径,比如 inputs/mod_input/*.list。旁边有一个 预览匹配的文件 按钮,点一下就能看到匹配到了哪些文件,通配符写错也能第一时间发现。
说话人配置 是下拉框,会自动扫描 inputs/ 目录下的 yaml 文件。旁边的 查看说话人列表 按钮会把 yaml 里的角色信息展开成一个表格,角色对应的权重路径、参考列表什么的一目了然,省得我们自己打开编辑器核对。
输出目录 就是合成结果的输出目录,不多解释。
候选参考音频数量 (Top-K) 是试运行阶段每行保留几个候选参考,默认 5,我个人觉得挺合适的——再多了人工复核的时候听不过来,再少了又怕模型没挑到合适的。
模式 默认是 auto,也就是按情感自动挑参考。如果你想偷懒给所有句子用同一个参考(比如只合成单角色的短片段),可以切到 manual,会多出来一排参考音频/文本/语言的输入框。
剩下 高级推理参数 里的 top_k / top_p / temperature / speed_factor / batch_size / seed / text_split_method 这些和原版 WebUI 完全一致。
填完之后,点 试运行(挑选参考音频)。这一步不会合成任何音频,而是:
- 把 yaml 里配置的所有角色的参考音频库都读一遍,按时长过滤掉太短或太长的(默认保留 3~10 秒之间的,第一次跑的时候会慢一点,之后会缓存,缓存还会按 list 文件的 MD5 自动失效,所以你改了参考列表之后不用手动清);
- 按输入语言自动加载对应的情感分类模型——中、日、英、韩各有一个,首次运行会自动从 HuggingFace 下载;
- 对参考音频库的每一条文案打一个情感分数向量;
- 对你输入清单里的每一行台词同样打分;
- 用余弦相似度,从当前角色的参考库里挑出 Top-K 个情感最接近的候选,然后把这些候选路径写回到
.list文件的第 5 列(用逗号分隔)。
整个过程的日志会实时打到 UI 下方的 运行日志 框里,可以一边看进度一边摸鱼。跑完之后,输出目录里会多出来一份新的 .list 文件,每行末尾多了一列长得像 ref_a.wav,ref_b.wav,ref_c.wav,... 这样的候选列表。
第二步:人工复核
这时候切换到 审阅试运行结果 标签页。整个流程基本是这样:
- 点 重新扫描 output/,然后从下拉里选刚才生成的那份
.list文件(.curated.list会被自动隐藏,所以你回头不会看到自己已经筛过的东西混进来); - 页面会按每页 5 行展示,每一行包含:要合成的目标台词、角色名、语言、最多 5 个内嵌的音频播放器(就是 dry-run 选出来的 Top-K 候选),以及一个单选框让你挑最合适的那一个;
- 用 ◀ 上一页 / 下一页 ▶ 翻页,已经选过的不会丢;
- 全部听完之后,点 保存筛选后的列表。工具会在原文件旁边写一份
<原名>.curated.list,第 5 列就只留你选中的那一个参考路径。
这一步是整个流程里最花时间的,但也是质量保证的关键。在绝大多数情况下,这 5 个里会有一个合适的,如果都没有,那可能是输入里根本没有。
第三步:一键合成
筛选完之后,有两条路可以走。
第一条路是回到配置标签页,把输入列表通配符改成 output/.../*.curated.list,然后点 开始批量推理。
第二条路更省事——直接在审阅试运行结果标签页点 使用筛选后的列表开始批量推理,工具会自动用刚才保存的 curated 列表跑全量推理,不用你再跳回去。
接下来就可以把整台电脑丢给显卡过夜,第二天早上起来就能看到一堆 wav 文件静静地躺在输出目录里。
一些踩坑小记
这里顺便记录几个我自己踩过的坑,说不定对后来者有用。
Unicode / GBK 报错:go-batch-webui.bat 已经提前设了 chcp 65001 和 PYTHONIOENCODING=utf-8,如果你是从别的 shell 里直接跑 Python 文件,记得自己设一下,不然日文台词一打印就直接报错退出。
NLTK 的 tagger 缺包(英文 G2P 会用到):跑 python -m nltk.downloader averaged_perceptron_tagger_eng 一次来下载停用词即可。
首次运行下载情感模型失败:无非就是连不上 HuggingFace 的经典问题。实在不行就从别的地方手动把模型下到 GPT_SoVITS/pretrained_models/emotion-{ja,en,zh,ko}/ 目录下,工具会优先读本地的。
Dry-run 提示”No candidates”:先去检查一下 speaker 列有没有拼对,必须和 yaml 里的 key 一致、而且都是小写。yaml 里 key 的大小写工具会自动归一化,但输入清单里的不会。
端口被占用:9870 如果和你别的工具撞了,改一下 webui_batch_inference.py 里的 DEFAULT_PORT 即可。
仓库地址再贴一遍:https://github.com/AsaChiri/GPT-SoVITS,欢迎试用并反馈,有什么问题可以直接在 Github 上提 issue。











