mirror of
https://github.com/RVC-Boss/GPT-SoVITS.git
synced 2026-07-23 02:45:48 +08:00
兼容 proplus-hc-dev 分支基于 6 列 .list 训练的模型,并按主分支自身流程
增加 emotion 字段(标注/推理 UI 单输入框「情绪/括注」,存 emotion 列,
保留 remark 列以兼容 proplus 6 列结构)。emotion/remark 不参与训练。
核心兼容性修复(消除 3 处硬编码拒绝 proplus 的 6 列 .list):
- 新增 tools/list_metadata.py: 6 列 .list 解析/格式化器 (parse/format_list_line)
- 1-get-text.py:129 line.split("|") 严格 4 列解包 -> parse_list_line
(proplus 同款修复,只取训练所需前 4 列,emotion/remark 静默忽略)
- subfix_webui b_load_list: 仅接受 len==4 -> 改用 parse_list_line (>=4 列)
- subfix_webui b_save_list: 写 4 列 -> 写 6 列 (保留 emotion/remark,向前向后兼容)
标注 UI (tools/subfix_webui.py):
- 每条音频新增「情绪/括注」Text 输入框 (g_emotion_list)
- b_change_index/reload_data/b_submit_change 贯通 emotion 读写
- 8 个分页事件输出列表统一追加 *g_emotion_list
推理 WebUI (inference_webui.py):
- _read_emotion_map_for_webui: 读 output/asr_opt/<exp>/*.list 的 emotion 列
- 训练样本下拉标签附加【emotion】(有则显示)
- 选中样本时同步刷新「情绪/括注」只读文本框; 应用样本一并填入
- 无 emotion 数据则文本框留空 (符合「无数据不显示」)
API (api_v2.py):
- GET /models/{name}/samples 响应增加 emotion 字段 (来自同源 .list)
向后兼容: 主分支原生 4 列 .list 全程正常; 训练 pipeline 不感知 emotion。
list_metadata/parse/emotion/round-trip 单元自测通过; py_compile 全通过。
62 lines
1.7 KiB
Python
62 lines
1.7 KiB
Python
from __future__ import annotations
|
||
|
||
from dataclasses import dataclass
|
||
|
||
|
||
@dataclass(frozen=True)
|
||
class ListLine:
|
||
"""一条 `.list` 标注行(兼容 4/5/6 列)。
|
||
|
||
列定义: wav_path|speaker_name|language|text[|emotion|remark]
|
||
训练只用前 4 列(training_fields);emotion / remark 为元数据,
|
||
不参与模型训练,用于标注与参考音频展示。
|
||
"""
|
||
|
||
wav_path: str
|
||
speaker_name: str
|
||
language: str
|
||
text: str
|
||
emotion: str = ""
|
||
remark: str = ""
|
||
|
||
@property
|
||
def training_fields(self):
|
||
return [self.wav_path, self.speaker_name, self.language, self.text]
|
||
|
||
|
||
def _clean(value):
|
||
return str(value or "").strip()
|
||
|
||
|
||
def parse_list_line(line):
|
||
"""解析一行 `.list`。列数 < 4 返回 None;emotion/remark 缺省为空串。"""
|
||
parts = str(line or "").rstrip("\r\n").split("|")
|
||
if len(parts) < 4:
|
||
return None
|
||
return ListLine(
|
||
wav_path=_clean(parts[0]),
|
||
speaker_name=_clean(parts[1]),
|
||
language=_clean(parts[2]),
|
||
text=_clean(parts[3]),
|
||
emotion=_clean(parts[4]) if len(parts) >= 5 else "",
|
||
remark=_clean(parts[5]) if len(parts) >= 6 else "",
|
||
)
|
||
|
||
|
||
def format_list_line(item):
|
||
"""把 ListLine 格式化为 6 列 `.list` 行(emotion/remark 为空也保留分隔符)。
|
||
|
||
注意:写出 6 列以保证与 proplus-hc-dev 分支互操作,主分支训练侧
|
||
(1-get-text.py)已用 parse_list_line 只消费前 4 列,多余列不影响训练。
|
||
"""
|
||
return "|".join(
|
||
[
|
||
str(item.wav_path or ""),
|
||
str(item.speaker_name or ""),
|
||
str(item.language or ""),
|
||
str(item.text or ""),
|
||
str(item.emotion or ""),
|
||
str(item.remark or ""),
|
||
]
|
||
)
|