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()