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/.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 -m -o -k -id -e true -eak ``` 2. DDSP 的原始输出结果: ```bash # 速度快,但音质相对较低(像您在tensorboard里听到的那样) python main.py -i -m -o -k -e false -id ``` 3. 关于 f0 提取器、响应阈值及其他参数,参见: ```bash python main.py -h ``` 4. 如果要使用混合说话人(捏音色)功能,增添 “-mix” 选项来设计音色,下面是个例子: ```bash # 将1号说话人和2号说话人的音色按照0.5:0.5的比例混合 python main.py -i -m -o -k -mix "{1:0.5, 2:0.5}" -e true -eak 0 ``` ''' webui=WebUI()