File size: 13,417 Bytes
85a7d2c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
import gradio as gr
import os,subprocess,yaml
class WebUI:
def __init__(self) -> None:
self.info=Info()
self.opt_cfg_pth='configs/opt.yaml'
self.main_ui()
def main_ui(self):
with gr.Blocks() as ui:
gr.Markdown('## 一个便于训练和推理的DDSP-webui,每一步的说明在下面,可以自己展开看。')
with gr.Tab("训练/Training"):
gr.Markdown(self.info.general)
with gr.Accordion('预训练模型说明',open=False):
gr.Markdown(self.info.pretrain_model)
with gr.Accordion('数据集说明',open=False):
gr.Markdown(self.info.dataset)
gr.Markdown('## 生成配置文件')
with gr.Row():
self.batch_size=gr.Slider(minimum=2,maximum=60,value=24,label='Batch_size',interactive=True)
self.learning_rate=gr.Number(value=0.0005,label='学习率',info='和batch_size关系大概是0.0001:6')
self.f0_extractor=gr.Dropdown(['parselmouth', 'dio', 'harvest', 'crepe'],type='value',value='crepe',label='f0提取器种类',interactive=True)
self.sampling_rate=gr.Number(value=44100,label='采样率',info='数据集音频的采样率',interactive=True)
self.n_spk=gr.Number(value=1,label='说话人数量',interactive=True)
with gr.Row():
self.device=gr.Dropdown(['cuda','cpu'],value='cuda',label='使用设备',interactive=True)
self.num_workers=gr.Number(value=2,label='读取数据进程数',info='如果你的设备性能很好,可以设置为0',interactive=True)
self.cache_all_data=gr.Checkbox(value=True,label='启用缓存',info='将数据全部加载以加速训练',interactive=True)
self.cache_device=gr.Dropdown(['cuda','cpu'],value='cuda',type='value',label='缓存设备',info='如果你的显存比较大,设置为cuda',interactive=True)
self.bt_create_config=gr.Button(value='创建配置文件')
gr.Markdown('## 预处理')
with gr.Accordion('预训练说明',open=False):
gr.Markdown(self.info.preprocess)
with gr.Row():
self.bt_open_data_folder=gr.Button('打开数据集文件夹')
self.bt_preprocess=gr.Button('开始预处理')
gr.Markdown('## 训练')
with gr.Accordion('训练说明',open=False):
gr.Markdown(self.info.train)
with gr.Row():
self.bt_train=gr.Button('开始训练')
self.bt_visual=gr.Button('启动可视化')
gr.Markdown('启动可视化后[点击打开](http://127.0.0.1:6006)')
with gr.Tab('推理/Inference'):
with gr.Accordion('推理说明',open=False):
gr.Markdown(self.info.infer)
with gr.Row():
self.input_wav=gr.Audio(type='filepath',label='选择待转换音频')
self.choose_model=gr.Textbox('exp/model_chino.pt',label='模型路径')
with gr.Row():
self.keychange=gr.Slider(-24,24,value=0,step=1,label='变调')
self.id=gr.Number(value=1,label='说话人id')
self.enhancer_adaptive_key=gr.Number(value=0,label='增强器音区偏移',info='调高可以防止超高音(比如大于G5) 破音,但是低音效果可能会下降')
with gr.Row():
self.bt_infer=gr.Button(value='开始转换')
self.output_wav=gr.Audio(type='filepath',label='输出音频')
self.bt_create_config.click(fn=self.create_config)
self.bt_open_data_folder.click(fn=self.openfolder)
self.bt_preprocess.click(fn=self.preprocess)
self.bt_train.click(fn=self.training)
self.bt_visual.click(fn=self.visualize)
self.bt_infer.click(fn=self.inference,inputs=[self.input_wav,self.choose_model,self.keychange,self.id,self.enhancer_adaptive_key],outputs=self.output_wav)
ui.launch(inbrowser=True,server_port=7858)
def openfolder(self):
try:
os.startfile('data')
except:
print('Fail to open folder!')
def create_config(self):
with open('configs/combsub.yaml','r',encoding='utf-8') as f:
cfg=yaml.load(f.read(),Loader=yaml.FullLoader)
cfg['data']['f0_extractor']=str(self.f0_extractor.value)
cfg['data']['sampling_rate']=int(self.sampling_rate.value)
cfg['train']['batch_size']=int(self.batch_size.value)
cfg['device']=str(self.device.value)
cfg['train']['num_workers']=int(self.num_workers.value)
cfg['train']['cache_all_data']=str(self.cache_all_data.value)
cfg['train']['cache_device']=str(self.cache_device.value)
cfg['train']['lr']=int(self.learning_rate.value)
print('配置文件信息:'+str(cfg))
with open(self.opt_cfg_pth,'w',encoding='utf-8') as f:
yaml.dump(cfg,f)
print('成功生成配置文件')
def preprocess(self):
preprocessing_process=subprocess.Popen('python -u preprocess.py -c '+self.opt_cfg_pth,stdout=subprocess.PIPE)
while preprocessing_process.poll() is None:
output=preprocessing_process.stdout.readline().decode('utf-8')
print(output)
print('预处理完成')
def training(self):
train_process=subprocess.Popen('python -u train.py -c '+self.opt_cfg_pth,stdout=subprocess.PIPE)
while train_process.poll() is None:
output=train_process.stdout.readline().decode('utf-8')
print(output)
def visualize(self):
tb_process=subprocess.Popen('tensorboard --logdir=exp --port=6006',stdout=subprocess.PIPE)
while tb_process.poll() is None:
output=tb_process.stdout.readline().decode('utf-8')
print(output)
def inference(self,input_wav:str,model:str,keychange,id,enhancer_adaptive_key):
print(input_wav,model)
output_wav='samples/'+ input_wav.replace('\\','/').split('/')[-1]
cmd='python -u main.py -i '+input_wav+' -m '+model+' -o '+output_wav+' -k '+str(int(keychange))+' -id '+str(int(id))+' -e true -eak '+str(int(enhancer_adaptive_key))
infer_process=subprocess.Popen(cmd,stdout=subprocess.PIPE)
while infer_process.poll() is None:
output=infer_process.stdout.readline().decode('utf-8')
print(output)
print('推理完成')
return output_wav
class Info:
def __init__(self) -> None:
self.general='''
### 不看也没事,大致就是
1.设置好配置之后点击创建配置文件
2.点击‘打开数据集文件夹’,把数据集选个十个塞到data\\train\\val目录下面,剩下的音频全塞到data\\train\\audio下面
3.点击‘开始预处理’等待执行完毕
4.点击‘开始训练’和‘启动可视化’然后点击右侧链接
'''
self.pretrain_model="""
- **(必要操作)** 下载预训练 [**HubertSoft**](https://github.com/bshall/hubert/releases/download/v0.1/hubert-soft-0d54a1f4.pt) 编码器并将其放到 `pretrain/hubert` 文件夹。
- 更新:现在支持 ContentVec 编码器了。你可以下载预训练 [ContentVec](https://ibm.ent.box.com/s/z1wgl1stco8ffooyatzdwsqn2psd9lrr) 编码器替代 HubertSoft 编码器并修改配置文件以使用它。
- 从 [DiffSinger 社区声码器项目](https://openvpi.github.io/vocoders) 下载基于预训练声码器的增强器,并解压至 `pretrain/` 文件夹。
- 注意:你应当下载名称中带有`nsf_hifigan`的压缩文件,而非`nsf_hifigan_finetune`。
"""
self.dataset="""
### 1. 配置训练数据集和验证数据集
#### 1.1 手动配置:
将所有的训练集数据 (.wav 格式音频切片) 放到 `data/train/audio`。
将所有的验证集数据 (.wav 格式音频切片) 放到 `data/val/audio`。
#### 1.2 程序随机选择(**多人物时不可使用**):
运行`python draw.py`,程序将帮助你挑选验证集数据(可以调整 `draw.py` 中的参数修改抽取文件的数量等参数)。
#### 1.3文件夹结构目录展示:
- 单人物目录结构:
```
data
├─ train
│ ├─ audio
│ │ ├─ aaa.wav
│ │ ├─ bbb.wav
│ │ └─ ....wav
│ └─ val
│ │ ├─ eee.wav
│ │ ├─ fff.wav
│ │ └─ ....wav
```
- 多人物目录结构:
```
data
├─ train
│ ├─ audio
│ │ ├─ 1
│ │ │ ├─ aaa.wav
│ │ │ ├─ bbb.wav
│ │ │ └─ ....wav
│ │ ├─ 2
│ │ │ ├─ ccc.wav
│ │ │ ├─ ddd.wav
│ │ │ └─ ....wav
│ │ └─ ...
│ └─ val
│ │ ├─ 1
│ │ │ ├─ eee.wav
│ │ │ ├─ fff.wav
│ │ │ └─ ....wav
│ │ ├─ 2
│ │ │ ├─ ggg.wav
│ │ │ ├─ hhh.wav
│ │ │ └─ ....wav
│ │ └─ ...
```
"""
self.preprocess='''
您可以在预处理之前修改配置文件 `config/<model_name>.yaml`,默认配置适用于GTX-1660 显卡训练 44.1khz 高采样率合成器。
### 备注:
1. 请保持所有音频切片的采样率与 yaml 配置文件中的采样率一致!如果不一致,程序可以跑,但训练过程中的重新采样将非常缓慢。(可选:使用Adobe Audition™的响度匹配功能可以一次性完成重采样修改声道和响度匹配。)
2. 训练数据集的音频切片总数建议为约 1000 个,另外长音频切成小段可以加快训练速度,但所有音频切片的时长不应少于 2 秒。如果音频切片太多,则需要较大的内存,配置文件中将 `cache_all_data` 选项设置为 false 可以解决此问题。
3. 验证集的音频切片总数建议为 10 个左右,不要放太多,不然验证过程会很慢。
4. 如果您的数据集质量不是很高,请在配置文件中将 'f0_extractor' 设为 'crepe'。crepe 算法的抗噪性最好,但代价是会极大增加数据预处理所需的时间。
5. 配置文件中的 ‘n_spk’ 参数将控制是否训练多说话人模型。如果您要训练**多说话人**模型,为了对说话人进行编号,所有音频文件夹的名称必须是**不大于 ‘n_spk’ 的正整数**。
'''
self.train='''
## 训练
### 1. 不使用预训练数据进行训练:
```bash
# 以训练 combsub 模型为例
python train.py -c configs/combsub.yaml
```
1. 训练其他模型方法类似。
2. 可以随时中止训练,然后运行相同的命令来继续训练。
3. 微调 (finetune):在中止训练后,重新预处理新数据集或更改训练参数(batchsize、lr等),然后运行相同的命令。
### 2. 使用预训练数据(底模)进行训练:
1. **使用预训练模型请修改配置文件中的 'n_spk' 参数为 '2' ,同时配置`train`目录结构为多人物目录,不论你是否训练多说话人模型。**
2. **如果你要训练一个更多说话人的模型,就不要下载预训练模型了。**
3. 欢迎PR训练的多人底模 (请使用授权同意开源的数据集进行训练)。
4. 从[**这里**](https://github.com/yxlllc/DDSP-SVC/releases/download/2.0/opencpop+kiritan.zip)下载预训练模型,并将`model_300000.pt`解压到`.\exp\combsub-test\`中
5. 同不使用预训练数据进行训练一样,启动训练。
'''
self.visualize='''
## 可视化
```bash
# 使用tensorboard检查训练状态
tensorboard --logdir=exp
```
第一次验证 (validation) 后,在 TensorBoard 中可以看到合成后的测试音频。
注:TensorBoard 中的测试音频是 DDSP-SVC 模型的原始输出,并未通过增强器增强。
'''
self.infer='''
## 非实时变声
1. (**推荐**)使用预训练声码器增强 DDSP 的输出结果:
```bash
# 默认 enhancer_adaptive_key = 0 正常音域范围内将有更高的音质
# 设置 enhancer_adaptive_key > 0 可将增强器适配于更高的音域
python main.py -i <input.wav> -m <model_file.pt> -o <output.wav> -k <keychange (semitones)> -id <speaker_id> -e true -eak <enhancer_adaptive_key (semitones)>
```
2. DDSP 的原始输出结果:
```bash
# 速度快,但音质相对较低(像您在tensorboard里听到的那样)
python main.py -i <input.wav> -m <model_file.pt> -o <output.wav> -k <keychange (semitones)> -e false -id <speaker_id>
```
3. 关于 f0 提取器、响应阈值及其他参数,参见:
```bash
python main.py -h
```
4. 如果要使用混合说话人(捏音色)功能,增添 “-mix” 选项来设计音色,下面是个例子:
```bash
# 将1号说话人和2号说话人的音色按照0.5:0.5的比例混合
python main.py -i <input.wav> -m <model_file.pt> -o <output.wav> -k <keychange (semitones)> -mix "{1:0.5, 2:0.5}" -e true -eak 0
```
'''
webui=WebUI() |