ddsp-demo / DDSP-SVC /webui.py
pdjdev's picture
add ddsp-svc
85a7d2c
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()