音色工程 · 01 RVC(在用)¶
配套:
音色工程_00_公用.md(素材 / 清洗 / 混音 / 指标)、音色工程_02_SVC.md(实验线,已暂停)。 RVC = Retrieval-based Voice Conversion,我们现在语音条和翻唱都跑在这套上。
0. 一句话选型¶
| 需求 | 模型 | 备注 |
|---|---|---|
| 说话(QQ 语音条、TTS 变声) | 深澜语音用_v1 |
46 秒说话素材,够用 |
| 唱歌翻唱 | 深澜翻唱用_v2(48k) |
目前听感最顺,长音不飘(配合 crepe) |
1. 它是什么¶
- 仓库:https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI;CLI 分支用手上的 Applio。
- 核心:HuBERT / ContentVec 取内容特征 + Faiss 检索,把音色往训练集里"最像的那几条"上拉。
- 特点:整条音频一次过、不分段 → 响度连贯、没有拼接痕迹,这是我们选它的主要原因。
- 索引(
*.index)= 音色参照库;index-rate越高越贴训练集(更像,也更容易带噪、过拟合)。
2. 语言¶
- 中文占比够就行,不必纯中文。
- 实测:纯日文素材训出来有怪口音;加入中文素材后口音消失。 原因:ContentVec 把语言信息剥得比较干净 + Faiss 检索把音色压回中文口型。
- 要日语歌 → 另训一套日语为主的,别硬凑三语。
3. 训练(Applio CLI)¶
cd <RVC 目录>\Applio # cwd 必须是这里,否则 ModuleNotFoundError 'rvc'
python core.py preprocess --model-name X --dataset-path <清洗目录>
python core.py extract --model-name X --f0-method rmvpe
python core.py train --model-name X --epochs 200 --batch-size 4 \
--custom-pretrained --g-pretrained-path pretrained\f0G40k.pth --d-pretrained-path pretrained\f0D40k.pth
python core.py index --model-name X
坑:
- 默认会去 HuggingFace 拉权重(连不上),必须 --custom-pretrained 指本地;HF 走 hf-mirror.com。
- 48k 要用 f0G48k.pth / f0D48k.pth。
- 人声分离(BS-Roformer)是 CPU,极慢:48 分钟音频约 2 小时。
- segment_size(训练窗口)与切片长度要匹配:48k 下 17280 ≈ 0.36s。窗口拉到 34560(0.72s)时,短于 1.5 秒的片段装不下,会报
RuntimeError: The expanded size of the tensor (72) must match the existing size (0)(rvc\lib\algorithm\commons.py:65 slice_segments)→ 训练前先按 ≥1.5s 过滤 filelist。
- logs\<exp>\sliced_audios 里至少要有一个 wav,否则 No wav file found.(rvc\train\train.py:213)。
- 导出模型报 cannot access local variable 'embedder_model' → 缺 model_info.json;报 Unexpected UTF-8 BOM → 该 json 被写成了带 BOM。
- 导出报 'collections.OrderedDict' object has no attribute 'half' → 拿到的是整包训练 checkpoint,要取 ckpt["model"] 再交给 extract_model。
- 中文模型名在 CLI 里会因编码问题读不到索引(could not open ...index)→ 先复制成 ASCII 名再用。
实验记录(2026-11-11):只把训练窗口从 0.36s 拉到 0.72s 重训 20 轮(logs\deepsea_v6,step 8160,25 分钟,lowest 16.775@epoch17)→ 长音抖动没改善(0.134→0.123 半音),高频反而更差(>5kHz 0.024→0.013)。结论:切片长度不是长音发颤的原因。
4. 推理参数(四个旋钮)¶
| 参数 | 作用 | 取值 |
|---|---|---|
pitch |
升降调(半音) | 翻唱 +10~12;说话 0 |
index-rate |
检索融合强度 | 0.5(稳)~0.75(像但风险高) |
protect |
保护清辅音/呼吸声 | 0.33(默认);调到 0.5 实测更差(高频 0.062→0.050),别乱调 |
f0-method |
音高提取 | 高音长音用 crepe,其余 rmvpe |
升调时伴奏必须同步降调,否则串调:
rubberband=pitch=0.8908987(= −2 半音)。--f0-method harvest这个选项不存在;可选只有 crepe / rmvpe / fcpe / hybrid,而 fcpe 缺rvc\models\predictors\fcpe.pt会直接报 FileNotFoundError,hybrid 跟着崩。
5. 常驻服务(把 116 秒压到 7 秒)¶
- 每条语音冷启动要重载 torch + 模型 + 30MB 索引,占 55 秒;10 秒音频整条 116 秒。
- 解法:常驻 worker 监听
127.0.0.1:8899,一次加载反复用,空闲 600 秒自退。 - 实测:冷启 57.5s → 热调 0.7s。
6. 高音长音发颤 → 换 crepe(2026-11-11 验证)¶
现象:转换后 2:51 那种高音长音变成上下起伏的颤音,原唱是平的一条线。
定位:只截长音那 1.6 秒,去掉整体滑音趋势后,统计半音尺度上的摆动。
| 版本 | 摆动 std | p90 | 摆动主频 |
|---|---|---|---|
| 原音 | 0.04 半音 | 0.07 | — |
| rmvpe 输出 | 1.43 半音 | 2.10 | 2.7Hz |
| crepe 输出 | 0.04 半音 | 0.10 | — |
结论:不是模型在抖,是 rmvpe 在 500Hz+ 的持续长音上把音高轨迹画歪了(差两三个半音)。
处理:推理加 --f0-method crepe,其余参数不动。
代价:8 秒段 8.2s → 10.2s,整首多不到一分钟。
验证口径:取长音段 → pyin 抽 f0 → 换半音 → 减线性趋势 → 算 std 与摆动主频。std > 0.5 半音就说明 f0 跟歪了。
成品:voice-samples\成品\08_使一颗心_深澜_crepe音高版.mp3
7. 常见问题(RVC)¶
Q:破音怎么办?
A:先 check_range 看音域,超了降调(降 2–4 半音往往比补素材有效);再用 protect 0.33 + index-rate 0.5;最后才局部重推。
Q:长音发颤 / 像加了 vibrato?
A:换 --f0-method crepe(见第 6 节)。
Q:整首发闷、高频少? A:素材本身 5kHz 以上能量低(195 条抽样中位 0.0059,只有前 10% 到 0.11),模型在如实学素材亮度。靠 EQ 硬提会出人机感,优先筛亮素材。
Q:声音发虚 / 气声多?
A:素材侧去掉气声重、HNR 低的片段;推理侧降 protect、提 index-rate;后期轻压 + 一点 afftdn。
Q:听着像日语 / 不像中文? A:中文素材占比不够。加中文、砍日语重训。
Q:人机感重? A:多数是过度后期(EQ 提亮、强压缩、噪声门)叠出来的。回原声、少动。
Q:多快能出一版? A:说话模型 200 轮约 1 小时;20 轮探路版 25 分钟(100W 限功耗下)。
8. 待办(RVC 线)¶
- [ ] 清洗后的 2677 条重训 48k,对比
深澜翻唱用_v2(是否值得换) - [ ] 按 5kHz 能量筛亮素材子集,验证「发闷」能不能从素材侧解决
- [ ] 模型容量(当前宽 32 / 6 层)加宽是否带来实质提升,一次只改一个变量