YUNSUN7 commited on
Commit
e00a6f7
·
1 Parent(s): 6eb7cc3

Upload 29 files

Browse files
Dockerfile ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM python:3.10-bullseye
4
+
5
+ EXPOSE 7865
6
+
7
+ WORKDIR /app
8
+
9
+ COPY . .
10
+
11
+ RUN apt update && apt install -y -qq ffmpeg aria2 && apt clean
12
+
13
+ RUN pip3 install --no-cache-dir -r requirements.txt
14
+
15
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d assets/pretrained_v2/ -o D40k.pth
16
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d assets/pretrained_v2/ -o G40k.pth
17
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -d assets/pretrained_v2/ -o f0D40k.pth
18
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -d assets/pretrained_v2/ -o f0G40k.pth
19
+
20
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth -d assets/uvr5_weights/ -o HP2-人声vocals+非人声instrumentals.pth
21
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth -d assets/uvr5_weights/ -o HP5-主旋律人声vocals+其他instrumentals.pth
22
+
23
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d assets/hubert -o hubert_base.pt
24
+
25
+ RUN aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d assets/hubert -o rmvpe.pt
26
+
27
+ VOLUME [ "/app/weights", "/app/opt" ]
28
+
29
+ CMD ["python3", "infer-web.py"]
GUI.py ADDED
@@ -0,0 +1,1410 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ import datetime, subprocess
3
+ from mega import Mega
4
+ now_dir = os.getcwd()
5
+ sys.path.append(now_dir)
6
+ import logging
7
+ import shutil
8
+ import threading
9
+ import traceback
10
+ import warnings
11
+ from random import shuffle
12
+ from subprocess import Popen
13
+ from time import sleep
14
+ import json
15
+ import pathlib
16
+
17
+ import fairseq
18
+ import faiss
19
+ import gradio as gr
20
+ import numpy as np
21
+ import torch
22
+ from dotenv import load_dotenv
23
+ from sklearn.cluster import MiniBatchKMeans
24
+
25
+ from configs.config import Config
26
+ from i18n.i18n import I18nAuto
27
+ from infer.lib.train.process_ckpt import (
28
+ change_info,
29
+ extract_small_model,
30
+ merge,
31
+ show_info,
32
+ )
33
+ from infer.modules.uvr5.modules import uvr
34
+ from infer.modules.vc.modules import VC
35
+ logging.getLogger("numba").setLevel(logging.WARNING)
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ tmp = os.path.join(now_dir, "TEMP")
40
+ shutil.rmtree(tmp, ignore_errors=True)
41
+ shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)
42
+ shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)
43
+ os.makedirs(tmp, exist_ok=True)
44
+ os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)
45
+ os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)
46
+ os.environ["TEMP"] = tmp
47
+ warnings.filterwarnings("ignore")
48
+ torch.manual_seed(114514)
49
+
50
+
51
+ load_dotenv()
52
+ config = Config()
53
+ vc = VC(config)
54
+
55
+ if config.dml == True:
56
+
57
+ def forward_dml(ctx, x, scale):
58
+ ctx.scale = scale
59
+ res = x.clone().detach()
60
+ return res
61
+
62
+ fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml
63
+ i18n = I18nAuto()
64
+ logger.info(i18n)
65
+ # 判断是否有能用来训练和加速推理的N卡
66
+ ngpu = torch.cuda.device_count()
67
+ gpu_infos = []
68
+ mem = []
69
+ if_gpu_ok = False
70
+
71
+ if torch.cuda.is_available() or ngpu != 0:
72
+ for i in range(ngpu):
73
+ gpu_name = torch.cuda.get_device_name(i)
74
+ if any(
75
+ value in gpu_name.upper()
76
+ for value in [
77
+ "10",
78
+ "16",
79
+ "20",
80
+ "30",
81
+ "40",
82
+ "A2",
83
+ "A3",
84
+ "A4",
85
+ "P4",
86
+ "A50",
87
+ "500",
88
+ "A60",
89
+ "70",
90
+ "80",
91
+ "90",
92
+ "M4",
93
+ "T4",
94
+ "TITAN",
95
+ ]
96
+ ):
97
+ # A10#A100#V100#A40#P40#M40#K80#A4500
98
+ if_gpu_ok = True # 至少有一张能用的N卡
99
+ gpu_infos.append("%s\t%s" % (i, gpu_name))
100
+ mem.append(
101
+ int(
102
+ torch.cuda.get_device_properties(i).total_memory
103
+ / 1024
104
+ / 1024
105
+ / 1024
106
+ + 0.4
107
+ )
108
+ )
109
+ if if_gpu_ok and len(gpu_infos) > 0:
110
+ gpu_info = "\n".join(gpu_infos)
111
+ default_batch_size = min(mem) // 2
112
+ else:
113
+ gpu_info = i18n("很遗憾您这没有能用的显卡来支持您训练")
114
+ default_batch_size = 1
115
+ gpus = "-".join([i[0] for i in gpu_infos])
116
+
117
+
118
+ class ToolButton(gr.Button, gr.components.FormComponent):
119
+ """Small button with single emoji as text, fits inside gradio forms"""
120
+
121
+ def __init__(self, **kwargs):
122
+ super().__init__(variant="tool", **kwargs)
123
+
124
+ def get_block_name(self):
125
+ return "button"
126
+
127
+
128
+ weight_root = os.getenv("weight_root")
129
+ weight_uvr5_root = os.getenv("weight_uvr5_root")
130
+ index_root = os.getenv("index_root")
131
+
132
+ names = []
133
+ for name in os.listdir(weight_root):
134
+ if name.endswith(".pth"):
135
+ names.append(name)
136
+ index_paths = []
137
+ for root, dirs, files in os.walk(index_root, topdown=False):
138
+ for name in files:
139
+ if name.endswith(".index") and "trained" not in name:
140
+ index_paths.append("%s/%s" % (root, name))
141
+ uvr5_names = []
142
+ for name in os.listdir(weight_uvr5_root):
143
+ if name.endswith(".pth") or "onnx" in name:
144
+ uvr5_names.append(name.replace(".pth", ""))
145
+
146
+
147
+ def change_choices():
148
+ names = []
149
+ for name in os.listdir(weight_root):
150
+ if name.endswith(".pth"):
151
+ names.append(name)
152
+ index_paths = []
153
+ for root, dirs, files in os.walk(index_root, topdown=False):
154
+ for name in files:
155
+ if name.endswith(".index") and "trained" not in name:
156
+ index_paths.append("%s/%s" % (root, name))
157
+ audio_files=[]
158
+ for filename in os.listdir("./audios"):
159
+ if filename.endswith(('.wav','.mp3','.ogg')):
160
+ audio_files.append('./audios/'+filename)
161
+ return {"choices": sorted(names), "__type__": "update"}, {
162
+ "choices": sorted(index_paths),
163
+ "__type__": "update",
164
+ }, {"choices": sorted(audio_files), "__type__": "update"}
165
+
166
+ def clean():
167
+ return {"value": "", "__type__": "update"}
168
+
169
+
170
+ def export_onnx():
171
+ from infer.modules.onnx.export import export_onnx as eo
172
+
173
+ eo()
174
+
175
+
176
+ sr_dict = {
177
+ "32k": 32000,
178
+ "40k": 40000,
179
+ "48k": 48000,
180
+ }
181
+
182
+
183
+ def if_done(done, p):
184
+ while 1:
185
+ if p.poll() is None:
186
+ sleep(0.5)
187
+ else:
188
+ break
189
+ done[0] = True
190
+
191
+
192
+ def if_done_multi(done, ps):
193
+ while 1:
194
+ # poll==None代表进程未结束
195
+ # 只要有一个进程未结束都不停
196
+ flag = 1
197
+ for p in ps:
198
+ if p.poll() is None:
199
+ flag = 0
200
+ sleep(0.5)
201
+ break
202
+ if flag == 1:
203
+ break
204
+ done[0] = True
205
+
206
+
207
+ def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):
208
+ sr = sr_dict[sr]
209
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
210
+ f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")
211
+ f.close()
212
+ per = 3.0 if config.is_half else 3.7
213
+ cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (
214
+ config.python_cmd,
215
+ trainset_dir,
216
+ sr,
217
+ n_p,
218
+ now_dir,
219
+ exp_dir,
220
+ config.noparallel,
221
+ per,
222
+ )
223
+ logger.info(cmd)
224
+ p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir
225
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
226
+ done = [False]
227
+ threading.Thread(
228
+ target=if_done,
229
+ args=(
230
+ done,
231
+ p,
232
+ ),
233
+ ).start()
234
+ while 1:
235
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
236
+ yield (f.read())
237
+ sleep(1)
238
+ if done[0]:
239
+ break
240
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
241
+ log = f.read()
242
+ logger.info(log)
243
+ yield log
244
+
245
+
246
+ # but2.click(extract_f0,[gpus6,np7,f0method8,if_f0_3,trainset_dir4],[info2])
247
+ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, gpus_rmvpe):
248
+ gpus = gpus.split("-")
249
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
250
+ f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")
251
+ f.close()
252
+ if if_f0:
253
+ if f0method != "rmvpe_gpu":
254
+ cmd = (
255
+ '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'
256
+ % (
257
+ config.python_cmd,
258
+ now_dir,
259
+ exp_dir,
260
+ n_p,
261
+ f0method,
262
+ )
263
+ )
264
+ logger.info(cmd)
265
+ p = Popen(
266
+ cmd, shell=True, cwd=now_dir
267
+ ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE
268
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
269
+ done = [False]
270
+ threading.Thread(
271
+ target=if_done,
272
+ args=(
273
+ done,
274
+ p,
275
+ ),
276
+ ).start()
277
+ else:
278
+ if gpus_rmvpe != "-":
279
+ gpus_rmvpe = gpus_rmvpe.split("-")
280
+ leng = len(gpus_rmvpe)
281
+ ps = []
282
+ for idx, n_g in enumerate(gpus_rmvpe):
283
+ cmd = (
284
+ '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '
285
+ % (
286
+ config.python_cmd,
287
+ leng,
288
+ idx,
289
+ n_g,
290
+ now_dir,
291
+ exp_dir,
292
+ config.is_half,
293
+ )
294
+ )
295
+ logger.info(cmd)
296
+ p = Popen(
297
+ cmd, shell=True, cwd=now_dir
298
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
299
+ ps.append(p)
300
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
301
+ done = [False]
302
+ threading.Thread(
303
+ target=if_done_multi, #
304
+ args=(
305
+ done,
306
+ ps,
307
+ ),
308
+ ).start()
309
+ else:
310
+ cmd = (
311
+ config.python_cmd
312
+ + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '
313
+ % (
314
+ now_dir,
315
+ exp_dir,
316
+ )
317
+ )
318
+ logger.info(cmd)
319
+ p = Popen(
320
+ cmd, shell=True, cwd=now_dir
321
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
322
+ p.wait()
323
+ done = [True]
324
+ while 1:
325
+ with open(
326
+ "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"
327
+ ) as f:
328
+ yield (f.read())
329
+ sleep(1)
330
+ if done[0]:
331
+ break
332
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
333
+ log = f.read()
334
+ logger.info(log)
335
+ yield log
336
+ ####对不同part分别开多进程
337
+ """
338
+ n_part=int(sys.argv[1])
339
+ i_part=int(sys.argv[2])
340
+ i_gpu=sys.argv[3]
341
+ exp_dir=sys.argv[4]
342
+ os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)
343
+ """
344
+ leng = len(gpus)
345
+ ps = []
346
+ for idx, n_g in enumerate(gpus):
347
+ cmd = (
348
+ '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'
349
+ % (
350
+ config.python_cmd,
351
+ config.device,
352
+ leng,
353
+ idx,
354
+ n_g,
355
+ now_dir,
356
+ exp_dir,
357
+ version19,
358
+ )
359
+ )
360
+ logger.info(cmd)
361
+ p = Popen(
362
+ cmd, shell=True, cwd=now_dir
363
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
364
+ ps.append(p)
365
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
366
+ done = [False]
367
+ threading.Thread(
368
+ target=if_done_multi,
369
+ args=(
370
+ done,
371
+ ps,
372
+ ),
373
+ ).start()
374
+ while 1:
375
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
376
+ yield (f.read())
377
+ sleep(1)
378
+ if done[0]:
379
+ break
380
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
381
+ log = f.read()
382
+ logger.info(log)
383
+ yield log
384
+
385
+
386
+ def get_pretrained_models(path_str, f0_str, sr2):
387
+ if_pretrained_generator_exist = os.access(
388
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
389
+ )
390
+ if_pretrained_discriminator_exist = os.access(
391
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
392
+ )
393
+ if not if_pretrained_generator_exist:
394
+ logger.warn(
395
+ "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",
396
+ path_str,
397
+ f0_str,
398
+ sr2,
399
+ )
400
+ if not if_pretrained_discriminator_exist:
401
+ logger.warn(
402
+ "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",
403
+ path_str,
404
+ f0_str,
405
+ sr2,
406
+ )
407
+ return (
408
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
409
+ if if_pretrained_generator_exist
410
+ else "",
411
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
412
+ if if_pretrained_discriminator_exist
413
+ else "",
414
+ )
415
+
416
+
417
+ def change_sr2(sr2, if_f0_3, version19):
418
+ path_str = "" if version19 == "v1" else "_v2"
419
+ f0_str = "f0" if if_f0_3 else ""
420
+ return get_pretrained_models(path_str, f0_str, sr2)
421
+
422
+
423
+ def change_version19(sr2, if_f0_3, version19):
424
+ path_str = "" if version19 == "v1" else "_v2"
425
+ if sr2 == "32k" and version19 == "v1":
426
+ sr2 = "40k"
427
+ to_return_sr2 = (
428
+ {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}
429
+ if version19 == "v1"
430
+ else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}
431
+ )
432
+ f0_str = "f0" if if_f0_3 else ""
433
+ return (
434
+ *get_pretrained_models(path_str, f0_str, sr2),
435
+ to_return_sr2,
436
+ )
437
+
438
+
439
+ def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15
440
+ path_str = "" if version19 == "v1" else "_v2"
441
+ return (
442
+ {"visible": if_f0_3, "__type__": "update"},
443
+ *get_pretrained_models(path_str, "f0", sr2),
444
+ )
445
+
446
+
447
+ # but3.click(click_train,[exp_dir1,sr2,if_f0_3,save_epoch10,total_epoch11,batch_size12,if_save_latest13,pretrained_G14,pretrained_D15,gpus16])
448
+ def click_train(
449
+ exp_dir1,
450
+ sr2,
451
+ if_f0_3,
452
+ spk_id5,
453
+ save_epoch10,
454
+ total_epoch11,
455
+ batch_size12,
456
+ if_save_latest13,
457
+ pretrained_G14,
458
+ pretrained_D15,
459
+ gpus16,
460
+ if_cache_gpu17,
461
+ if_save_every_weights18,
462
+ version19,
463
+ ):
464
+ # 生成filelist
465
+ exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
466
+ os.makedirs(exp_dir, exist_ok=True)
467
+ gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)
468
+ feature_dir = (
469
+ "%s/3_feature256" % (exp_dir)
470
+ if version19 == "v1"
471
+ else "%s/3_feature768" % (exp_dir)
472
+ )
473
+ if if_f0_3:
474
+ f0_dir = "%s/2a_f0" % (exp_dir)
475
+ f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)
476
+ names = (
477
+ set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])
478
+ & set([name.split(".")[0] for name in os.listdir(feature_dir)])
479
+ & set([name.split(".")[0] for name in os.listdir(f0_dir)])
480
+ & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])
481
+ )
482
+ else:
483
+ names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(
484
+ [name.split(".")[0] for name in os.listdir(feature_dir)]
485
+ )
486
+ opt = []
487
+ for name in names:
488
+ if if_f0_3:
489
+ opt.append(
490
+ "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"
491
+ % (
492
+ gt_wavs_dir.replace("\\", "\\\\"),
493
+ name,
494
+ feature_dir.replace("\\", "\\\\"),
495
+ name,
496
+ f0_dir.replace("\\", "\\\\"),
497
+ name,
498
+ f0nsf_dir.replace("\\", "\\\\"),
499
+ name,
500
+ spk_id5,
501
+ )
502
+ )
503
+ else:
504
+ opt.append(
505
+ "%s/%s.wav|%s/%s.npy|%s"
506
+ % (
507
+ gt_wavs_dir.replace("\\", "\\\\"),
508
+ name,
509
+ feature_dir.replace("\\", "\\\\"),
510
+ name,
511
+ spk_id5,
512
+ )
513
+ )
514
+ fea_dim = 256 if version19 == "v1" else 768
515
+ if if_f0_3:
516
+ for _ in range(2):
517
+ opt.append(
518
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s/logs/mute/2a_f0/mute.wav.npy|%s/logs/mute/2b-f0nsf/mute.wav.npy|%s"
519
+ % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)
520
+ )
521
+ else:
522
+ for _ in range(2):
523
+ opt.append(
524
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"
525
+ % (now_dir, sr2, now_dir, fea_dim, spk_id5)
526
+ )
527
+ shuffle(opt)
528
+ with open("%s/filelist.txt" % exp_dir, "w") as f:
529
+ f.write("\n".join(opt))
530
+ logger.debug("Write filelist done")
531
+ # 生成config#无需生成config
532
+ # cmd = python_cmd + " train_nsf_sim_cache_sid_load_pretrain.py -e mi-test -sr 40k -f0 1 -bs 4 -g 0 -te 10 -se 5 -pg pretrained/f0G40k.pth -pd pretrained/f0D40k.pth -l 1 -c 0"
533
+ logger.info("Use gpus: %s", str(gpus16))
534
+ if pretrained_G14 == "":
535
+ logger.info("No pretrained Generator")
536
+ if pretrained_D15 == "":
537
+ logger.info("No pretrained Discriminator")
538
+ if version19 == "v1" or sr2 == "40k":
539
+ config_path = "v1/%s.json" % sr2
540
+ else:
541
+ config_path = "v2/%s.json" % sr2
542
+ config_save_path = os.path.join(exp_dir, "config.json")
543
+ if not pathlib.Path(config_save_path).exists():
544
+ with open(config_save_path, "w", encoding="utf-8") as f:
545
+ json.dump(
546
+ config.json_config[config_path],
547
+ f,
548
+ ensure_ascii=False,
549
+ indent=4,
550
+ sort_keys=True,
551
+ )
552
+ f.write("\n")
553
+ if gpus16:
554
+ cmd = (
555
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
556
+ % (
557
+ config.python_cmd,
558
+ exp_dir1,
559
+ sr2,
560
+ 1 if if_f0_3 else 0,
561
+ batch_size12,
562
+ gpus16,
563
+ total_epoch11,
564
+ save_epoch10,
565
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
566
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
567
+ 1 if if_save_latest13 == i18n("是") else 0,
568
+ 1 if if_cache_gpu17 == i18n("是") else 0,
569
+ 1 if if_save_every_weights18 == i18n("是") else 0,
570
+ version19,
571
+ )
572
+ )
573
+ else:
574
+ cmd = (
575
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
576
+ % (
577
+ config.python_cmd,
578
+ exp_dir1,
579
+ sr2,
580
+ 1 if if_f0_3 else 0,
581
+ batch_size12,
582
+ total_epoch11,
583
+ save_epoch10,
584
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
585
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
586
+ 1 if if_save_latest13 == i18n("是") else 0,
587
+ 1 if if_cache_gpu17 == i18n("是") else 0,
588
+ 1 if if_save_every_weights18 == i18n("是") else 0,
589
+ version19,
590
+ )
591
+ )
592
+ logger.info(cmd)
593
+ p = Popen(cmd, shell=True, cwd=now_dir)
594
+ p.wait()
595
+ return "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"
596
+
597
+
598
+ # but4.click(train_index, [exp_dir1], info3)
599
+ def train_index(exp_dir1, version19):
600
+ # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
601
+ exp_dir = "logs/%s" % (exp_dir1)
602
+ os.makedirs(exp_dir, exist_ok=True)
603
+ feature_dir = (
604
+ "%s/3_feature256" % (exp_dir)
605
+ if version19 == "v1"
606
+ else "%s/3_feature768" % (exp_dir)
607
+ )
608
+ if not os.path.exists(feature_dir):
609
+ return "请先进行特征提取!"
610
+ listdir_res = list(os.listdir(feature_dir))
611
+ if len(listdir_res) == 0:
612
+ return "请先进行特征提取!"
613
+ infos = []
614
+ npys = []
615
+ for name in sorted(listdir_res):
616
+ phone = np.load("%s/%s" % (feature_dir, name))
617
+ npys.append(phone)
618
+ big_npy = np.concatenate(npys, 0)
619
+ big_npy_idx = np.arange(big_npy.shape[0])
620
+ np.random.shuffle(big_npy_idx)
621
+ big_npy = big_npy[big_npy_idx]
622
+ if big_npy.shape[0] > 2e5:
623
+ infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
624
+ yield "\n".join(infos)
625
+ try:
626
+ big_npy = (
627
+ MiniBatchKMeans(
628
+ n_clusters=10000,
629
+ verbose=True,
630
+ batch_size=256 * config.n_cpu,
631
+ compute_labels=False,
632
+ init="random",
633
+ )
634
+ .fit(big_npy)
635
+ .cluster_centers_
636
+ )
637
+ except:
638
+ info = traceback.format_exc()
639
+ logger.info(info)
640
+ infos.append(info)
641
+ yield "\n".join(infos)
642
+
643
+ np.save("%s/total_fea.npy" % exp_dir, big_npy)
644
+ n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
645
+ infos.append("%s,%s" % (big_npy.shape, n_ivf))
646
+ yield "\n".join(infos)
647
+ index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
648
+ # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)
649
+ infos.append("training")
650
+ yield "\n".join(infos)
651
+ index_ivf = faiss.extract_index_ivf(index) #
652
+ index_ivf.nprobe = 1
653
+ index.train(big_npy)
654
+ faiss.write_index(
655
+ index,
656
+ "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"
657
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
658
+ )
659
+
660
+ infos.append("adding")
661
+ yield "\n".join(infos)
662
+ batch_size_add = 8192
663
+ for i in range(0, big_npy.shape[0], batch_size_add):
664
+ index.add(big_npy[i : i + batch_size_add])
665
+ faiss.write_index(
666
+ index,
667
+ "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"
668
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
669
+ )
670
+ infos.append(
671
+ "成功构建索引,added_IVF%s_Flat_nprobe_%s_%s_%s.index"
672
+ % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
673
+ )
674
+ # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))
675
+ # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))
676
+ yield "\n".join(infos)
677
+
678
+
679
+ # but5.click(train1key, [exp_dir1, sr2, if_f0_3, trainset_dir4, spk_id5, gpus6, np7, f0method8, save_epoch10, total_epoch11, batch_size12, if_save_latest13, pretrained_G14, pretrained_D15, gpus16, if_cache_gpu17], info3)
680
+ def train1key(
681
+ exp_dir1,
682
+ sr2,
683
+ if_f0_3,
684
+ trainset_dir4,
685
+ spk_id5,
686
+ np7,
687
+ f0method8,
688
+ save_epoch10,
689
+ total_epoch11,
690
+ batch_size12,
691
+ if_save_latest13,
692
+ pretrained_G14,
693
+ pretrained_D15,
694
+ gpus16,
695
+ if_cache_gpu17,
696
+ if_save_every_weights18,
697
+ version19,
698
+ gpus_rmvpe,
699
+ ):
700
+ infos = []
701
+
702
+ def get_info_str(strr):
703
+ infos.append(strr)
704
+ return "\n".join(infos)
705
+
706
+ ####### step1:处理数据
707
+ yield get_info_str(i18n("step1:正在处理数据"))
708
+ [get_info_str(_) for _ in preprocess_dataset(trainset_dir4, exp_dir1, sr2, np7)]
709
+
710
+ ####### step2a:提取音高
711
+ yield get_info_str(i18n("step2:正在提取音高&正在提取特征"))
712
+ [
713
+ get_info_str(_)
714
+ for _ in extract_f0_feature(
715
+ gpus16, np7, f0method8, if_f0_3, exp_dir1, version19, gpus_rmvpe
716
+ )
717
+ ]
718
+
719
+ ####### step3a:训练模型
720
+ yield get_info_str(i18n("step3a:正在训练模型"))
721
+ click_train(
722
+ exp_dir1,
723
+ sr2,
724
+ if_f0_3,
725
+ spk_id5,
726
+ save_epoch10,
727
+ total_epoch11,
728
+ batch_size12,
729
+ if_save_latest13,
730
+ pretrained_G14,
731
+ pretrained_D15,
732
+ gpus16,
733
+ if_cache_gpu17,
734
+ if_save_every_weights18,
735
+ version19,
736
+ )
737
+ yield get_info_str(i18n("训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"))
738
+
739
+ ####### step3b:训练索引
740
+ [get_info_str(_) for _ in train_index(exp_dir1, version19)]
741
+ yield get_info_str(i18n("全流程结束!"))
742
+
743
+
744
+ # ckpt_path2.change(change_info_,[ckpt_path2],[sr__,if_f0__])
745
+ def change_info_(ckpt_path):
746
+ if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):
747
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
748
+ try:
749
+ with open(
750
+ ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"
751
+ ) as f:
752
+ info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])
753
+ sr, f0 = info["sample_rate"], info["if_f0"]
754
+ version = "v2" if ("version" in info and info["version"] == "v2") else "v1"
755
+ return sr, str(f0), version
756
+ except:
757
+ traceback.print_exc()
758
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
759
+
760
+
761
+ F0GPUVisible = config.dml == False
762
+
763
+
764
+ def change_f0_method(f0method8):
765
+ if f0method8 == "rmvpe_gpu":
766
+ visible = F0GPUVisible
767
+ else:
768
+ visible = False
769
+ return {"visible": visible, "__type__": "update"}
770
+
771
+ def find_model():
772
+ if len(names) > 0:
773
+ vc.get_vc(sorted(names)[0],None,None)
774
+ return sorted(names)[0]
775
+ else:
776
+ try:
777
+ gr.Info("Do not forget to choose a model.")
778
+ except:
779
+ pass
780
+ return ''
781
+
782
+ def find_audios(index=False):
783
+ audio_files=[]
784
+ if not os.path.exists('./audios'): os.mkdir("./audios")
785
+ for filename in os.listdir("./audios"):
786
+ if filename.endswith(('.wav','.mp3','.ogg')):
787
+ audio_files.append("./audios/"+filename)
788
+ if index:
789
+ if len(audio_files) > 0: return sorted(audio_files)[0]
790
+ else: return ""
791
+ elif len(audio_files) > 0: return sorted(audio_files)
792
+ else: return []
793
+
794
+ def get_index():
795
+ if find_model() != '':
796
+ chosen_model=sorted(names)[0].split(".")[0]
797
+ logs_path="./logs/"+chosen_model
798
+ if os.path.exists(logs_path):
799
+ for file in os.listdir(logs_path):
800
+ if file.endswith(".index"):
801
+ return os.path.join(logs_path, file)
802
+ return ''
803
+ else:
804
+ return ''
805
+
806
+ def get_indexes():
807
+ indexes_list=[]
808
+ for dirpath, dirnames, filenames in os.walk("./logs/"):
809
+ for filename in filenames:
810
+ if filename.endswith(".index"):
811
+ indexes_list.append(os.path.join(dirpath,filename))
812
+ if len(indexes_list) > 0:
813
+ return indexes_list
814
+ else:
815
+ return ''
816
+
817
+ def save_wav(file):
818
+ try:
819
+ file_path=file.name
820
+ shutil.move(file_path,'./audios')
821
+ return './audios/'+os.path.basename(file_path)
822
+ except AttributeError:
823
+ try:
824
+ new_name = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")+'.wav'
825
+ new_path='./audios/'+new_name
826
+ shutil.move(file,new_path)
827
+ return new_path
828
+ except TypeError:
829
+ return None
830
+
831
+ def download_from_url(url, model):
832
+ if url == '':
833
+ return "URL cannot be left empty."
834
+ if model =='':
835
+ return "You need to name your model. For example: My-Model"
836
+ url = url.strip()
837
+ zip_dirs = ["zips", "unzips"]
838
+ for directory in zip_dirs:
839
+ if os.path.exists(directory):
840
+ shutil.rmtree(directory)
841
+ os.makedirs("zips", exist_ok=True)
842
+ os.makedirs("unzips", exist_ok=True)
843
+ zipfile = model + '.zip'
844
+ zipfile_path = './zips/' + zipfile
845
+ try:
846
+ if "drive.google.com" in url:
847
+ subprocess.run(["gdown", url, "--fuzzy", "-O", zipfile_path])
848
+ elif "mega.nz" in url:
849
+ m = Mega()
850
+ m.download_url(url, './zips')
851
+ else:
852
+ subprocess.run(["wget", url, "-O", zipfile_path])
853
+ for filename in os.listdir("./zips"):
854
+ if filename.endswith(".zip"):
855
+ zipfile_path = os.path.join("./zips/",filename)
856
+ shutil.unpack_archive(zipfile_path, "./unzips", 'zip')
857
+ else:
858
+ return "No zipfile found."
859
+ for root, dirs, files in os.walk('./unzips'):
860
+ for file in files:
861
+ file_path = os.path.join(root, file)
862
+ if file.endswith(".index"):
863
+ os.mkdir(f'./logs/{model}')
864
+ shutil.copy2(file_path,f'./logs/{model}')
865
+ elif "G_" not in file and "D_" not in file and file.endswith(".pth"):
866
+ shutil.copy(file_path,f'./assets/weights/{model}.pth')
867
+ shutil.rmtree("zips")
868
+ shutil.rmtree("unzips")
869
+ return "Success."
870
+ except:
871
+ return "There's been an error."
872
+
873
+ def upload_to_dataset(files, dir):
874
+ if dir == '':
875
+ dir = './dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
876
+ if not os.path.exists(dir):
877
+ os.makedirs(dir)
878
+ for file in files:
879
+ path=file.name
880
+ shutil.copy2(path,dir)
881
+ try:
882
+ gr.Info(i18n("处理数据"))
883
+ except:
884
+ pass
885
+ return i18n("处理数据"), {"value":dir,"__type__":"update"}
886
+
887
+ with gr.Blocks(title="EasyGUI v2.9",theme=gr.themes.Base()) as app:
888
+ gr.HTML("<h1> EasyGUI v2.9 </h1>")
889
+ with gr.Tabs():
890
+ with gr.TabItem(i18n("模型推理")):
891
+ with gr.Row():
892
+ sid0 = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names), value=find_model())
893
+ refresh_button = gr.Button(i18n("刷新音色列表和索引路径"), variant="primary")
894
+ #clean_button = gr.Button(i18n("卸载音色省显存"), variant="primary")
895
+ spk_item = gr.Slider(
896
+ minimum=0,
897
+ maximum=2333,
898
+ step=1,
899
+ label=i18n("请选择说话人id"),
900
+ value=0,
901
+ visible=False,
902
+ interactive=True,
903
+ )
904
+ #clean_button.click(
905
+ # fn=clean, inputs=[], outputs=[sid0], api_name="infer_clean"
906
+ #)
907
+ vc_transform0 = gr.Number(
908
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
909
+ )
910
+ but0 = gr.Button(i18n("转换"), variant="primary")
911
+ with gr.Row():
912
+ with gr.Column():
913
+ with gr.Row():
914
+ dropbox = gr.File(label="Drop your audio here & hit the Reload button.")
915
+ with gr.Row():
916
+ record_button=gr.Audio(source="microphone", label="OR Record audio.", type="filepath")
917
+ with gr.Row():
918
+ input_audio0 = gr.Dropdown(
919
+ label=i18n("输入待处理音频文件路径(默认是正确格式示例)"),
920
+ value=find_audios(True),
921
+ choices=find_audios()
922
+ )
923
+ record_button.change(fn=save_wav, inputs=[record_button], outputs=[input_audio0])
924
+ dropbox.upload(fn=save_wav, inputs=[dropbox], outputs=[input_audio0])
925
+ with gr.Column():
926
+ with gr.Accordion(label=i18n("自动检测index路径,下拉式选择(dropdown)"), open=False):
927
+ file_index2 = gr.Dropdown(
928
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
929
+ choices=get_indexes(),
930
+ interactive=True,
931
+ value=get_index()
932
+ )
933
+ index_rate1 = gr.Slider(
934
+ minimum=0,
935
+ maximum=1,
936
+ label=i18n("检索特征占比"),
937
+ value=0.66,
938
+ interactive=True,
939
+ )
940
+ vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
941
+ with gr.Accordion(label=i18n("常规设置"), open=False):
942
+ f0method0 = gr.Radio(
943
+ label=i18n(
944
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
945
+ ),
946
+ choices=["pm", "harvest", "crepe", "rmvpe"]
947
+ if config.dml == False
948
+ else ["pm", "harvest", "rmvpe"],
949
+ value="rmvpe",
950
+ interactive=True,
951
+ )
952
+ filter_radius0 = gr.Slider(
953
+ minimum=0,
954
+ maximum=7,
955
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
956
+ value=3,
957
+ step=1,
958
+ interactive=True,
959
+ )
960
+ resample_sr0 = gr.Slider(
961
+ minimum=0,
962
+ maximum=48000,
963
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
964
+ value=0,
965
+ step=1,
966
+ interactive=True,
967
+ )
968
+ rms_mix_rate0 = gr.Slider(
969
+ minimum=0,
970
+ maximum=1,
971
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
972
+ value=0.21,
973
+ interactive=True,
974
+ )
975
+ protect0 = gr.Slider(
976
+ minimum=0,
977
+ maximum=0.5,
978
+ label=i18n(
979
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
980
+ ),
981
+ value=0.33,
982
+ step=0.01,
983
+ interactive=True,
984
+ )
985
+ file_index1 = gr.Textbox(
986
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
987
+ value="",
988
+ interactive=True,
989
+ visible=False
990
+ )
991
+ refresh_button.click(
992
+ fn=change_choices,
993
+ inputs=[],
994
+ outputs=[sid0, file_index2, input_audio0],
995
+ api_name="infer_refresh",
996
+ )
997
+ # file_big_npy1 = gr.Textbox(
998
+ # label=i18n("特征文件路径"),
999
+ # value="E:\\codes\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1000
+ # interactive=True,
1001
+ # )
1002
+ with gr.Row():
1003
+ f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"), visible=False)
1004
+ with gr.Row():
1005
+ vc_output1 = gr.Textbox(label=i18n("输出信息"))
1006
+ but0.click(
1007
+ vc.vc_single,
1008
+ [
1009
+ spk_item,
1010
+ input_audio0,
1011
+ vc_transform0,
1012
+ f0_file,
1013
+ f0method0,
1014
+ file_index1,
1015
+ file_index2,
1016
+ # file_big_npy1,
1017
+ index_rate1,
1018
+ filter_radius0,
1019
+ resample_sr0,
1020
+ rms_mix_rate0,
1021
+ protect0,
1022
+ ],
1023
+ [vc_output1, vc_output2],
1024
+ api_name="infer_convert",
1025
+ )
1026
+ with gr.Row():
1027
+ with gr.Accordion(open=False, label=i18n("批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ")):
1028
+ with gr.Column():
1029
+ vc_transform1 = gr.Number(
1030
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
1031
+ )
1032
+ opt_input = gr.Textbox(label=i18n("指定输出文件夹"), value="opt")
1033
+ f0method1 = gr.Radio(
1034
+ label=i18n(
1035
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
1036
+ ),
1037
+ choices=["pm", "harvest", "crepe", "rmvpe"]
1038
+ if config.dml == False
1039
+ else ["pm", "harvest", "rmvpe"],
1040
+ value="pm",
1041
+ interactive=True,
1042
+ )
1043
+ filter_radius1 = gr.Slider(
1044
+ minimum=0,
1045
+ maximum=7,
1046
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
1047
+ value=3,
1048
+ step=1,
1049
+ interactive=True,
1050
+ )
1051
+ with gr.Column():
1052
+ file_index3 = gr.Textbox(
1053
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
1054
+ value="",
1055
+ interactive=True,
1056
+ visible=False
1057
+ )
1058
+ file_index4 = gr.Dropdown(
1059
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
1060
+ choices=sorted(index_paths),
1061
+ interactive=True,
1062
+ )
1063
+ refresh_button.click(
1064
+ fn=lambda: change_choices()[1],
1065
+ inputs=[],
1066
+ outputs=file_index4,
1067
+ api_name="infer_refresh_batch",
1068
+ )
1069
+ # file_big_npy2 = gr.Textbox(
1070
+ # label=i18n("特征文件路径"),
1071
+ # value="E:\\codes\\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1072
+ # interactive=True,
1073
+ # )
1074
+ index_rate2 = gr.Slider(
1075
+ minimum=0,
1076
+ maximum=1,
1077
+ label=i18n("检索特征占比"),
1078
+ value=1,
1079
+ interactive=True,
1080
+ )
1081
+ with gr.Column():
1082
+ resample_sr1 = gr.Slider(
1083
+ minimum=0,
1084
+ maximum=48000,
1085
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
1086
+ value=0,
1087
+ step=1,
1088
+ interactive=True,
1089
+ )
1090
+ rms_mix_rate1 = gr.Slider(
1091
+ minimum=0,
1092
+ maximum=1,
1093
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
1094
+ value=1,
1095
+ interactive=True,
1096
+ )
1097
+ protect1 = gr.Slider(
1098
+ minimum=0,
1099
+ maximum=0.5,
1100
+ label=i18n(
1101
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
1102
+ ),
1103
+ value=0.33,
1104
+ step=0.01,
1105
+ interactive=True,
1106
+ )
1107
+ with gr.Column():
1108
+ dir_input = gr.Textbox(
1109
+ label=i18n("输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)"),
1110
+ value="E:\codes\py39\\test-20230416b\\todo-songs",
1111
+ )
1112
+ inputs = gr.File(
1113
+ file_count="multiple", label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹")
1114
+ )
1115
+ with gr.Row():
1116
+ format1 = gr.Radio(
1117
+ label=i18n("导出文件格式"),
1118
+ choices=["wav", "flac", "mp3", "m4a"],
1119
+ value="flac",
1120
+ interactive=True,
1121
+ )
1122
+ but1 = gr.Button(i18n("转换"), variant="primary")
1123
+ vc_output3 = gr.Textbox(label=i18n("输出信息"))
1124
+ but1.click(
1125
+ vc.vc_multi,
1126
+ [
1127
+ spk_item,
1128
+ dir_input,
1129
+ opt_input,
1130
+ inputs,
1131
+ vc_transform1,
1132
+ f0method1,
1133
+ file_index3,
1134
+ file_index4,
1135
+ # file_big_npy2,
1136
+ index_rate2,
1137
+ filter_radius1,
1138
+ resample_sr1,
1139
+ rms_mix_rate1,
1140
+ protect1,
1141
+ format1,
1142
+ ],
1143
+ [vc_output3],
1144
+ api_name="infer_convert_batch",
1145
+ )
1146
+ sid0.change(
1147
+ fn=vc.get_vc,
1148
+ inputs=[sid0, protect0, protect1],
1149
+ outputs=[spk_item, protect0, protect1, file_index2, file_index4],
1150
+ )
1151
+ with gr.TabItem("Download Model"):
1152
+ with gr.Row():
1153
+ url=gr.Textbox(label="Enter the URL to the Model:")
1154
+ with gr.Row():
1155
+ model = gr.Textbox(label="Name your model:")
1156
+ download_button=gr.Button("Download")
1157
+ with gr.Row():
1158
+ status_bar=gr.Textbox(label="")
1159
+ download_button.click(fn=download_from_url, inputs=[url, model], outputs=[status_bar])
1160
+ with gr.Row():
1161
+ gr.Markdown(
1162
+ """
1163
+ ❤️ If you like the EasyGUI, help me keep it.❤️
1164
+ https://paypal.me/lesantillan
1165
+ """
1166
+ )
1167
+ with gr.TabItem(i18n("训练")):
1168
+ with gr.Row():
1169
+ with gr.Column():
1170
+ exp_dir1 = gr.Textbox(label=i18n("输入实验名"), value="My-Voice")
1171
+ np7 = gr.Slider(
1172
+ minimum=0,
1173
+ maximum=config.n_cpu,
1174
+ step=1,
1175
+ label=i18n("提取音高和处理数据使用的CPU进程数"),
1176
+ value=int(np.ceil(config.n_cpu / 1.5)),
1177
+ interactive=True,
1178
+ )
1179
+ sr2 = gr.Radio(
1180
+ label=i18n("目标采样率"),
1181
+ choices=["40k", "48k"],
1182
+ value="40k",
1183
+ interactive=True,
1184
+ visible=False
1185
+ )
1186
+ if_f0_3 = gr.Radio(
1187
+ label=i18n("模型是否带音高指导(唱歌一定要, 语音可以不要)"),
1188
+ choices=[True, False],
1189
+ value=True,
1190
+ interactive=True,
1191
+ visible=False
1192
+ )
1193
+ version19 = gr.Radio(
1194
+ label=i18n("版本"),
1195
+ choices=["v1", "v2"],
1196
+ value="v2",
1197
+ interactive=True,
1198
+ visible=False,
1199
+ )
1200
+ trainset_dir4 = gr.Textbox(
1201
+ label=i18n("输入训练文件夹路径"), value='./dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
1202
+ )
1203
+ easy_uploader = gr.Files(label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹"),file_types=['audio'])
1204
+ but1 = gr.Button(label=i18n("处理数据"), variant="primary")
1205
+ info1 = gr.Textbox(label=i18n("输出信息"), value="")
1206
+ easy_uploader.upload(fn=upload_to_dataset, inputs=[easy_uploader, trainset_dir4], outputs=[info1, trainset_dir4])
1207
+ gpus6 = gr.Textbox(
1208
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1209
+ value=gpus,
1210
+ interactive=True,
1211
+ visible=F0GPUVisible,
1212
+ )
1213
+ gpu_info9 = gr.Textbox(
1214
+ label=i18n("显卡信息"), value=gpu_info, visible=F0GPUVisible
1215
+ )
1216
+ spk_id5 = gr.Slider(
1217
+ minimum=0,
1218
+ maximum=4,
1219
+ step=1,
1220
+ label=i18n("请指定说话人id"),
1221
+ value=0,
1222
+ interactive=True,
1223
+ visible=False
1224
+ )
1225
+ but1.click(
1226
+ preprocess_dataset,
1227
+ [trainset_dir4, exp_dir1, sr2, np7],
1228
+ [info1],
1229
+ api_name="train_preprocess",
1230
+ )
1231
+ with gr.Column():
1232
+ f0method8 = gr.Radio(
1233
+ label=i18n(
1234
+ "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢,rmvpe效果最好且微吃CPU/GPU"
1235
+ ),
1236
+ choices=["pm", "harvest", "dio", "rmvpe", "rmvpe_gpu"],
1237
+ value="rmvpe_gpu",
1238
+ interactive=True,
1239
+ )
1240
+ gpus_rmvpe = gr.Textbox(
1241
+ label=i18n(
1242
+ "rmvpe卡号配置:以-分隔输入使用的不同进程卡号,例如0-0-1使用在卡0上跑2个进程并在卡1上跑1个进程"
1243
+ ),
1244
+ value="%s-%s" % (gpus, gpus),
1245
+ interactive=True,
1246
+ visible=F0GPUVisible,
1247
+ )
1248
+ but2 = gr.Button(i18n("特征提取"), variant="primary")
1249
+ info2 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1250
+ f0method8.change(
1251
+ fn=change_f0_method,
1252
+ inputs=[f0method8],
1253
+ outputs=[gpus_rmvpe],
1254
+ )
1255
+ but2.click(
1256
+ extract_f0_feature,
1257
+ [
1258
+ gpus6,
1259
+ np7,
1260
+ f0method8,
1261
+ if_f0_3,
1262
+ exp_dir1,
1263
+ version19,
1264
+ gpus_rmvpe,
1265
+ ],
1266
+ [info2],
1267
+ api_name="train_extract_f0_feature",
1268
+ )
1269
+ with gr.Column():
1270
+ total_epoch11 = gr.Slider(
1271
+ minimum=2,
1272
+ maximum=1000,
1273
+ step=1,
1274
+ label=i18n("总训练轮数total_epoch"),
1275
+ value=150,
1276
+ interactive=True,
1277
+ )
1278
+ gpus16 = gr.Textbox(
1279
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1280
+ value="0",
1281
+ interactive=True,
1282
+ visible=True
1283
+ )
1284
+ but3 = gr.Button(i18n("训练模型"), variant="primary")
1285
+ but4 = gr.Button(i18n("训练特征索引"), variant="primary")
1286
+ info3 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=10)
1287
+ with gr.Accordion(label=i18n("常规设置"), open=False):
1288
+ save_epoch10 = gr.Slider(
1289
+ minimum=1,
1290
+ maximum=50,
1291
+ step=1,
1292
+ label=i18n("保存频率save_every_epoch"),
1293
+ value=25,
1294
+ interactive=True,
1295
+ )
1296
+ batch_size12 = gr.Slider(
1297
+ minimum=1,
1298
+ maximum=40,
1299
+ step=1,
1300
+ label=i18n("每张显卡的batch_size"),
1301
+ value=default_batch_size,
1302
+ interactive=True,
1303
+ )
1304
+ if_save_latest13 = gr.Radio(
1305
+ label=i18n("是否仅保存最新的ckpt文件以节省硬盘空间"),
1306
+ choices=[i18n("是"), i18n("否")],
1307
+ value=i18n("是"),
1308
+ interactive=True,
1309
+ )
1310
+ if_cache_gpu17 = gr.Radio(
1311
+ label=i18n(
1312
+ "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速"
1313
+ ),
1314
+ choices=[i18n("是"), i18n("否")],
1315
+ value=i18n("否"),
1316
+ interactive=True,
1317
+ )
1318
+ if_save_every_weights18 = gr.Radio(
1319
+ label=i18n("是否在每次保存时间点将最终小模型保存至weights文件夹"),
1320
+ choices=[i18n("是"), i18n("否")],
1321
+ value=i18n("是"),
1322
+ interactive=True,
1323
+ )
1324
+ with gr.Row():
1325
+ pretrained_G14 = gr.Textbox(
1326
+ label=i18n("加载预训练底模G路径"),
1327
+ value="assets/pretrained_v2/f0G40k.pth",
1328
+ interactive=True,
1329
+ visible=False
1330
+ )
1331
+ pretrained_D15 = gr.Textbox(
1332
+ label=i18n("加载预训练底模D路径"),
1333
+ value="assets/pretrained_v2/f0D40k.pth",
1334
+ interactive=True,
1335
+ visible=False
1336
+ )
1337
+ sr2.change(
1338
+ change_sr2,
1339
+ [sr2, if_f0_3, version19],
1340
+ [pretrained_G14, pretrained_D15],
1341
+ )
1342
+ version19.change(
1343
+ change_version19,
1344
+ [sr2, if_f0_3, version19],
1345
+ [pretrained_G14, pretrained_D15, sr2],
1346
+ )
1347
+ if_f0_3.change(
1348
+ change_f0,
1349
+ [if_f0_3, sr2, version19],
1350
+ [f0method8, pretrained_G14, pretrained_D15],
1351
+ )
1352
+ with gr.Row():
1353
+ but5 = gr.Button(i18n("一键训练"), variant="primary", visible=False)
1354
+ but3.click(
1355
+ click_train,
1356
+ [
1357
+ exp_dir1,
1358
+ sr2,
1359
+ if_f0_3,
1360
+ spk_id5,
1361
+ save_epoch10,
1362
+ total_epoch11,
1363
+ batch_size12,
1364
+ if_save_latest13,
1365
+ pretrained_G14,
1366
+ pretrained_D15,
1367
+ gpus16,
1368
+ if_cache_gpu17,
1369
+ if_save_every_weights18,
1370
+ version19,
1371
+ ],
1372
+ info3,
1373
+ api_name="train_start",
1374
+ )
1375
+ but4.click(train_index, [exp_dir1, version19], info3)
1376
+ but5.click(
1377
+ train1key,
1378
+ [
1379
+ exp_dir1,
1380
+ sr2,
1381
+ if_f0_3,
1382
+ trainset_dir4,
1383
+ spk_id5,
1384
+ np7,
1385
+ f0method8,
1386
+ save_epoch10,
1387
+ total_epoch11,
1388
+ batch_size12,
1389
+ if_save_latest13,
1390
+ pretrained_G14,
1391
+ pretrained_D15,
1392
+ gpus16,
1393
+ if_cache_gpu17,
1394
+ if_save_every_weights18,
1395
+ version19,
1396
+ gpus_rmvpe,
1397
+ ],
1398
+ info3,
1399
+ api_name="train_start_all",
1400
+ )
1401
+
1402
+ if config.iscolab:
1403
+ app.queue(concurrency_count=511, max_size=1022).launch(share=True)
1404
+ else:
1405
+ app.queue(concurrency_count=511, max_size=1022).launch(
1406
+ server_name="0.0.0.0",
1407
+ inbrowser=not config.noautoopen,
1408
+ server_port=config.listen_port,
1409
+ quiet=True,
1410
+ )
LICENSE ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 liujing04
4
+ Copyright (c) 2023 源文雨
5
+ Copyright (c) 2023 Ftps
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
Logo_of_TWICE.svg.png ADDED
MIT协议暨相关引用库协议 ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 本软件及其相关代码以MIT协议开源,作者不对软件具备任何控制力,使用软件者、传播软件导出的声音者自负全责。
2
+ 如不认可该条款,则不能使用或引用软件包内任何代码和文件。
3
+
4
+ 特此授予任何获得本软件和相关文档文件(以下简称“软件”)副本的人免费使用、复制、修改、合并、出版、分发、再授权和/或销售本软件的权利,以及授予本软件所提供的人使用本软件的权利,但须符合以下条件:
5
+ 上述版权声明和本许可声明应包含在软件的所有副本或实质部分中。
6
+ 软件是“按原样”提供的,没有任何明示或暗示的保证,包括但不限于适销性、适用于特定目的和不侵权的保证。在任何情况下,作者或版权持有人均不承担因软件或软件的使用或其他交易而产生、产生或与之相关的任何索赔、损害赔偿或其他责任,无论是在合同诉讼、侵权诉讼还是其他诉讼中。
7
+
8
+
9
+ The LICENCEs for related libraries are as follows.
10
+ 相关引用库协议如下:
11
+
12
+ ContentVec
13
+ https://github.com/auspicious3000/contentvec/blob/main/LICENSE
14
+ MIT License
15
+
16
+ VITS
17
+ https://github.com/jaywalnut310/vits/blob/main/LICENSE
18
+ MIT License
19
+
20
+ HIFIGAN
21
+ https://github.com/jik876/hifi-gan/blob/master/LICENSE
22
+ MIT License
23
+
24
+ gradio
25
+ https://github.com/gradio-app/gradio/blob/main/LICENSE
26
+ Apache License 2.0
27
+
28
+ ffmpeg
29
+ https://github.com/FFmpeg/FFmpeg/blob/master/COPYING.LGPLv3
30
+ https://github.com/BtbN/FFmpeg-Builds/releases/download/autobuild-2021-02-28-12-32/ffmpeg-n4.3.2-160-gfbb9368226-win64-lgpl-4.3.zip
31
+ LPGLv3 License
32
+ MIT License
33
+
34
+ ultimatevocalremovergui
35
+ https://github.com/Anjok07/ultimatevocalremovergui/blob/master/LICENSE
36
+ https://github.com/yang123qwe/vocal_separation_by_uvr5
37
+ MIT License
38
+
39
+ audio-slicer
40
+ https://github.com/openvpi/audio-slicer/blob/main/LICENSE
41
+ MIT License
42
+
43
+ PySimpleGUI
44
+ https://github.com/PySimpleGUI/PySimpleGUI/blob/master/license.txt
45
+ LPGLv3 License
README.md CHANGED
@@ -1,13 +1,32 @@
1
- ---
2
- title: Nw
3
- emoji: 🏢
4
- colorFrom: pink
5
- colorTo: red
6
- sdk: gradio
7
- sdk_version: 4.10.0
8
- app_file: app.py
9
- pinned: false
10
- license: apache-2.0
11
- ---
12
-
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [![Open In Colab](https://img.shields.io/badge/Colab-F9AB00?style=for-the-badge&logo=googlecolab&color=525252)](https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw)
2
+
3
+ # Local Installation
4
+ If you already have RVC installed, then just download GUI.py and drop it in the root folder!
5
+ If you need to install RVC, I recommend you check the [original repo](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI)
6
+ Or read this at least.
7
+
8
+ I recommend you use a virtual environment
9
+
10
+ ```bash
11
+ python -m venv RVC
12
+ cd RVC
13
+ git clone https://github.com/777gt/-EVC-
14
+ Scripts/activate.bat
15
+ pip install torch torchvision torchaudio
16
+ pip install -r "-EVC-/requirements.txt"
17
+ ```
18
+ If you're on Windows, like me, and don't have an NVIDA graphics card, install the requirements from a different .txt:
19
+ ```bash
20
+ pip install -r "-EVC-/requirements-dml.txt"
21
+ ```
22
+ Also, do not forget to download the necessary models. EasyGUI uses RVC 2 40k models.
23
+
24
+ ```bash
25
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -O ./assets/rmvpe/rmvpe.pt
26
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.onnx -O ./assets/rmvpe/rmvpe.onnx
27
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -O ./assets/hubert/hubert_base.pt
28
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -O ./assets/pretrained_v2/D40k.pth
29
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -O ./assets/pretrained_v2/G40k.pth
30
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -O ./assets/pretrained_v2/f0D40k.pth
31
+ wget https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -O ./assets/pretrained_v2/f0G40k.pth
32
+ ```
Retrieval_based_Voice_Conversion_WebUI.ipynb ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "attachments": {},
5
+ "cell_type": "markdown",
6
+ "metadata": {},
7
+ "source": [
8
+ "# [Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) Training notebook"
9
+ ]
10
+ },
11
+ {
12
+ "attachments": {},
13
+ "cell_type": "markdown",
14
+ "metadata": {
15
+ "id": "ZFFCx5J80SGa"
16
+ },
17
+ "source": [
18
+ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI.ipynb)"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "metadata": {
25
+ "id": "GmFP6bN9dvOq"
26
+ },
27
+ "outputs": [],
28
+ "source": [
29
+ "# @title 查看显卡\n",
30
+ "!nvidia-smi"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": null,
36
+ "metadata": {
37
+ "id": "jwu07JgqoFON"
38
+ },
39
+ "outputs": [],
40
+ "source": [
41
+ "# @title 挂载谷歌云盘\n",
42
+ "\n",
43
+ "from google.colab import drive\n",
44
+ "\n",
45
+ "drive.mount(\"/content/drive\")"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": null,
51
+ "metadata": {
52
+ "id": "wjddIFr1oS3W"
53
+ },
54
+ "outputs": [],
55
+ "source": [
56
+ "# @title 安装依赖\n",
57
+ "!apt-get -y install build-essential python3-dev ffmpeg\n",
58
+ "!pip3 install --upgrade setuptools wheel\n",
59
+ "!pip3 install --upgrade pip\n",
60
+ "!pip3 install faiss-cpu==1.7.2 fairseq gradio==3.14.0 ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": null,
66
+ "metadata": {
67
+ "id": "ge_97mfpgqTm"
68
+ },
69
+ "outputs": [],
70
+ "source": [
71
+ "# @title 克隆仓库\n",
72
+ "\n",
73
+ "!git clone --depth=1 -b stable https://github.com/fumiama/Retrieval-based-Voice-Conversion-WebUI\n",
74
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
75
+ "!mkdir -p pretrained uvr5_weights"
76
+ ]
77
+ },
78
+ {
79
+ "cell_type": "code",
80
+ "execution_count": null,
81
+ "metadata": {
82
+ "id": "BLDEZADkvlw1"
83
+ },
84
+ "outputs": [],
85
+ "source": [
86
+ "# @title 更新仓库(一般无需执行)\n",
87
+ "!git pull"
88
+ ]
89
+ },
90
+ {
91
+ "cell_type": "code",
92
+ "execution_count": null,
93
+ "metadata": {
94
+ "id": "pqE0PrnuRqI2"
95
+ },
96
+ "outputs": [],
97
+ "source": [
98
+ "# @title 安装aria2\n",
99
+ "!apt -y install -qq aria2"
100
+ ]
101
+ },
102
+ {
103
+ "cell_type": "code",
104
+ "execution_count": null,
105
+ "metadata": {
106
+ "id": "UG3XpUwEomUz"
107
+ },
108
+ "outputs": [],
109
+ "source": [
110
+ "# @title 下载底模\n",
111
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D32k.pth\n",
112
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D40k.pth\n",
113
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D48k.pth\n",
114
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G32k.pth\n",
115
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G40k.pth\n",
116
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G48k.pth\n",
117
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D32k.pth\n",
118
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D40k.pth\n",
119
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D48k.pth\n",
120
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G32k.pth\n",
121
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G40k.pth\n",
122
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G48k.pth"
123
+ ]
124
+ },
125
+ {
126
+ "cell_type": "code",
127
+ "execution_count": null,
128
+ "metadata": {
129
+ "id": "HugjmZqZRuiF"
130
+ },
131
+ "outputs": [],
132
+ "source": [
133
+ "# @title 下载人声分离模型\n",
134
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP2-人声vocals+非人声instrumentals.pth\n",
135
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP5-主旋律人声vocals+其他instrumentals.pth"
136
+ ]
137
+ },
138
+ {
139
+ "cell_type": "code",
140
+ "execution_count": null,
141
+ "metadata": {
142
+ "id": "2RCaT9FTR0ej"
143
+ },
144
+ "outputs": [],
145
+ "source": [
146
+ "# @title 下载hubert_base\n",
147
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o hubert_base.pt"
148
+ ]
149
+ },
150
+ {
151
+ "cell_type": "code",
152
+ "execution_count": null,
153
+ "metadata": {},
154
+ "outputs": [],
155
+ "source": [
156
+ "# @title #下载rmvpe模型\n",
157
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o rmvpe.pt"
158
+ ]
159
+ },
160
+ {
161
+ "cell_type": "code",
162
+ "execution_count": null,
163
+ "metadata": {
164
+ "id": "Mwk7Q0Loqzjx"
165
+ },
166
+ "outputs": [],
167
+ "source": [
168
+ "# @title 从谷歌云盘加载打包好的数据集到/content/dataset\n",
169
+ "\n",
170
+ "# @markdown 数据集位置\n",
171
+ "DATASET = (\n",
172
+ " \"/content/drive/MyDrive/dataset/lulu20230327_32k.zip\" # @param {type:\"string\"}\n",
173
+ ")\n",
174
+ "\n",
175
+ "!mkdir -p /content/dataset\n",
176
+ "!unzip -d /content/dataset -B {DATASET}"
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": null,
182
+ "metadata": {
183
+ "id": "PDlFxWHWEynD"
184
+ },
185
+ "outputs": [],
186
+ "source": [
187
+ "# @title 重命名数据集中的重名文件\n",
188
+ "!ls -a /content/dataset/\n",
189
+ "!rename 's/(\\w+)\\.(\\w+)~(\\d*)/$1_$3.$2/' /content/dataset/*.*~*"
190
+ ]
191
+ },
192
+ {
193
+ "cell_type": "code",
194
+ "execution_count": null,
195
+ "metadata": {
196
+ "id": "7vh6vphDwO0b"
197
+ },
198
+ "outputs": [],
199
+ "source": [
200
+ "# @title 启动web\n",
201
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
202
+ "# %load_ext tensorboard\n",
203
+ "# %tensorboard --logdir /content/Retrieval-based-Voice-Conversion-WebUI/logs\n",
204
+ "!python3 infer-web.py --colab --pycmd python3"
205
+ ]
206
+ },
207
+ {
208
+ "cell_type": "code",
209
+ "execution_count": null,
210
+ "metadata": {
211
+ "id": "FgJuNeAwx5Y_"
212
+ },
213
+ "outputs": [],
214
+ "source": [
215
+ "# @title 手动将训练后的模型文件备份到谷歌云盘\n",
216
+ "# @markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
217
+ "\n",
218
+ "# @markdown 模型名\n",
219
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
220
+ "# @markdown 模型epoch\n",
221
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
222
+ "\n",
223
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth\n",
224
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth\n",
225
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/added_*.index /content/drive/MyDrive/\n",
226
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/total_*.npy /content/drive/MyDrive/\n",
227
+ "\n",
228
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth"
229
+ ]
230
+ },
231
+ {
232
+ "cell_type": "code",
233
+ "execution_count": null,
234
+ "metadata": {
235
+ "id": "OVQoLQJXS7WX"
236
+ },
237
+ "outputs": [],
238
+ "source": [
239
+ "# @title 从谷歌云盘恢复pth\n",
240
+ "# @markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
241
+ "\n",
242
+ "# @markdown 模型名\n",
243
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
244
+ "# @markdown 模型epoch\n",
245
+ "MODELEPOCH = 7500 # @param {type:\"integer\"}\n",
246
+ "\n",
247
+ "!mkdir -p /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
248
+ "\n",
249
+ "!cp /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
250
+ "!cp /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
251
+ "!cp /content/drive/MyDrive/*.index /content/\n",
252
+ "!cp /content/drive/MyDrive/*.npy /content/\n",
253
+ "!cp /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth"
254
+ ]
255
+ },
256
+ {
257
+ "cell_type": "code",
258
+ "execution_count": null,
259
+ "metadata": {
260
+ "id": "ZKAyuKb9J6dz"
261
+ },
262
+ "outputs": [],
263
+ "source": [
264
+ "# @title 手动预处理(不推荐)\n",
265
+ "# @markdown 模型名\n",
266
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
267
+ "# @markdown 采样率\n",
268
+ "BITRATE = 48000 # @param {type:\"integer\"}\n",
269
+ "# @markdown 使用的进程数\n",
270
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
271
+ "\n",
272
+ "!python3 trainset_preprocess_pipeline_print.py /content/dataset {BITRATE} {THREADCOUNT} logs/{MODELNAME} True"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "metadata": {
279
+ "id": "CrxJqzAUKmPJ"
280
+ },
281
+ "outputs": [],
282
+ "source": [
283
+ "# @title 手动提取特征(不推荐)\n",
284
+ "# @markdown 模型名\n",
285
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
286
+ "# @markdown 使用的进程数\n",
287
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
288
+ "# @markdown 音高提取算法\n",
289
+ "ALGO = \"harvest\" # @param {type:\"string\"}\n",
290
+ "\n",
291
+ "!python3 extract_f0_print.py logs/{MODELNAME} {THREADCOUNT} {ALGO}\n",
292
+ "\n",
293
+ "!python3 extract_feature_print.py cpu 1 0 0 logs/{MODELNAME}"
294
+ ]
295
+ },
296
+ {
297
+ "cell_type": "code",
298
+ "execution_count": null,
299
+ "metadata": {
300
+ "id": "IMLPLKOaKj58"
301
+ },
302
+ "outputs": [],
303
+ "source": [
304
+ "# @title 手动训练(不推荐)\n",
305
+ "# @markdown 模型名\n",
306
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
307
+ "# @markdown 使用的GPU\n",
308
+ "USEGPU = \"0\" # @param {type:\"string\"}\n",
309
+ "# @markdown 批大小\n",
310
+ "BATCHSIZE = 32 # @param {type:\"integer\"}\n",
311
+ "# @markdown 停止的epoch\n",
312
+ "MODELEPOCH = 3200 # @param {type:\"integer\"}\n",
313
+ "# @markdown 保存epoch间隔\n",
314
+ "EPOCHSAVE = 100 # @param {type:\"integer\"}\n",
315
+ "# @markdown 采样率\n",
316
+ "MODELSAMPLE = \"48k\" # @param {type:\"string\"}\n",
317
+ "# @markdown 是否缓存训练集\n",
318
+ "CACHEDATA = 1 # @param {type:\"integer\"}\n",
319
+ "# @markdown 是否仅保存最新的ckpt文件\n",
320
+ "ONLYLATEST = 0 # @param {type:\"integer\"}\n",
321
+ "\n",
322
+ "!python3 train_nsf_sim_cache_sid_load_pretrain.py -e lulu -sr {MODELSAMPLE} -f0 1 -bs {BATCHSIZE} -g {USEGPU} -te {MODELEPOCH} -se {EPOCHSAVE} -pg pretrained/f0G{MODELSAMPLE}.pth -pd pretrained/f0D{MODELSAMPLE}.pth -l {ONLYLATEST} -c {CACHEDATA}"
323
+ ]
324
+ },
325
+ {
326
+ "cell_type": "code",
327
+ "execution_count": null,
328
+ "metadata": {
329
+ "id": "haYA81hySuDl"
330
+ },
331
+ "outputs": [],
332
+ "source": [
333
+ "# @title 删除其它pth,只留选中的(慎点,仔细看代码)\n",
334
+ "# @markdown 模型名\n",
335
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
336
+ "# @markdown 选中模型epoch\n",
337
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
338
+ "\n",
339
+ "!echo \"备份选中的模型。。。\"\n",
340
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
341
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
342
+ "\n",
343
+ "!echo \"正在删除。。。\"\n",
344
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
345
+ "!rm /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*.pth\n",
346
+ "\n",
347
+ "!echo \"恢复选中的模型。。。\"\n",
348
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
349
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
350
+ "\n",
351
+ "!echo \"删除完成\"\n",
352
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
353
+ ]
354
+ },
355
+ {
356
+ "cell_type": "code",
357
+ "execution_count": null,
358
+ "metadata": {
359
+ "id": "QhSiPTVPoIRh"
360
+ },
361
+ "outputs": [],
362
+ "source": [
363
+ "# @title 清除项目下所有文件,只留选中的模型(慎点,仔细看代码)\n",
364
+ "# @markdown 模型名\n",
365
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
366
+ "# @markdown 选中模型epoch\n",
367
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
368
+ "\n",
369
+ "!echo \"备份选中的模型。。。\"\n",
370
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
371
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
372
+ "\n",
373
+ "!echo \"正��删除。。。\"\n",
374
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
375
+ "!rm -rf /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*\n",
376
+ "\n",
377
+ "!echo \"恢复选中的模型。。。\"\n",
378
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
379
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
380
+ "\n",
381
+ "!echo \"删除完成\"\n",
382
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
383
+ ]
384
+ }
385
+ ],
386
+ "metadata": {
387
+ "accelerator": "GPU",
388
+ "colab": {
389
+ "private_outputs": true,
390
+ "provenance": []
391
+ },
392
+ "gpuClass": "standard",
393
+ "kernelspec": {
394
+ "display_name": "Python 3",
395
+ "name": "python3"
396
+ },
397
+ "language_info": {
398
+ "name": "python"
399
+ }
400
+ },
401
+ "nbformat": 4,
402
+ "nbformat_minor": 0
403
+ }
Retrieval_based_Voice_Conversion_WebUI_v2.ipynb ADDED
@@ -0,0 +1,422 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "attachments": {},
5
+ "cell_type": "markdown",
6
+ "metadata": {},
7
+ "source": [
8
+ "# [Retrieval-based-Voice-Conversion-WebUI](https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI) Training notebook"
9
+ ]
10
+ },
11
+ {
12
+ "attachments": {},
13
+ "cell_type": "markdown",
14
+ "metadata": {
15
+ "id": "ZFFCx5J80SGa"
16
+ },
17
+ "source": [
18
+ "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/RVC-Project/Retrieval-based-Voice-Conversion-WebUI/blob/main/Retrieval_based_Voice_Conversion_WebUI_v2.ipynb)"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "code",
23
+ "execution_count": null,
24
+ "metadata": {
25
+ "id": "GmFP6bN9dvOq"
26
+ },
27
+ "outputs": [],
28
+ "source": [
29
+ "# @title #查看显卡\n",
30
+ "!nvidia-smi"
31
+ ]
32
+ },
33
+ {
34
+ "cell_type": "code",
35
+ "execution_count": null,
36
+ "metadata": {
37
+ "id": "jwu07JgqoFON"
38
+ },
39
+ "outputs": [],
40
+ "source": [
41
+ "# @title 挂载谷歌云盘\n",
42
+ "\n",
43
+ "from google.colab import drive\n",
44
+ "\n",
45
+ "drive.mount(\"/content/drive\")"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "code",
50
+ "execution_count": null,
51
+ "metadata": {
52
+ "id": "wjddIFr1oS3W"
53
+ },
54
+ "outputs": [],
55
+ "source": [
56
+ "# @title #安装依赖\n",
57
+ "!apt-get -y install build-essential python3-dev ffmpeg\n",
58
+ "!pip3 install --upgrade setuptools wheel\n",
59
+ "!pip3 install --upgrade pip\n",
60
+ "!pip3 install faiss-cpu==1.7.2 fairseq gradio==3.14.0 ffmpeg ffmpeg-python praat-parselmouth pyworld numpy==1.23.5 numba==0.56.4 librosa==0.9.2"
61
+ ]
62
+ },
63
+ {
64
+ "cell_type": "code",
65
+ "execution_count": null,
66
+ "metadata": {
67
+ "id": "ge_97mfpgqTm"
68
+ },
69
+ "outputs": [],
70
+ "source": [
71
+ "# @title #克隆仓库\n",
72
+ "\n",
73
+ "!mkdir Retrieval-based-Voice-Conversion-WebUI\n",
74
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
75
+ "!git init\n",
76
+ "!git remote add origin https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI.git\n",
77
+ "!git fetch origin cfd984812804ddc9247d65b14c82cd32e56c1133 --depth=1\n",
78
+ "!git reset --hard FETCH_HEAD"
79
+ ]
80
+ },
81
+ {
82
+ "cell_type": "code",
83
+ "execution_count": null,
84
+ "metadata": {
85
+ "id": "BLDEZADkvlw1"
86
+ },
87
+ "outputs": [],
88
+ "source": [
89
+ "# @title #更新仓库(一般无需执行)\n",
90
+ "!git pull"
91
+ ]
92
+ },
93
+ {
94
+ "cell_type": "code",
95
+ "execution_count": null,
96
+ "metadata": {
97
+ "id": "pqE0PrnuRqI2"
98
+ },
99
+ "outputs": [],
100
+ "source": [
101
+ "# @title #安装aria2\n",
102
+ "!apt -y install -qq aria2"
103
+ ]
104
+ },
105
+ {
106
+ "cell_type": "code",
107
+ "execution_count": null,
108
+ "metadata": {
109
+ "id": "UG3XpUwEomUz"
110
+ },
111
+ "outputs": [],
112
+ "source": [
113
+ "# @title 下载底模\n",
114
+ "\n",
115
+ "# v1\n",
116
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D32k.pth\n",
117
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D40k.pth\n",
118
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o D48k.pth\n",
119
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G32k.pth\n",
120
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G40k.pth\n",
121
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o G48k.pth\n",
122
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D32k.pth\n",
123
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D40k.pth\n",
124
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0D48k.pth\n",
125
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G32k.pth\n",
126
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G40k.pth\n",
127
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained -o f0G48k.pth\n",
128
+ "\n",
129
+ "# v2\n",
130
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D32k.pth\n",
131
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D40k.pth\n",
132
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o D48k.pth\n",
133
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G32k.pth\n",
134
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G40k.pth\n",
135
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o G48k.pth\n",
136
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D32k.pth\n",
137
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D40k.pth\n",
138
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0D48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0D48k.pth\n",
139
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G32k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G32k.pth\n",
140
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G40k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G40k.pth\n",
141
+ "# !aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/pretrained_v2/f0G48k.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/pretrained_v2 -o f0G48k.pth"
142
+ ]
143
+ },
144
+ {
145
+ "cell_type": "code",
146
+ "execution_count": null,
147
+ "metadata": {
148
+ "id": "HugjmZqZRuiF"
149
+ },
150
+ "outputs": [],
151
+ "source": [
152
+ "# @title #下载人声分离模型\n",
153
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP2-人声vocals+非人声instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP2-人声vocals+非人声instrumentals.pth\n",
154
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth -d /content/Retrieval-based-Voice-Conversion-WebUI/uvr5_weights -o HP5-主旋律人声vocals+其他instrumentals.pth"
155
+ ]
156
+ },
157
+ {
158
+ "cell_type": "code",
159
+ "execution_count": null,
160
+ "metadata": {
161
+ "id": "2RCaT9FTR0ej"
162
+ },
163
+ "outputs": [],
164
+ "source": [
165
+ "# @title #下载hubert_base\n",
166
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o hubert_base.pt"
167
+ ]
168
+ },
169
+ {
170
+ "cell_type": "code",
171
+ "execution_count": null,
172
+ "metadata": {},
173
+ "outputs": [],
174
+ "source": [
175
+ "# @title #下载rmvpe模型\n",
176
+ "!aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/rmvpe.pt -d /content/Retrieval-based-Voice-Conversion-WebUI -o rmvpe.pt"
177
+ ]
178
+ },
179
+ {
180
+ "cell_type": "code",
181
+ "execution_count": null,
182
+ "metadata": {
183
+ "id": "Mwk7Q0Loqzjx"
184
+ },
185
+ "outputs": [],
186
+ "source": [
187
+ "# @title #从谷歌云盘加载打包好的数据集到/content/dataset\n",
188
+ "\n",
189
+ "# @markdown 数据集位置\n",
190
+ "DATASET = (\n",
191
+ " \"/content/drive/MyDrive/dataset/lulu20230327_32k.zip\" # @param {type:\"string\"}\n",
192
+ ")\n",
193
+ "\n",
194
+ "!mkdir -p /content/dataset\n",
195
+ "!unzip -d /content/dataset -B {DATASET}"
196
+ ]
197
+ },
198
+ {
199
+ "cell_type": "code",
200
+ "execution_count": null,
201
+ "metadata": {
202
+ "id": "PDlFxWHWEynD"
203
+ },
204
+ "outputs": [],
205
+ "source": [
206
+ "# @title #重命名数据集中的重名文件\n",
207
+ "!ls -a /content/dataset/\n",
208
+ "!rename 's/(\\w+)\\.(\\w+)~(\\d*)/$1_$3.$2/' /content/dataset/*.*~*"
209
+ ]
210
+ },
211
+ {
212
+ "cell_type": "code",
213
+ "execution_count": null,
214
+ "metadata": {
215
+ "id": "7vh6vphDwO0b"
216
+ },
217
+ "outputs": [],
218
+ "source": [
219
+ "# @title #启动webui\n",
220
+ "%cd /content/Retrieval-based-Voice-Conversion-WebUI\n",
221
+ "# %load_ext tensorboard\n",
222
+ "# %tensorboard --logdir /content/Retrieval-based-Voice-Conversion-WebUI/logs\n",
223
+ "!python3 infer-web.py --colab --pycmd python3"
224
+ ]
225
+ },
226
+ {
227
+ "cell_type": "code",
228
+ "execution_count": null,
229
+ "metadata": {
230
+ "id": "FgJuNeAwx5Y_"
231
+ },
232
+ "outputs": [],
233
+ "source": [
234
+ "# @title #手动将训练后的模型文件备份到谷歌云盘\n",
235
+ "# @markdown #需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
236
+ "\n",
237
+ "# @markdown #模型名\n",
238
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
239
+ "# @markdown #模型epoch\n",
240
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
241
+ "\n",
242
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth\n",
243
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth\n",
244
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/added_*.index /content/drive/MyDrive/\n",
245
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/total_*.npy /content/drive/MyDrive/\n",
246
+ "\n",
247
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth"
248
+ ]
249
+ },
250
+ {
251
+ "cell_type": "code",
252
+ "execution_count": null,
253
+ "metadata": {
254
+ "id": "OVQoLQJXS7WX"
255
+ },
256
+ "outputs": [],
257
+ "source": [
258
+ "# @title 从谷歌云盘恢复pth\n",
259
+ "# @markdown 需要自己查看logs文件夹下模型的文件名,手动修改下方命令末尾的文件名\n",
260
+ "\n",
261
+ "# @markdown 模型名\n",
262
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
263
+ "# @markdown 模型epoch\n",
264
+ "MODELEPOCH = 7500 # @param {type:\"integer\"}\n",
265
+ "\n",
266
+ "!mkdir -p /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
267
+ "\n",
268
+ "!cp /content/drive/MyDrive/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
269
+ "!cp /content/drive/MyDrive/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
270
+ "!cp /content/drive/MyDrive/*.index /content/\n",
271
+ "!cp /content/drive/MyDrive/*.npy /content/\n",
272
+ "!cp /content/drive/MyDrive/{MODELNAME}{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/weights/{MODELNAME}.pth"
273
+ ]
274
+ },
275
+ {
276
+ "cell_type": "code",
277
+ "execution_count": null,
278
+ "metadata": {
279
+ "id": "ZKAyuKb9J6dz"
280
+ },
281
+ "outputs": [],
282
+ "source": [
283
+ "# @title 手动预处理(不推荐)\n",
284
+ "# @markdown 模型名\n",
285
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
286
+ "# @markdown 采样率\n",
287
+ "BITRATE = 48000 # @param {type:\"integer\"}\n",
288
+ "# @markdown 使用的进程数\n",
289
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
290
+ "\n",
291
+ "!python3 trainset_preprocess_pipeline_print.py /content/dataset {BITRATE} {THREADCOUNT} logs/{MODELNAME} True"
292
+ ]
293
+ },
294
+ {
295
+ "cell_type": "code",
296
+ "execution_count": null,
297
+ "metadata": {
298
+ "id": "CrxJqzAUKmPJ"
299
+ },
300
+ "outputs": [],
301
+ "source": [
302
+ "# @title 手动提取特征(不推荐)\n",
303
+ "# @markdown 模型名\n",
304
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
305
+ "# @markdown 使用的进程数\n",
306
+ "THREADCOUNT = 8 # @param {type:\"integer\"}\n",
307
+ "# @markdown 音高提取算法\n",
308
+ "ALGO = \"harvest\" # @param {type:\"string\"}\n",
309
+ "\n",
310
+ "!python3 extract_f0_print.py logs/{MODELNAME} {THREADCOUNT} {ALGO}\n",
311
+ "\n",
312
+ "!python3 extract_feature_print.py cpu 1 0 0 logs/{MODELNAME}"
313
+ ]
314
+ },
315
+ {
316
+ "cell_type": "code",
317
+ "execution_count": null,
318
+ "metadata": {
319
+ "id": "IMLPLKOaKj58"
320
+ },
321
+ "outputs": [],
322
+ "source": [
323
+ "# @title 手动训练(不推荐)\n",
324
+ "# @markdown 模型名\n",
325
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
326
+ "# @markdown 使用的GPU\n",
327
+ "USEGPU = \"0\" # @param {type:\"string\"}\n",
328
+ "# @markdown 批大小\n",
329
+ "BATCHSIZE = 32 # @param {type:\"integer\"}\n",
330
+ "# @markdown 停止的epoch\n",
331
+ "MODELEPOCH = 3200 # @param {type:\"integer\"}\n",
332
+ "# @markdown 保存epoch间隔\n",
333
+ "EPOCHSAVE = 100 # @param {type:\"integer\"}\n",
334
+ "# @markdown 采样率\n",
335
+ "MODELSAMPLE = \"48k\" # @param {type:\"string\"}\n",
336
+ "# @markdown 是否缓存训练集\n",
337
+ "CACHEDATA = 1 # @param {type:\"integer\"}\n",
338
+ "# @markdown 是否仅保存最新的ckpt文件\n",
339
+ "ONLYLATEST = 0 # @param {type:\"integer\"}\n",
340
+ "\n",
341
+ "!python3 train_nsf_sim_cache_sid_load_pretrain.py -e lulu -sr {MODELSAMPLE} -f0 1 -bs {BATCHSIZE} -g {USEGPU} -te {MODELEPOCH} -se {EPOCHSAVE} -pg pretrained/f0G{MODELSAMPLE}.pth -pd pretrained/f0D{MODELSAMPLE}.pth -l {ONLYLATEST} -c {CACHEDATA}"
342
+ ]
343
+ },
344
+ {
345
+ "cell_type": "code",
346
+ "execution_count": null,
347
+ "metadata": {
348
+ "id": "haYA81hySuDl"
349
+ },
350
+ "outputs": [],
351
+ "source": [
352
+ "# @title 删除其它pth,只留选中的(慎点,仔细看代码)\n",
353
+ "# @markdown 模型名\n",
354
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
355
+ "# @markdown 选中模型epoch\n",
356
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
357
+ "\n",
358
+ "!echo \"备份选中的模型。。。\"\n",
359
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
360
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
361
+ "\n",
362
+ "!echo \"正在删除。。。\"\n",
363
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
364
+ "!rm /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*.pth\n",
365
+ "\n",
366
+ "!echo \"恢复选中的模型。。。\"\n",
367
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
368
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
369
+ "\n",
370
+ "!echo \"删除完成\"\n",
371
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
372
+ ]
373
+ },
374
+ {
375
+ "cell_type": "code",
376
+ "execution_count": null,
377
+ "metadata": {
378
+ "id": "QhSiPTVPoIRh"
379
+ },
380
+ "outputs": [],
381
+ "source": [
382
+ "# @title 清除项目下所有文件,只留选中的模型(慎点,仔细看代码)\n",
383
+ "# @markdown 模型名\n",
384
+ "MODELNAME = \"lulu\" # @param {type:\"string\"}\n",
385
+ "# @markdown 选中模型epoch\n",
386
+ "MODELEPOCH = 9600 # @param {type:\"integer\"}\n",
387
+ "\n",
388
+ "!echo \"备份选中的模型。。。\"\n",
389
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth /content/{MODELNAME}_D_{MODELEPOCH}.pth\n",
390
+ "!cp /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth /content/{MODELNAME}_G_{MODELEPOCH}.pth\n",
391
+ "\n",
392
+ "!echo \"正在删除。。。\"\n",
393
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}\n",
394
+ "!rm -rf /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/*\n",
395
+ "\n",
396
+ "!echo \"恢复选中的模型。。。\"\n",
397
+ "!mv /content/{MODELNAME}_D_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/G_{MODELEPOCH}.pth\n",
398
+ "!mv /content/{MODELNAME}_G_{MODELEPOCH}.pth /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}/D_{MODELEPOCH}.pth\n",
399
+ "\n",
400
+ "!echo \"删除完成\"\n",
401
+ "!ls /content/Retrieval-based-Voice-Conversion-WebUI/logs/{MODELNAME}"
402
+ ]
403
+ }
404
+ ],
405
+ "metadata": {
406
+ "accelerator": "GPU",
407
+ "colab": {
408
+ "private_outputs": true,
409
+ "provenance": []
410
+ },
411
+ "gpuClass": "standard",
412
+ "kernelspec": {
413
+ "display_name": "Python 3",
414
+ "name": "python3"
415
+ },
416
+ "language_info": {
417
+ "name": "python"
418
+ }
419
+ },
420
+ "nbformat": 4,
421
+ "nbformat_minor": 0
422
+ }
app.py ADDED
@@ -0,0 +1,1449 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+ import datetime, subprocess
3
+ from mega import Mega
4
+ now_dir = os.getcwd()
5
+ sys.path.append(now_dir)
6
+ import logging
7
+ import shutil
8
+ import threading
9
+ import traceback
10
+ import warnings
11
+ from random import shuffle
12
+ from subprocess import Popen
13
+ from time import sleep
14
+ import json
15
+ import pathlib
16
+
17
+ import fairseq
18
+ import faiss
19
+ import gradio as gr
20
+ import numpy as np
21
+ import torch
22
+ from dotenv import load_dotenv
23
+ from sklearn.cluster import MiniBatchKMeans
24
+
25
+ from configs.config import Config
26
+ from i18n.i18n import I18nAuto
27
+ from infer.lib.train.process_ckpt import (
28
+ change_info,
29
+ extract_small_model,
30
+ merge,
31
+ show_info,
32
+ )
33
+ from infer.modules.uvr5.modules import uvr
34
+ from infer.modules.vc.modules import VC
35
+ logging.getLogger("numba").setLevel(logging.WARNING)
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ tmp = os.path.join(now_dir, "TEMP")
40
+ shutil.rmtree(tmp, ignore_errors=True)
41
+ shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)
42
+ shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)
43
+ os.makedirs(tmp, exist_ok=True)
44
+ os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)
45
+ os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)
46
+ os.environ["TEMP"] = tmp
47
+ warnings.filterwarnings("ignore")
48
+ torch.manual_seed(114514)
49
+
50
+
51
+ load_dotenv()
52
+ config = Config()
53
+ vc = VC(config)
54
+
55
+ if config.dml == True:
56
+
57
+ def forward_dml(ctx, x, scale):
58
+ ctx.scale = scale
59
+ res = x.clone().detach()
60
+ return res
61
+
62
+ fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml
63
+ i18n = I18nAuto()
64
+ logger.info(i18n)
65
+ # 判断是否有能用来训练和加速推理的N卡
66
+ ngpu = torch.cuda.device_count()
67
+ gpu_infos = []
68
+ mem = []
69
+ if_gpu_ok = False
70
+
71
+ if torch.cuda.is_available() or ngpu != 0:
72
+ for i in range(ngpu):
73
+ gpu_name = torch.cuda.get_device_name(i)
74
+ if any(
75
+ value in gpu_name.upper()
76
+ for value in [
77
+ "10",
78
+ "16",
79
+ "20",
80
+ "30",
81
+ "40",
82
+ "A2",
83
+ "A3",
84
+ "A4",
85
+ "P4",
86
+ "A50",
87
+ "500",
88
+ "A60",
89
+ "70",
90
+ "80",
91
+ "90",
92
+ "M4",
93
+ "T4",
94
+ "TITAN",
95
+ ]
96
+ ):
97
+ # A10#A100#V100#A40#P40#M40#K80#A4500
98
+ if_gpu_ok = True # 至少有一张能用的N卡
99
+ gpu_infos.append("%s\t%s" % (i, gpu_name))
100
+ mem.append(
101
+ int(
102
+ torch.cuda.get_device_properties(i).total_memory
103
+ / 1024
104
+ / 1024
105
+ / 1024
106
+ + 0.4
107
+ )
108
+ )
109
+ if if_gpu_ok and len(gpu_infos) > 0:
110
+ gpu_info = "\n".join(gpu_infos)
111
+ default_batch_size = min(mem) // 2
112
+ else:
113
+ gpu_info = i18n("很遗憾您这没有能用的显卡来支持您训练")
114
+ default_batch_size = 1
115
+ gpus = "-".join([i[0] for i in gpu_infos])
116
+
117
+
118
+ class ToolButton(gr.Button, gr.components.FormComponent):
119
+ """Small button with single emoji as text, fits inside gradio forms"""
120
+
121
+ def __init__(self, **kwargs):
122
+ super().__init__(variant="tool", **kwargs)
123
+
124
+ def get_block_name(self):
125
+ return "button"
126
+
127
+
128
+ weight_root = os.getenv("weight_root")
129
+ weight_uvr5_root = os.getenv("weight_uvr5_root")
130
+ index_root = os.getenv("index_root")
131
+
132
+ names = []
133
+ for name in os.listdir(weight_root):
134
+ if name.endswith(".pth"):
135
+ names.append(name)
136
+ index_paths = []
137
+ for root, dirs, files in os.walk(index_root, topdown=False):
138
+ for name in files:
139
+ if name.endswith(".index") and "trained" not in name:
140
+ index_paths.append("%s/%s" % (root, name))
141
+ uvr5_names = []
142
+ for name in os.listdir(weight_uvr5_root):
143
+ if name.endswith(".pth") or "onnx" in name:
144
+ uvr5_names.append(name.replace(".pth", ""))
145
+
146
+
147
+ def change_choices():
148
+ names = []
149
+ for name in os.listdir(weight_root):
150
+ if name.endswith(".pth"):
151
+ names.append(name)
152
+ index_paths = []
153
+ for root, dirs, files in os.walk(index_root, topdown=False):
154
+ for name in files:
155
+ if name.endswith(".index") and "trained" not in name:
156
+ index_paths.append("%s/%s" % (root, name))
157
+ audio_files=[]
158
+ for filename in os.listdir("./audios"):
159
+ if filename.endswith(('.wav','.mp3','.ogg')):
160
+ audio_files.append('./audios/'+filename)
161
+ return {"choices": sorted(names), "__type__": "update"}, {
162
+ "choices": sorted(index_paths),
163
+ "__type__": "update",
164
+ }, {"choices": sorted(audio_files), "__type__": "update"}
165
+
166
+ def clean():
167
+ return {"value": "", "__type__": "update"}
168
+
169
+
170
+ def export_onnx():
171
+ from infer.modules.onnx.export import export_onnx as eo
172
+
173
+ eo()
174
+
175
+
176
+ sr_dict = {
177
+ "32k": 32000,
178
+ "40k": 40000,
179
+ "48k": 48000,
180
+ }
181
+
182
+
183
+ def if_done(done, p):
184
+ while 1:
185
+ if p.poll() is None:
186
+ sleep(0.5)
187
+ else:
188
+ break
189
+ done[0] = True
190
+
191
+
192
+ def if_done_multi(done, ps):
193
+ while 1:
194
+ # poll==None代表进程未结束
195
+ # 只要有一个进程未结束都不停
196
+ flag = 1
197
+ for p in ps:
198
+ if p.poll() is None:
199
+ flag = 0
200
+ sleep(0.5)
201
+ break
202
+ if flag == 1:
203
+ break
204
+ done[0] = True
205
+
206
+
207
+ def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):
208
+ sr = sr_dict[sr]
209
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
210
+ f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")
211
+ f.close()
212
+ per = 3.0 if config.is_half else 3.7
213
+ cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (
214
+ config.python_cmd,
215
+ trainset_dir,
216
+ sr,
217
+ n_p,
218
+ now_dir,
219
+ exp_dir,
220
+ config.noparallel,
221
+ per,
222
+ )
223
+ logger.info(cmd)
224
+ p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir
225
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
226
+ done = [False]
227
+ threading.Thread(
228
+ target=if_done,
229
+ args=(
230
+ done,
231
+ p,
232
+ ),
233
+ ).start()
234
+ while 1:
235
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
236
+ yield (f.read())
237
+ sleep(1)
238
+ if done[0]:
239
+ break
240
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
241
+ log = f.read()
242
+ logger.info(log)
243
+ yield log
244
+
245
+
246
+ # but2.click(extract_f0,[gpus6,np7,f0method8,if_f0_3,trainset_dir4],[info2])
247
+ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, gpus_rmvpe):
248
+ gpus = gpus.split("-")
249
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
250
+ f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")
251
+ f.close()
252
+ if if_f0:
253
+ if f0method != "rmvpe_gpu":
254
+ cmd = (
255
+ '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'
256
+ % (
257
+ config.python_cmd,
258
+ now_dir,
259
+ exp_dir,
260
+ n_p,
261
+ f0method,
262
+ )
263
+ )
264
+ logger.info(cmd)
265
+ p = Popen(
266
+ cmd, shell=True, cwd=now_dir
267
+ ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE
268
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
269
+ done = [False]
270
+ threading.Thread(
271
+ target=if_done,
272
+ args=(
273
+ done,
274
+ p,
275
+ ),
276
+ ).start()
277
+ else:
278
+ if gpus_rmvpe != "-":
279
+ gpus_rmvpe = gpus_rmvpe.split("-")
280
+ leng = len(gpus_rmvpe)
281
+ ps = []
282
+ for idx, n_g in enumerate(gpus_rmvpe):
283
+ cmd = (
284
+ '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '
285
+ % (
286
+ config.python_cmd,
287
+ leng,
288
+ idx,
289
+ n_g,
290
+ now_dir,
291
+ exp_dir,
292
+ config.is_half,
293
+ )
294
+ )
295
+ logger.info(cmd)
296
+ p = Popen(
297
+ cmd, shell=True, cwd=now_dir
298
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
299
+ ps.append(p)
300
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
301
+ done = [False]
302
+ threading.Thread(
303
+ target=if_done_multi, #
304
+ args=(
305
+ done,
306
+ ps,
307
+ ),
308
+ ).start()
309
+ else:
310
+ cmd = (
311
+ config.python_cmd
312
+ + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '
313
+ % (
314
+ now_dir,
315
+ exp_dir,
316
+ )
317
+ )
318
+ logger.info(cmd)
319
+ p = Popen(
320
+ cmd, shell=True, cwd=now_dir
321
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
322
+ p.wait()
323
+ done = [True]
324
+ while 1:
325
+ with open(
326
+ "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"
327
+ ) as f:
328
+ yield (f.read())
329
+ sleep(1)
330
+ if done[0]:
331
+ break
332
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
333
+ log = f.read()
334
+ logger.info(log)
335
+ yield log
336
+ ####对不同part分别开多进程
337
+ """
338
+ n_part=int(sys.argv[1])
339
+ i_part=int(sys.argv[2])
340
+ i_gpu=sys.argv[3]
341
+ exp_dir=sys.argv[4]
342
+ os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)
343
+ """
344
+ leng = len(gpus)
345
+ ps = []
346
+ for idx, n_g in enumerate(gpus):
347
+ cmd = (
348
+ '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'
349
+ % (
350
+ config.python_cmd,
351
+ config.device,
352
+ leng,
353
+ idx,
354
+ n_g,
355
+ now_dir,
356
+ exp_dir,
357
+ version19,
358
+ )
359
+ )
360
+ logger.info(cmd)
361
+ p = Popen(
362
+ cmd, shell=True, cwd=now_dir
363
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
364
+ ps.append(p)
365
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
366
+ done = [False]
367
+ threading.Thread(
368
+ target=if_done_multi,
369
+ args=(
370
+ done,
371
+ ps,
372
+ ),
373
+ ).start()
374
+ while 1:
375
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
376
+ yield (f.read())
377
+ sleep(1)
378
+ if done[0]:
379
+ break
380
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
381
+ log = f.read()
382
+ logger.info(log)
383
+ yield log
384
+
385
+
386
+ def get_pretrained_models(path_str, f0_str, sr2):
387
+ if_pretrained_generator_exist = os.access(
388
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
389
+ )
390
+ if_pretrained_discriminator_exist = os.access(
391
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
392
+ )
393
+ if not if_pretrained_generator_exist:
394
+ logger.warn(
395
+ "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",
396
+ path_str,
397
+ f0_str,
398
+ sr2,
399
+ )
400
+ if not if_pretrained_discriminator_exist:
401
+ logger.warn(
402
+ "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",
403
+ path_str,
404
+ f0_str,
405
+ sr2,
406
+ )
407
+ return (
408
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
409
+ if if_pretrained_generator_exist
410
+ else "",
411
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
412
+ if if_pretrained_discriminator_exist
413
+ else "",
414
+ )
415
+
416
+
417
+ def change_sr2(sr2, if_f0_3, version19):
418
+ path_str = "" if version19 == "v1" else "_v2"
419
+ f0_str = "f0" if if_f0_3 else ""
420
+ return get_pretrained_models(path_str, f0_str, sr2)
421
+
422
+
423
+ def change_version19(sr2, if_f0_3, version19):
424
+ path_str = "" if version19 == "v1" else "_v2"
425
+ if sr2 == "32k" and version19 == "v1":
426
+ sr2 = "40k"
427
+ to_return_sr2 = (
428
+ {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}
429
+ if version19 == "v1"
430
+ else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}
431
+ )
432
+ f0_str = "f0" if if_f0_3 else ""
433
+ return (
434
+ *get_pretrained_models(path_str, f0_str, sr2),
435
+ to_return_sr2,
436
+ )
437
+
438
+
439
+ def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15
440
+ path_str = "" if version19 == "v1" else "_v2"
441
+ return (
442
+ {"visible": if_f0_3, "__type__": "update"},
443
+ *get_pretrained_models(path_str, "f0", sr2),
444
+ )
445
+
446
+
447
+ # but3.click(click_train,[exp_dir1,sr2,if_f0_3,save_epoch10,total_epoch11,batch_size12,if_save_latest13,pretrained_G14,pretrained_D15,gpus16])
448
+ def click_train(
449
+ exp_dir1,
450
+ sr2,
451
+ if_f0_3,
452
+ spk_id5,
453
+ save_epoch10,
454
+ total_epoch11,
455
+ batch_size12,
456
+ if_save_latest13,
457
+ pretrained_G14,
458
+ pretrained_D15,
459
+ gpus16,
460
+ if_cache_gpu17,
461
+ if_save_every_weights18,
462
+ version19,
463
+ ):
464
+ # 生成filelist
465
+ exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
466
+ os.makedirs(exp_dir, exist_ok=True)
467
+ gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)
468
+ feature_dir = (
469
+ "%s/3_feature256" % (exp_dir)
470
+ if version19 == "v1"
471
+ else "%s/3_feature768" % (exp_dir)
472
+ )
473
+ if if_f0_3:
474
+ f0_dir = "%s/2a_f0" % (exp_dir)
475
+ f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)
476
+ names = (
477
+ set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])
478
+ & set([name.split(".")[0] for name in os.listdir(feature_dir)])
479
+ & set([name.split(".")[0] for name in os.listdir(f0_dir)])
480
+ & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])
481
+ )
482
+ else:
483
+ names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(
484
+ [name.split(".")[0] for name in os.listdir(feature_dir)]
485
+ )
486
+ opt = []
487
+ for name in names:
488
+ if if_f0_3:
489
+ opt.append(
490
+ "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"
491
+ % (
492
+ gt_wavs_dir.replace("\\", "\\\\"),
493
+ name,
494
+ feature_dir.replace("\\", "\\\\"),
495
+ name,
496
+ f0_dir.replace("\\", "\\\\"),
497
+ name,
498
+ f0nsf_dir.replace("\\", "\\\\"),
499
+ name,
500
+ spk_id5,
501
+ )
502
+ )
503
+ else:
504
+ opt.append(
505
+ "%s/%s.wav|%s/%s.npy|%s"
506
+ % (
507
+ gt_wavs_dir.replace("\\", "\\\\"),
508
+ name,
509
+ feature_dir.replace("\\", "\\\\"),
510
+ name,
511
+ spk_id5,
512
+ )
513
+ )
514
+ fea_dim = 256 if version19 == "v1" else 768
515
+ if if_f0_3:
516
+ for _ in range(2):
517
+ opt.append(
518
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s/logs/mute/2a_f0/mute.wav.npy|%s/logs/mute/2b-f0nsf/mute.wav.npy|%s"
519
+ % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)
520
+ )
521
+ else:
522
+ for _ in range(2):
523
+ opt.append(
524
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"
525
+ % (now_dir, sr2, now_dir, fea_dim, spk_id5)
526
+ )
527
+ shuffle(opt)
528
+ with open("%s/filelist.txt" % exp_dir, "w") as f:
529
+ f.write("\n".join(opt))
530
+ logger.debug("Write filelist done")
531
+ # 生成config#无需生成config
532
+ # cmd = python_cmd + " train_nsf_sim_cache_sid_load_pretrain.py -e mi-test -sr 40k -f0 1 -bs 4 -g 0 -te 10 -se 5 -pg pretrained/f0G40k.pth -pd pretrained/f0D40k.pth -l 1 -c 0"
533
+ logger.info("Use gpus: %s", str(gpus16))
534
+ if pretrained_G14 == "":
535
+ logger.info("No pretrained Generator")
536
+ if pretrained_D15 == "":
537
+ logger.info("No pretrained Discriminator")
538
+ if version19 == "v1" or sr2 == "40k":
539
+ config_path = "v1/%s.json" % sr2
540
+ else:
541
+ config_path = "v2/%s.json" % sr2
542
+ config_save_path = os.path.join(exp_dir, "config.json")
543
+ if not pathlib.Path(config_save_path).exists():
544
+ with open(config_save_path, "w", encoding="utf-8") as f:
545
+ json.dump(
546
+ config.json_config[config_path],
547
+ f,
548
+ ensure_ascii=False,
549
+ indent=4,
550
+ sort_keys=True,
551
+ )
552
+ f.write("\n")
553
+ if gpus16:
554
+ cmd = (
555
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
556
+ % (
557
+ config.python_cmd,
558
+ exp_dir1,
559
+ sr2,
560
+ 1 if if_f0_3 else 0,
561
+ batch_size12,
562
+ gpus16,
563
+ total_epoch11,
564
+ save_epoch10,
565
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
566
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
567
+ 1 if if_save_latest13 == i18n("是") else 0,
568
+ 1 if if_cache_gpu17 == i18n("是") else 0,
569
+ 1 if if_save_every_weights18 == i18n("是") else 0,
570
+ version19,
571
+ )
572
+ )
573
+ else:
574
+ cmd = (
575
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
576
+ % (
577
+ config.python_cmd,
578
+ exp_dir1,
579
+ sr2,
580
+ 1 if if_f0_3 else 0,
581
+ batch_size12,
582
+ total_epoch11,
583
+ save_epoch10,
584
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
585
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
586
+ 1 if if_save_latest13 == i18n("是") else 0,
587
+ 1 if if_cache_gpu17 == i18n("是") else 0,
588
+ 1 if if_save_every_weights18 == i18n("是") else 0,
589
+ version19,
590
+ )
591
+ )
592
+ logger.info(cmd)
593
+ p = Popen(cmd, shell=True, cwd=now_dir)
594
+ p.wait()
595
+ return "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"
596
+
597
+
598
+ # but4.click(train_index, [exp_dir1], info3)
599
+ def train_index(exp_dir1, version19):
600
+ # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
601
+ exp_dir = "logs/%s" % (exp_dir1)
602
+ os.makedirs(exp_dir, exist_ok=True)
603
+ feature_dir = (
604
+ "%s/3_feature256" % (exp_dir)
605
+ if version19 == "v1"
606
+ else "%s/3_feature768" % (exp_dir)
607
+ )
608
+ if not os.path.exists(feature_dir):
609
+ return "请先进行特征提取!"
610
+ listdir_res = list(os.listdir(feature_dir))
611
+ if len(listdir_res) == 0:
612
+ return "请先进行特征提取!"
613
+ infos = []
614
+ npys = []
615
+ for name in sorted(listdir_res):
616
+ phone = np.load("%s/%s" % (feature_dir, name))
617
+ npys.append(phone)
618
+ big_npy = np.concatenate(npys, 0)
619
+ big_npy_idx = np.arange(big_npy.shape[0])
620
+ np.random.shuffle(big_npy_idx)
621
+ big_npy = big_npy[big_npy_idx]
622
+ if big_npy.shape[0] > 2e5:
623
+ infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
624
+ yield "\n".join(infos)
625
+ try:
626
+ big_npy = (
627
+ MiniBatchKMeans(
628
+ n_clusters=10000,
629
+ verbose=True,
630
+ batch_size=256 * config.n_cpu,
631
+ compute_labels=False,
632
+ init="random",
633
+ )
634
+ .fit(big_npy)
635
+ .cluster_centers_
636
+ )
637
+ except:
638
+ info = traceback.format_exc()
639
+ logger.info(info)
640
+ infos.append(info)
641
+ yield "\n".join(infos)
642
+
643
+ np.save("%s/total_fea.npy" % exp_dir, big_npy)
644
+ n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
645
+ infos.append("%s,%s" % (big_npy.shape, n_ivf))
646
+ yield "\n".join(infos)
647
+ index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
648
+ # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)
649
+ infos.append("training")
650
+ yield "\n".join(infos)
651
+ index_ivf = faiss.extract_index_ivf(index) #
652
+ index_ivf.nprobe = 1
653
+ index.train(big_npy)
654
+ faiss.write_index(
655
+ index,
656
+ "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"
657
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
658
+ )
659
+
660
+ infos.append("adding")
661
+ yield "\n".join(infos)
662
+ batch_size_add = 8192
663
+ for i in range(0, big_npy.shape[0], batch_size_add):
664
+ index.add(big_npy[i : i + batch_size_add])
665
+ faiss.write_index(
666
+ index,
667
+ "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"
668
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
669
+ )
670
+ infos.append(
671
+ "成功构建索引,added_IVF%s_Flat_nprobe_%s_%s_%s.index"
672
+ % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
673
+ )
674
+ # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))
675
+ # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))
676
+ yield "\n".join(infos)
677
+
678
+
679
+ # but5.click(train1key, [exp_dir1, sr2, if_f0_3, trainset_dir4, spk_id5, gpus6, np7, f0method8, save_epoch10, total_epoch11, batch_size12, if_save_latest13, pretrained_G14, pretrained_D15, gpus16, if_cache_gpu17], info3)
680
+ def train1key(
681
+ exp_dir1,
682
+ sr2,
683
+ if_f0_3,
684
+ trainset_dir4,
685
+ spk_id5,
686
+ np7,
687
+ f0method8,
688
+ save_epoch10,
689
+ total_epoch11,
690
+ batch_size12,
691
+ if_save_latest13,
692
+ pretrained_G14,
693
+ pretrained_D15,
694
+ gpus16,
695
+ if_cache_gpu17,
696
+ if_save_every_weights18,
697
+ version19,
698
+ gpus_rmvpe,
699
+ ):
700
+ infos = []
701
+
702
+ def get_info_str(strr):
703
+ infos.append(strr)
704
+ return "\n".join(infos)
705
+
706
+ ####### step1:处理数据
707
+ yield get_info_str(i18n("step1:正在处理数据"))
708
+ [get_info_str(_) for _ in preprocess_dataset(trainset_dir4, exp_dir1, sr2, np7)]
709
+
710
+ ####### step2a:提取音高
711
+ yield get_info_str(i18n("step2:正在提取音高&正在提取特征"))
712
+ [
713
+ get_info_str(_)
714
+ for _ in extract_f0_feature(
715
+ gpus16, np7, f0method8, if_f0_3, exp_dir1, version19, gpus_rmvpe
716
+ )
717
+ ]
718
+
719
+ ####### step3a:训练模型
720
+ yield get_info_str(i18n("step3a:正在训练模型"))
721
+ click_train(
722
+ exp_dir1,
723
+ sr2,
724
+ if_f0_3,
725
+ spk_id5,
726
+ save_epoch10,
727
+ total_epoch11,
728
+ batch_size12,
729
+ if_save_latest13,
730
+ pretrained_G14,
731
+ pretrained_D15,
732
+ gpus16,
733
+ if_cache_gpu17,
734
+ if_save_every_weights18,
735
+ version19,
736
+ )
737
+ yield get_info_str(i18n("训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"))
738
+
739
+ ####### step3b:训练索引
740
+ [get_info_str(_) for _ in train_index(exp_dir1, version19)]
741
+ yield get_info_str(i18n("全流程结束!"))
742
+
743
+
744
+ # ckpt_path2.change(change_info_,[ckpt_path2],[sr__,if_f0__])
745
+ def change_info_(ckpt_path):
746
+ if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):
747
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
748
+ try:
749
+ with open(
750
+ ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"
751
+ ) as f:
752
+ info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])
753
+ sr, f0 = info["sample_rate"], info["if_f0"]
754
+ version = "v2" if ("version" in info and info["version"] == "v2") else "v1"
755
+ return sr, str(f0), version
756
+ except:
757
+ traceback.print_exc()
758
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
759
+
760
+
761
+ F0GPUVisible = config.dml == False
762
+
763
+
764
+ def change_f0_method(f0method8):
765
+ if f0method8 == "rmvpe_gpu":
766
+ visible = F0GPUVisible
767
+ else:
768
+ visible = False
769
+ return {"visible": visible, "__type__": "update"}
770
+
771
+ def find_model():
772
+ if len(names) > 0:
773
+ vc.get_vc(sorted(names)[0],None,None)
774
+ return sorted(names)[0]
775
+ else:
776
+ try:
777
+ gr.Info("Do not forget to choose a model.")
778
+ except:
779
+ pass
780
+ return ''
781
+
782
+ def find_audios(index=False):
783
+ audio_files=[]
784
+ if not os.path.exists('./audios'): os.mkdir("./audios")
785
+ for filename in os.listdir("./audios"):
786
+ if filename.endswith(('.wav','.mp3','.ogg')):
787
+ audio_files.append("./audios/"+filename)
788
+ if index:
789
+ if len(audio_files) > 0: return sorted(audio_files)[0]
790
+ else: return ""
791
+ elif len(audio_files) > 0: return sorted(audio_files)
792
+ else: return []
793
+
794
+ def get_index():
795
+ if find_model() != '':
796
+ chosen_model=sorted(names)[0].split(".")[0]
797
+ logs_path="./logs/"+chosen_model
798
+ if os.path.exists(logs_path):
799
+ for file in os.listdir(logs_path):
800
+ if file.endswith(".index"):
801
+ return os.path.join(logs_path, file)
802
+ return ''
803
+ else:
804
+ return ''
805
+
806
+ def get_indexes():
807
+ indexes_list=[]
808
+ for dirpath, dirnames, filenames in os.walk("./logs/"):
809
+ for filename in filenames:
810
+ if filename.endswith(".index"):
811
+ indexes_list.append(os.path.join(dirpath,filename))
812
+ if len(indexes_list) > 0:
813
+ return indexes_list
814
+ else:
815
+ return ''
816
+
817
+ def save_wav(file):
818
+ try:
819
+ file_path=file.name
820
+ shutil.move(file_path,'./audios')
821
+ return './audios/'+os.path.basename(file_path)
822
+ except AttributeError:
823
+ try:
824
+ new_name = 'kpop'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")+'.wav'
825
+ new_path='./audios/'+new_name
826
+ shutil.move(file,new_path)
827
+ return new_path
828
+ except TypeError:
829
+ return None
830
+
831
+ def download_from_url(url, model):
832
+ if url == '':
833
+ return "URL cannot be left empty."
834
+ if model =='':
835
+ return "You need to name your model. For example: My-Model"
836
+ url = url.strip()
837
+ zip_dirs = ["zips", "unzips"]
838
+ for directory in zip_dirs:
839
+ if os.path.exists(directory):
840
+ shutil.rmtree(directory)
841
+ os.makedirs("zips", exist_ok=True)
842
+ os.makedirs("unzips", exist_ok=True)
843
+ zipfile = model + '.zip'
844
+ zipfile_path = './zips/' + zipfile
845
+ try:
846
+ if "drive.google.com" in url:
847
+ subprocess.run(["gdown", url, "--fuzzy", "-O", zipfile_path])
848
+ elif "mega.nz" in url:
849
+ m = Mega()
850
+ m.download_url(url, './zips')
851
+ else:
852
+ subprocess.run(["wget", url, "-O", zipfile_path])
853
+ for filename in os.listdir("./zips"):
854
+ if filename.endswith(".zip"):
855
+ zipfile_path = os.path.join("./zips/",filename)
856
+ shutil.unpack_archive(zipfile_path, "./unzips", 'zip')
857
+ else:
858
+ return "No zipfile found."
859
+ for root, dirs, files in os.walk('./unzips'):
860
+ for file in files:
861
+ file_path = os.path.join(root, file)
862
+ if file.endswith(".index"):
863
+ os.mkdir(f'./logs/{model}')
864
+ shutil.copy2(file_path,f'./logs/{model}')
865
+ elif "G_" not in file and "D_" not in file and file.endswith(".pth"):
866
+ shutil.copy(file_path,f'./assets/weights/{model}.pth')
867
+ shutil.rmtree("zips")
868
+ shutil.rmtree("unzips")
869
+ return "Success."
870
+ except:
871
+ return "There's been an error."
872
+
873
+ def upload_to_dataset(files, dir):
874
+ if dir == '':
875
+ dir = './dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
876
+ if not os.path.exists(dir):
877
+ os.makedirs(dir)
878
+ for file in files:
879
+ path=file.name
880
+ shutil.copy2(path,dir)
881
+ try:
882
+ gr.Info(i18n("处理数据"))
883
+ except:
884
+ pass
885
+ return i18n("处理数据"), {"value":dir,"__type__":"update"}
886
+
887
+ def download_model_files(model):
888
+ model_found = False
889
+ index_found = False
890
+ if os.path.exists(f'./assets/weights/{model}.pth'): model_found = True
891
+ if os.path.exists(f'./logs/{model}'):
892
+ for file in os.listdir(f'./logs/{model}'):
893
+ if file.endswith('.index') and 'added' in file:
894
+ log_file = file
895
+ index_found = True
896
+ if model_found and index_found:
897
+ return [f'./assets/weights/{model}.pth', f'./logs/{model}/{log_file}'], "Done"
898
+ elif model_found and not index_found:
899
+ return f'./assets/weights/{model}.pth', "Could not find Index file."
900
+ elif index_found and not model_found:
901
+ return f'./logs/{model}/{log_file}', f'Make sure the Voice Name is correct. I could not find {model}.pth'
902
+ else:
903
+ return None, f'Could not find {model}.pth or corresponding Index file.'
904
+
905
+ with gr.Blocks(title="KPOPEASYGUI 🔊",theme=gr.themes.Base(primary_hue="rose", secondary_hue="pink", neutral_hue="slate")) as app:
906
+ with gr.Row():
907
+ gr.HTML("<img src='file/lp.gif' alt='image/gif'>")
908
+ with gr.Tabs():
909
+ with gr.TabItem(i18n("模型推理")):
910
+ with gr.Row():
911
+ sid0 = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names), value=find_model())
912
+ refresh_button = gr.Button(i18n("刷新音色列表和索引路径"), variant="primary")
913
+ #clean_button = gr.Button(i18n("卸载音色省显存"), variant="primary")
914
+ spk_item = gr.Slider(
915
+ minimum=0,
916
+ maximum=2333,
917
+ step=1,
918
+ label=i18n("请选择说话人id"),
919
+ value=0,
920
+ visible=False,
921
+ interactive=True,
922
+ )
923
+ #clean_button.click(
924
+ # fn=clean, inputs=[], outputs=[sid0], api_name="infer_clean"
925
+ #)
926
+ vc_transform0 = gr.Number(
927
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
928
+ )
929
+ but0 = gr.Button(i18n("转换"), variant="primary")
930
+ with gr.Row():
931
+ with gr.Column():
932
+ with gr.Row():
933
+ dropbox = gr.File(label="Drop your audio here & hit the Reload button.")
934
+ with gr.Row():
935
+ record_button=gr.Audio(source="microphone", label="OR Record audio.", type="filepath")
936
+ with gr.Row():
937
+ input_audio0 = gr.Dropdown(
938
+ label=i18n("输入待处理音频文件路径(默认是正确格式示例)"),
939
+ value=find_audios(True),
940
+ choices=find_audios()
941
+ )
942
+ record_button.change(fn=save_wav, inputs=[record_button], outputs=[input_audio0])
943
+ dropbox.upload(fn=save_wav, inputs=[dropbox], outputs=[input_audio0])
944
+ with gr.Column():
945
+ with gr.Accordion(label=i18n("自动检测index路径,下拉式选择(dropdown)"), open=False):
946
+ file_index2 = gr.Dropdown(
947
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
948
+ choices=get_indexes(),
949
+ interactive=True,
950
+ value=get_index()
951
+ )
952
+ index_rate1 = gr.Slider(
953
+ minimum=0,
954
+ maximum=1,
955
+ label=i18n("检索特征占比"),
956
+ value=0.66,
957
+ interactive=True,
958
+ )
959
+ vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
960
+ with gr.Accordion(label=i18n("常规设置"), open=False):
961
+ f0method0 = gr.Radio(
962
+ label=i18n(
963
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
964
+ ),
965
+ choices=["pm", "harvest", "crepe", "rmvpe"]
966
+ if config.dml == False
967
+ else ["pm", "harvest", "rmvpe"],
968
+ value="rmvpe",
969
+ interactive=True,
970
+ )
971
+ filter_radius0 = gr.Slider(
972
+ minimum=0,
973
+ maximum=7,
974
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
975
+ value=3,
976
+ step=1,
977
+ interactive=True,
978
+ )
979
+ resample_sr0 = gr.Slider(
980
+ minimum=0,
981
+ maximum=48000,
982
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
983
+ value=0,
984
+ step=1,
985
+ interactive=True,
986
+ visible=False
987
+ )
988
+ rms_mix_rate0 = gr.Slider(
989
+ minimum=0,
990
+ maximum=1,
991
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
992
+ value=0.21,
993
+ interactive=True,
994
+ )
995
+ protect0 = gr.Slider(
996
+ minimum=0,
997
+ maximum=0.5,
998
+ label=i18n(
999
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
1000
+ ),
1001
+ value=0.33,
1002
+ step=0.01,
1003
+ interactive=True,
1004
+ )
1005
+ file_index1 = gr.Textbox(
1006
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
1007
+ value="",
1008
+ interactive=True,
1009
+ visible=False
1010
+ )
1011
+ refresh_button.click(
1012
+ fn=change_choices,
1013
+ inputs=[],
1014
+ outputs=[sid0, file_index2, input_audio0],
1015
+ api_name="infer_refresh",
1016
+ )
1017
+ # file_big_npy1 = gr.Textbox(
1018
+ # label=i18n("特征文件路径"),
1019
+ # value="E:\\codes\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1020
+ # interactive=True,
1021
+ # )
1022
+ with gr.Row():
1023
+ f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"), visible=False)
1024
+ with gr.Row():
1025
+ vc_output1 = gr.Textbox(label=i18n("输出信息"))
1026
+ but0.click(
1027
+ vc.vc_single,
1028
+ [
1029
+ spk_item,
1030
+ input_audio0,
1031
+ vc_transform0,
1032
+ f0_file,
1033
+ f0method0,
1034
+ file_index1,
1035
+ file_index2,
1036
+ # file_big_npy1,
1037
+ index_rate1,
1038
+ filter_radius0,
1039
+ resample_sr0,
1040
+ rms_mix_rate0,
1041
+ protect0,
1042
+ ],
1043
+ [vc_output1, vc_output2],
1044
+ api_name="infer_convert",
1045
+ )
1046
+ with gr.Row():
1047
+ with gr.Accordion(open=False, label=i18n("批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ")):
1048
+ with gr.Row():
1049
+ opt_input = gr.Textbox(label=i18n("指定输出文件夹"), value="opt")
1050
+ vc_transform1 = gr.Number(
1051
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
1052
+ )
1053
+ f0method1 = gr.Radio(
1054
+ label=i18n(
1055
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
1056
+ ),
1057
+ choices=["pm", "harvest", "crepe", "rmvpe"]
1058
+ if config.dml == False
1059
+ else ["pm", "harvest", "rmvpe"],
1060
+ value="pm",
1061
+ interactive=True,
1062
+ )
1063
+ with gr.Row():
1064
+ filter_radius1 = gr.Slider(
1065
+ minimum=0,
1066
+ maximum=7,
1067
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
1068
+ value=3,
1069
+ step=1,
1070
+ interactive=True,
1071
+ visible=False
1072
+ )
1073
+ with gr.Row():
1074
+ file_index3 = gr.Textbox(
1075
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
1076
+ value="",
1077
+ interactive=True,
1078
+ visible=False
1079
+ )
1080
+ file_index4 = gr.Dropdown(
1081
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
1082
+ choices=sorted(index_paths),
1083
+ interactive=True,
1084
+ visible=False
1085
+ )
1086
+ refresh_button.click(
1087
+ fn=lambda: change_choices()[1],
1088
+ inputs=[],
1089
+ outputs=file_index4,
1090
+ api_name="infer_refresh_batch",
1091
+ )
1092
+ # file_big_npy2 = gr.Textbox(
1093
+ # label=i18n("特征文件路径"),
1094
+ # value="E:\\codes\\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
1095
+ # interactive=True,
1096
+ # )
1097
+ index_rate2 = gr.Slider(
1098
+ minimum=0,
1099
+ maximum=1,
1100
+ label=i18n("检索特征占比"),
1101
+ value=1,
1102
+ interactive=True,
1103
+ visible=False
1104
+ )
1105
+ with gr.Row():
1106
+ resample_sr1 = gr.Slider(
1107
+ minimum=0,
1108
+ maximum=48000,
1109
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
1110
+ value=0,
1111
+ step=1,
1112
+ interactive=True,
1113
+ visible=False
1114
+ )
1115
+ rms_mix_rate1 = gr.Slider(
1116
+ minimum=0,
1117
+ maximum=1,
1118
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
1119
+ value=0.21,
1120
+ interactive=True,
1121
+ )
1122
+ protect1 = gr.Slider(
1123
+ minimum=0,
1124
+ maximum=0.5,
1125
+ label=i18n(
1126
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
1127
+ ),
1128
+ value=0.33,
1129
+ step=0.01,
1130
+ interactive=True,
1131
+ )
1132
+ with gr.Row():
1133
+ dir_input = gr.Textbox(
1134
+ label=i18n("输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)"),
1135
+ value="./audios",
1136
+ )
1137
+ inputs = gr.File(
1138
+ file_count="multiple", label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹")
1139
+ )
1140
+ with gr.Row():
1141
+ format1 = gr.Radio(
1142
+ label=i18n("导出文件格式"),
1143
+ choices=["wav", "flac", "mp3", "m4a"],
1144
+ value="wav",
1145
+ interactive=True,
1146
+ )
1147
+ but1 = gr.Button(i18n("转换"), variant="primary")
1148
+ vc_output3 = gr.Textbox(label=i18n("输出信息"))
1149
+ but1.click(
1150
+ vc.vc_multi,
1151
+ [
1152
+ spk_item,
1153
+ dir_input,
1154
+ opt_input,
1155
+ inputs,
1156
+ vc_transform1,
1157
+ f0method1,
1158
+ file_index1,
1159
+ file_index2,
1160
+ # file_big_npy2,
1161
+ index_rate1,
1162
+ filter_radius1,
1163
+ resample_sr1,
1164
+ rms_mix_rate1,
1165
+ protect1,
1166
+ format1,
1167
+ ],
1168
+ [vc_output3],
1169
+ api_name="infer_convert_batch",
1170
+ )
1171
+ sid0.change(
1172
+ fn=vc.get_vc,
1173
+ inputs=[sid0, protect0, protect1],
1174
+ outputs=[spk_item, protect0, protect1, file_index2, file_index4],
1175
+ )
1176
+ with gr.TabItem("Download Model"):
1177
+ with gr.Row():
1178
+ gr.Markdown(
1179
+ """
1180
+ ⚠️ Google Drive Links, V1 models, and some leelo models will not work with this gradio ⚠️
1181
+ """
1182
+ )
1183
+ with gr.Row():
1184
+ url=gr.Textbox(label="Enter the URL to the Model:")
1185
+ with gr.Row():
1186
+ model = gr.Textbox(label="Name your model:")
1187
+ download_button=gr.Button("Download")
1188
+ with gr.Row():
1189
+ status_bar=gr.Textbox(label="")
1190
+ download_button.click(fn=download_from_url, inputs=[url, model], outputs=[status_bar])
1191
+ with gr.Row():
1192
+ gr.Markdown(
1193
+ """
1194
+ ❤️ Support Original Creator from this easyGUI ❤️
1195
+ paypal.me/lesantillan
1196
+ """
1197
+ )
1198
+ with gr.TabItem(i18n("训练")):
1199
+ with gr.Row():
1200
+ with gr.Column():
1201
+ exp_dir1 = gr.Textbox(label=i18n("输入实验名"), value="My-Voice")
1202
+ np7 = gr.Slider(
1203
+ minimum=0,
1204
+ maximum=config.n_cpu,
1205
+ step=1,
1206
+ label=i18n("提取音高和处理数据使用的CPU进程数"),
1207
+ value=int(np.ceil(config.n_cpu / 1.5)),
1208
+ interactive=True,
1209
+ )
1210
+ sr2 = gr.Radio(
1211
+ label=i18n("目标采样率"),
1212
+ choices=["40k", "48k"],
1213
+ value="40k",
1214
+ interactive=True,
1215
+ visible=False
1216
+ )
1217
+ if_f0_3 = gr.Radio(
1218
+ label=i18n("模型是否带音高指导(唱歌一定要, 语音可以不要)"),
1219
+ choices=[True, False],
1220
+ value=True,
1221
+ interactive=True,
1222
+ visible=False
1223
+ )
1224
+ version19 = gr.Radio(
1225
+ label=i18n("版本"),
1226
+ choices=["v1", "v2"],
1227
+ value="v2",
1228
+ interactive=True,
1229
+ visible=False,
1230
+ )
1231
+ trainset_dir4 = gr.Textbox(
1232
+ label=i18n("输入训练文件夹路径"), value='./dataset/'+datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
1233
+ )
1234
+ easy_uploader = gr.Files(label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹"),file_types=['audio'])
1235
+ but1 = gr.Button(i18n("处理数据"), variant="primary")
1236
+ info1 = gr.Textbox(label=i18n("输出信息"), value="")
1237
+ easy_uploader.upload(fn=upload_to_dataset, inputs=[easy_uploader, trainset_dir4], outputs=[info1, trainset_dir4])
1238
+ gpus6 = gr.Textbox(
1239
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1240
+ value=gpus,
1241
+ interactive=True,
1242
+ visible=F0GPUVisible,
1243
+ )
1244
+ gpu_info9 = gr.Textbox(
1245
+ label=i18n("显卡信息"), value=gpu_info, visible=F0GPUVisible
1246
+ )
1247
+ spk_id5 = gr.Slider(
1248
+ minimum=0,
1249
+ maximum=4,
1250
+ step=1,
1251
+ label=i18n("请指定说话人id"),
1252
+ value=0,
1253
+ interactive=True,
1254
+ visible=False
1255
+ )
1256
+ but1.click(
1257
+ preprocess_dataset,
1258
+ [trainset_dir4, exp_dir1, sr2, np7],
1259
+ [info1],
1260
+ api_name="train_preprocess",
1261
+ )
1262
+ with gr.Column():
1263
+ f0method8 = gr.Radio(
1264
+ label=i18n(
1265
+ "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢,rmvpe效果最好且微吃CPU/GPU"
1266
+ ),
1267
+ choices=["pm", "harvest", "dio", "rmvpe", "rmvpe_gpu"],
1268
+ value="rmvpe_gpu",
1269
+ interactive=True,
1270
+ )
1271
+ gpus_rmvpe = gr.Textbox(
1272
+ label=i18n(
1273
+ "rmvpe卡号配置:以-分隔输入使用的不同进程卡号,例如0-0-1使用在卡0上跑2个进程并在卡1上跑1个进程"
1274
+ ),
1275
+ value="%s-%s" % (gpus, gpus),
1276
+ interactive=True,
1277
+ visible=F0GPUVisible,
1278
+ )
1279
+ but2 = gr.Button(i18n("特征提取"), variant="primary")
1280
+ info2 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1281
+ f0method8.change(
1282
+ fn=change_f0_method,
1283
+ inputs=[f0method8],
1284
+ outputs=[gpus_rmvpe],
1285
+ )
1286
+ but2.click(
1287
+ extract_f0_feature,
1288
+ [
1289
+ gpus6,
1290
+ np7,
1291
+ f0method8,
1292
+ if_f0_3,
1293
+ exp_dir1,
1294
+ version19,
1295
+ gpus_rmvpe,
1296
+ ],
1297
+ [info2],
1298
+ api_name="train_extract_f0_feature",
1299
+ )
1300
+ with gr.Column():
1301
+ total_epoch11 = gr.Slider(
1302
+ minimum=2,
1303
+ maximum=1000,
1304
+ step=1,
1305
+ label=i18n("总训练轮数total_epoch"),
1306
+ value=150,
1307
+ interactive=True,
1308
+ )
1309
+ gpus16 = gr.Textbox(
1310
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1311
+ value="0",
1312
+ interactive=True,
1313
+ visible=True
1314
+ )
1315
+ but3 = gr.Button(i18n("训练模型"), variant="primary")
1316
+ but4 = gr.Button(i18n("训练特征索引"), variant="primary")
1317
+ info3 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=10)
1318
+ with gr.Accordion(label=i18n("常规设置"), open=False):
1319
+ save_epoch10 = gr.Slider(
1320
+ minimum=1,
1321
+ maximum=50,
1322
+ step=1,
1323
+ label=i18n("保存频率save_every_epoch"),
1324
+ value=25,
1325
+ interactive=True,
1326
+ )
1327
+ batch_size12 = gr.Slider(
1328
+ minimum=1,
1329
+ maximum=40,
1330
+ step=1,
1331
+ label=i18n("每张显卡的batch_size"),
1332
+ value=default_batch_size,
1333
+ interactive=True,
1334
+ )
1335
+ if_save_latest13 = gr.Radio(
1336
+ label=i18n("是否仅保存最新的ckpt文件以节省硬盘空间"),
1337
+ choices=[i18n("是"), i18n("否")],
1338
+ value=i18n("是"),
1339
+ interactive=True,
1340
+ visible=False
1341
+ )
1342
+ if_cache_gpu17 = gr.Radio(
1343
+ label=i18n(
1344
+ "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速"
1345
+ ),
1346
+ choices=[i18n("是"), i18n("否")],
1347
+ value=i18n("否"),
1348
+ interactive=True,
1349
+ )
1350
+ if_save_every_weights18 = gr.Radio(
1351
+ label=i18n("是否在每次保存时间点将最终小模型保存至weights文件夹"),
1352
+ choices=[i18n("是"), i18n("否")],
1353
+ value=i18n("是"),
1354
+ interactive=True,
1355
+ )
1356
+ with gr.Row():
1357
+ download_model = gr.Button('5.Download Model')
1358
+ with gr.Row():
1359
+ model_files = gr.Files(label='Your Model and Index file can be downloaded here:')
1360
+ download_model.click(fn=download_model_files, inputs=[exp_dir1], outputs=[model_files, info3])
1361
+ with gr.Row():
1362
+ pretrained_G14 = gr.Textbox(
1363
+ label=i18n("加载预训练底模G路径"),
1364
+ value="assets/pretrained_v2/f0G40k.pth",
1365
+ interactive=True,
1366
+ visible=False
1367
+ )
1368
+ pretrained_D15 = gr.Textbox(
1369
+ label=i18n("加载预训练底模D路径"),
1370
+ value="assets/pretrained_v2/f0D40k.pth",
1371
+ interactive=True,
1372
+ visible=False
1373
+ )
1374
+ sr2.change(
1375
+ change_sr2,
1376
+ [sr2, if_f0_3, version19],
1377
+ [pretrained_G14, pretrained_D15],
1378
+ )
1379
+ version19.change(
1380
+ change_version19,
1381
+ [sr2, if_f0_3, version19],
1382
+ [pretrained_G14, pretrained_D15, sr2],
1383
+ )
1384
+ if_f0_3.change(
1385
+ change_f0,
1386
+ [if_f0_3, sr2, version19],
1387
+ [f0method8, pretrained_G14, pretrained_D15],
1388
+ )
1389
+ with gr.Row():
1390
+ but5 = gr.Button(i18n("一键训练"), variant="primary", visible=False)
1391
+ but3.click(
1392
+ click_train,
1393
+ [
1394
+ exp_dir1,
1395
+ sr2,
1396
+ if_f0_3,
1397
+ spk_id5,
1398
+ save_epoch10,
1399
+ total_epoch11,
1400
+ batch_size12,
1401
+ if_save_latest13,
1402
+ pretrained_G14,
1403
+ pretrained_D15,
1404
+ gpus16,
1405
+ if_cache_gpu17,
1406
+ if_save_every_weights18,
1407
+ version19,
1408
+ ],
1409
+ info3,
1410
+ api_name="train_start",
1411
+ )
1412
+ but4.click(train_index, [exp_dir1, version19], info3)
1413
+ but5.click(
1414
+ train1key,
1415
+ [
1416
+ exp_dir1,
1417
+ sr2,
1418
+ if_f0_3,
1419
+ trainset_dir4,
1420
+ spk_id5,
1421
+ np7,
1422
+ f0method8,
1423
+ save_epoch10,
1424
+ total_epoch11,
1425
+ batch_size12,
1426
+ if_save_latest13,
1427
+ pretrained_G14,
1428
+ pretrained_D15,
1429
+ gpus16,
1430
+ if_cache_gpu17,
1431
+ if_save_every_weights18,
1432
+ version19,
1433
+ gpus_rmvpe,
1434
+ ],
1435
+ info3,
1436
+ api_name="train_start_all",
1437
+ )
1438
+
1439
+ if config.iscolab:
1440
+ app.queue(concurrency_count=511, max_size=1022).launch(share=True),
1441
+ favicon_path="file/Logo_of_TWICE.svg.png"
1442
+ else:
1443
+ app.queue(concurrency_count=511, max_size=1022).launch(
1444
+ server_name="0.0.0.0",
1445
+ favicon_path="file/Logo_of_TWICE.svg.png",
1446
+ inbrowser=not config.noautoopen,
1447
+ server_port=config.listen_port,
1448
+ quiet=True,
1449
+ )
docker-compose.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: "3.8"
2
+ services:
3
+ rvc:
4
+ build:
5
+ context: .
6
+ dockerfile: Dockerfile
7
+ container_name: rvc
8
+ volumes:
9
+ - ./weights:/app/assets/weights
10
+ - ./opt:/app/opt
11
+ # - ./dataset:/app/dataset # you can use this folder in order to provide your dataset for model training
12
+ ports:
13
+ - 7865:7865
download_files.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import subprocess, os
2
+ assets_folder = "./assets/"
3
+ if not os.path.exists(assets_folder):
4
+ os.makedirs(assets_folder)
5
+ files = {
6
+ "rmvpe/rmvpe.pt":"https://huggingface.co/Rejekts/project/resolve/main/rmvpe.pt",
7
+ "hubert/hubert_base.pt":"https://huggingface.co/Rejekts/project/resolve/main/hubert_base.pt",
8
+ "pretrained_v2/D40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/D40k.pth",
9
+ "pretrained_v2/G40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/G40k.pth",
10
+ "pretrained_v2/f0D40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/f0D40k.pth",
11
+ "pretrained_v2/f0G40k.pth":"https://huggingface.co/Rejekts/project/resolve/main/f0G40k.pth"
12
+ }
13
+ for file, link in files.items():
14
+ file_path = os.path.join(assets_folder, file)
15
+ if not os.path.exists(file_path):
16
+ try:
17
+ subprocess.run(['wget', link, '-O', file_path], check=True)
18
+ except subprocess.CalledProcessError as e:
19
+ print(f"Error downloading {file}: {e}")
environment_dml.yaml ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: pydml
2
+ channels:
3
+ - pytorch
4
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
5
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
6
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
7
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
8
+ - defaults
9
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/fastai/
10
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
11
+ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/bioconda/
12
+ dependencies:
13
+ - abseil-cpp=20211102.0=hd77b12b_0
14
+ - absl-py=1.3.0=py310haa95532_0
15
+ - aiohttp=3.8.3=py310h2bbff1b_0
16
+ - aiosignal=1.2.0=pyhd3eb1b0_0
17
+ - async-timeout=4.0.2=py310haa95532_0
18
+ - attrs=22.1.0=py310haa95532_0
19
+ - blas=1.0=mkl
20
+ - blinker=1.4=py310haa95532_0
21
+ - bottleneck=1.3.5=py310h9128911_0
22
+ - brotli=1.0.9=h2bbff1b_7
23
+ - brotli-bin=1.0.9=h2bbff1b_7
24
+ - brotlipy=0.7.0=py310h2bbff1b_1002
25
+ - bzip2=1.0.8=he774522_0
26
+ - c-ares=1.19.0=h2bbff1b_0
27
+ - ca-certificates=2023.05.30=haa95532_0
28
+ - cachetools=4.2.2=pyhd3eb1b0_0
29
+ - certifi=2023.5.7=py310haa95532_0
30
+ - cffi=1.15.1=py310h2bbff1b_3
31
+ - charset-normalizer=2.0.4=pyhd3eb1b0_0
32
+ - click=8.0.4=py310haa95532_0
33
+ - colorama=0.4.6=py310haa95532_0
34
+ - contourpy=1.0.5=py310h59b6b97_0
35
+ - cryptography=39.0.1=py310h21b164f_0
36
+ - cycler=0.11.0=pyhd3eb1b0_0
37
+ - fonttools=4.25.0=pyhd3eb1b0_0
38
+ - freetype=2.12.1=ha860e81_0
39
+ - frozenlist=1.3.3=py310h2bbff1b_0
40
+ - giflib=5.2.1=h8cc25b3_3
41
+ - glib=2.69.1=h5dc1a3c_2
42
+ - google-auth=2.6.0=pyhd3eb1b0_0
43
+ - google-auth-oauthlib=0.4.4=pyhd3eb1b0_0
44
+ - grpc-cpp=1.48.2=hf108199_0
45
+ - grpcio=1.48.2=py310hf108199_0
46
+ - gst-plugins-base=1.18.5=h9e645db_0
47
+ - gstreamer=1.18.5=hd78058f_0
48
+ - icu=58.2=ha925a31_3
49
+ - idna=3.4=py310haa95532_0
50
+ - intel-openmp=2023.1.0=h59b6b97_46319
51
+ - jpeg=9e=h2bbff1b_1
52
+ - kiwisolver=1.4.4=py310hd77b12b_0
53
+ - krb5=1.19.4=h5b6d351_0
54
+ - lerc=3.0=hd77b12b_0
55
+ - libbrotlicommon=1.0.9=h2bbff1b_7
56
+ - libbrotlidec=1.0.9=h2bbff1b_7
57
+ - libbrotlienc=1.0.9=h2bbff1b_7
58
+ - libclang=14.0.6=default_hb5a9fac_1
59
+ - libclang13=14.0.6=default_h8e68704_1
60
+ - libdeflate=1.17=h2bbff1b_0
61
+ - libffi=3.4.4=hd77b12b_0
62
+ - libiconv=1.16=h2bbff1b_2
63
+ - libogg=1.3.5=h2bbff1b_1
64
+ - libpng=1.6.39=h8cc25b3_0
65
+ - libprotobuf=3.20.3=h23ce68f_0
66
+ - libtiff=4.5.0=h6c2663c_2
67
+ - libuv=1.44.2=h2bbff1b_0
68
+ - libvorbis=1.3.7=he774522_0
69
+ - libwebp=1.2.4=hbc33d0d_1
70
+ - libwebp-base=1.2.4=h2bbff1b_1
71
+ - libxml2=2.10.3=h0ad7f3c_0
72
+ - libxslt=1.1.37=h2bbff1b_0
73
+ - lz4-c=1.9.4=h2bbff1b_0
74
+ - markdown=3.4.1=py310haa95532_0
75
+ - markupsafe=2.1.1=py310h2bbff1b_0
76
+ - matplotlib=3.7.1=py310haa95532_1
77
+ - matplotlib-base=3.7.1=py310h4ed8f06_1
78
+ - mkl=2023.1.0=h8bd8f75_46356
79
+ - mkl-service=2.4.0=py310h2bbff1b_1
80
+ - mkl_fft=1.3.6=py310h4ed8f06_1
81
+ - mkl_random=1.2.2=py310h4ed8f06_1
82
+ - multidict=6.0.2=py310h2bbff1b_0
83
+ - munkres=1.1.4=py_0
84
+ - numexpr=2.8.4=py310h2cd9be0_1
85
+ - numpy=1.24.3=py310h055cbcc_1
86
+ - numpy-base=1.24.3=py310h65a83cf_1
87
+ - oauthlib=3.2.2=py310haa95532_0
88
+ - openssl=1.1.1t=h2bbff1b_0
89
+ - packaging=23.0=py310haa95532_0
90
+ - pandas=1.5.3=py310h4ed8f06_0
91
+ - pcre=8.45=hd77b12b_0
92
+ - pillow=9.4.0=py310hd77b12b_0
93
+ - pip=23.0.1=py310haa95532_0
94
+ - ply=3.11=py310haa95532_0
95
+ - protobuf=3.20.3=py310hd77b12b_0
96
+ - pyasn1=0.4.8=pyhd3eb1b0_0
97
+ - pyasn1-modules=0.2.8=py_0
98
+ - pycparser=2.21=pyhd3eb1b0_0
99
+ - pyjwt=2.4.0=py310haa95532_0
100
+ - pyopenssl=23.0.0=py310haa95532_0
101
+ - pyparsing=3.0.9=py310haa95532_0
102
+ - pyqt=5.15.7=py310hd77b12b_0
103
+ - pyqt5-sip=12.11.0=py310hd77b12b_0
104
+ - pysocks=1.7.1=py310haa95532_0
105
+ - python=3.10.11=h966fe2a_2
106
+ - python-dateutil=2.8.2=pyhd3eb1b0_0
107
+ - pytorch-mutex=1.0=cpu
108
+ - pytz=2022.7=py310haa95532_0
109
+ - pyyaml=6.0=py310h2bbff1b_1
110
+ - qt-main=5.15.2=he8e5bd7_8
111
+ - qt-webengine=5.15.9=hb9a9bb5_5
112
+ - qtwebkit=5.212=h2bbfb41_5
113
+ - re2=2022.04.01=hd77b12b_0
114
+ - requests=2.29.0=py310haa95532_0
115
+ - requests-oauthlib=1.3.0=py_0
116
+ - rsa=4.7.2=pyhd3eb1b0_1
117
+ - setuptools=67.8.0=py310haa95532_0
118
+ - sip=6.6.2=py310hd77b12b_0
119
+ - six=1.16.0=pyhd3eb1b0_1
120
+ - sqlite=3.41.2=h2bbff1b_0
121
+ - tbb=2021.8.0=h59b6b97_0
122
+ - tensorboard=2.10.0=py310haa95532_0
123
+ - tensorboard-data-server=0.6.1=py310haa95532_0
124
+ - tensorboard-plugin-wit=1.8.1=py310haa95532_0
125
+ - tk=8.6.12=h2bbff1b_0
126
+ - toml=0.10.2=pyhd3eb1b0_0
127
+ - tornado=6.2=py310h2bbff1b_0
128
+ - tqdm=4.65.0=py310h9909e9c_0
129
+ - typing_extensions=4.5.0=py310haa95532_0
130
+ - tzdata=2023c=h04d1e81_0
131
+ - urllib3=1.26.16=py310haa95532_0
132
+ - vc=14.2=h21ff451_1
133
+ - vs2015_runtime=14.27.29016=h5e58377_2
134
+ - werkzeug=2.2.3=py310haa95532_0
135
+ - wheel=0.38.4=py310haa95532_0
136
+ - win_inet_pton=1.1.0=py310haa95532_0
137
+ - xz=5.4.2=h8cc25b3_0
138
+ - yaml=0.2.5=he774522_0
139
+ - yarl=1.8.1=py310h2bbff1b_0
140
+ - zlib=1.2.13=h8cc25b3_0
141
+ - zstd=1.5.5=hd43e919_0
142
+ - pip:
143
+ - antlr4-python3-runtime==4.8
144
+ - appdirs==1.4.4
145
+ - audioread==3.0.0
146
+ - bitarray==2.7.4
147
+ - cython==0.29.35
148
+ - decorator==5.1.1
149
+ - fairseq==0.12.2
150
+ - faiss-cpu==1.7.4
151
+ - filelock==3.12.0
152
+ - hydra-core==1.0.7
153
+ - jinja2==3.1.2
154
+ - joblib==1.2.0
155
+ - lazy-loader==0.2
156
+ - librosa==0.10.0.post2
157
+ - llvmlite==0.40.0
158
+ - lxml==4.9.2
159
+ - mpmath==1.3.0
160
+ - msgpack==1.0.5
161
+ - networkx==3.1
162
+ - noisereduce==2.0.1
163
+ - numba==0.57.0
164
+ - omegaconf==2.0.6
165
+ - opencv-python==4.7.0.72
166
+ - pooch==1.6.0
167
+ - portalocker==2.7.0
168
+ - pysimplegui==4.60.5
169
+ - pywin32==306
170
+ - pyworld==0.3.3
171
+ - regex==2023.5.5
172
+ - sacrebleu==2.3.1
173
+ - scikit-learn==1.2.2
174
+ - scipy==1.10.1
175
+ - sounddevice==0.4.6
176
+ - soundfile==0.12.1
177
+ - soxr==0.3.5
178
+ - sympy==1.12
179
+ - tabulate==0.9.0
180
+ - threadpoolctl==3.1.0
181
+ - torch==2.0.0
182
+ - torch-directml==0.2.0.dev230426
183
+ - torchaudio==2.0.1
184
+ - torchvision==0.15.1
185
+ - wget==3.2
186
+ prefix: D:\ProgramData\anaconda3_\envs\pydml
go-realtime-gui-dml.bat ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ runtime\python.exe gui_v1.py --pycmd runtime\python.exe --dml
2
+ pause
go-realtime-gui.bat ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ runtime\python.exe gui_v1.py
2
+ pause
go-web-dml.bat ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ runtime\python.exe infer-web.py --pycmd runtime\python.exe --port 7897 --dml
2
+ pause
go-web.bat ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ runtime\python.exe infer-web.py --pycmd runtime\python.exe --port 7897
2
+ pause
gui_v1.py ADDED
@@ -0,0 +1,708 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import logging
3
+ import sys
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+
8
+ os.environ["OMP_NUM_THREADS"] = "4"
9
+ if sys.platform == "darwin":
10
+ os.environ["PYTORCH_ENABLE_MPS_FALLBACK"] = "1"
11
+
12
+ now_dir = os.getcwd()
13
+ sys.path.append(now_dir)
14
+ import multiprocessing
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ class Harvest(multiprocessing.Process):
20
+ def __init__(self, inp_q, opt_q):
21
+ multiprocessing.Process.__init__(self)
22
+ self.inp_q = inp_q
23
+ self.opt_q = opt_q
24
+
25
+ def run(self):
26
+ import numpy as np
27
+ import pyworld
28
+
29
+ while 1:
30
+ idx, x, res_f0, n_cpu, ts = self.inp_q.get()
31
+ f0, t = pyworld.harvest(
32
+ x.astype(np.double),
33
+ fs=16000,
34
+ f0_ceil=1100,
35
+ f0_floor=50,
36
+ frame_period=10,
37
+ )
38
+ res_f0[idx] = f0
39
+ if len(res_f0.keys()) >= n_cpu:
40
+ self.opt_q.put(ts)
41
+
42
+
43
+ if __name__ == "__main__":
44
+ import json
45
+ import multiprocessing
46
+ import re
47
+ import threading
48
+ import time
49
+ import traceback
50
+ from multiprocessing import Queue, cpu_count
51
+ from queue import Empty
52
+
53
+ import librosa
54
+ from tools.torchgate import TorchGate
55
+ import numpy as np
56
+ import PySimpleGUI as sg
57
+ import sounddevice as sd
58
+ import torch
59
+ import torch.nn.functional as F
60
+ import torchaudio.transforms as tat
61
+
62
+ import tools.rvc_for_realtime as rvc_for_realtime
63
+ from i18n.i18n import I18nAuto
64
+
65
+ i18n = I18nAuto()
66
+ device = rvc_for_realtime.config.device
67
+ # device = torch.device(
68
+ # "cuda"
69
+ # if torch.cuda.is_available()
70
+ # else ("mps" if torch.backends.mps.is_available() else "cpu")
71
+ # )
72
+ current_dir = os.getcwd()
73
+ inp_q = Queue()
74
+ opt_q = Queue()
75
+ n_cpu = min(cpu_count(), 8)
76
+ for _ in range(n_cpu):
77
+ Harvest(inp_q, opt_q).start()
78
+
79
+ class GUIConfig:
80
+ def __init__(self) -> None:
81
+ self.pth_path: str = ""
82
+ self.index_path: str = ""
83
+ self.pitch: int = 0
84
+ self.samplerate: int = 40000
85
+ self.block_time: float = 1.0 # s
86
+ self.buffer_num: int = 1
87
+ self.threhold: int = -60
88
+ self.crossfade_time: float = 0.04
89
+ self.extra_time: float = 2.0
90
+ self.I_noise_reduce = False
91
+ self.O_noise_reduce = False
92
+ self.rms_mix_rate = 0.0
93
+ self.index_rate = 0.3
94
+ self.n_cpu = min(n_cpu, 6)
95
+ self.f0method = "harvest"
96
+ self.sg_input_device = ""
97
+ self.sg_output_device = ""
98
+
99
+ class GUI:
100
+ def __init__(self) -> None:
101
+ self.config = GUIConfig()
102
+ self.flag_vc = False
103
+
104
+ self.launcher()
105
+
106
+ def load(self):
107
+ input_devices, output_devices, _, _ = self.get_devices()
108
+ try:
109
+ with open("configs/config.json", "r") as j:
110
+ data = json.load(j)
111
+ data["pm"] = data["f0method"] == "pm"
112
+ data["harvest"] = data["f0method"] == "harvest"
113
+ data["crepe"] = data["f0method"] == "crepe"
114
+ data["rmvpe"] = data["f0method"] == "rmvpe"
115
+ except:
116
+ with open("configs/config.json", "w") as j:
117
+ data = {
118
+ "pth_path": " ",
119
+ "index_path": " ",
120
+ "sg_input_device": input_devices[sd.default.device[0]],
121
+ "sg_output_device": output_devices[sd.default.device[1]],
122
+ "threhold": "-60",
123
+ "pitch": "0",
124
+ "index_rate": "0",
125
+ "rms_mix_rate": "0",
126
+ "block_time": "0.25",
127
+ "crossfade_length": "0.04",
128
+ "extra_time": "2",
129
+ "f0method": "rmvpe",
130
+ }
131
+ data["pm"] = data["f0method"] == "pm"
132
+ data["harvest"] = data["f0method"] == "harvest"
133
+ data["crepe"] = data["f0method"] == "crepe"
134
+ data["rmvpe"] = data["f0method"] == "rmvpe"
135
+ return data
136
+
137
+ def launcher(self):
138
+ data = self.load()
139
+ sg.theme("LightBlue3")
140
+ input_devices, output_devices, _, _ = self.get_devices()
141
+ layout = [
142
+ [
143
+ sg.Frame(
144
+ title=i18n("加载模型"),
145
+ layout=[
146
+ [
147
+ sg.Input(
148
+ default_text=data.get("pth_path", ""),
149
+ key="pth_path",
150
+ ),
151
+ sg.FileBrowse(
152
+ i18n("选择.pth文件"),
153
+ initial_folder=os.path.join(
154
+ os.getcwd(), "assets/weights"
155
+ ),
156
+ file_types=((". pth"),),
157
+ ),
158
+ ],
159
+ [
160
+ sg.Input(
161
+ default_text=data.get("index_path", ""),
162
+ key="index_path",
163
+ ),
164
+ sg.FileBrowse(
165
+ i18n("选择.index文件"),
166
+ initial_folder=os.path.join(os.getcwd(), "logs"),
167
+ file_types=((". index"),),
168
+ ),
169
+ ],
170
+ ],
171
+ )
172
+ ],
173
+ [
174
+ sg.Frame(
175
+ layout=[
176
+ [
177
+ sg.Text(i18n("输入设备")),
178
+ sg.Combo(
179
+ input_devices,
180
+ key="sg_input_device",
181
+ default_value=data.get("sg_input_device", ""),
182
+ ),
183
+ ],
184
+ [
185
+ sg.Text(i18n("输出设备")),
186
+ sg.Combo(
187
+ output_devices,
188
+ key="sg_output_device",
189
+ default_value=data.get("sg_output_device", ""),
190
+ ),
191
+ ],
192
+ [sg.Button(i18n("重载设备列表"), key="reload_devices")],
193
+ ],
194
+ title=i18n("音频设备(请使用同种类驱动)"),
195
+ )
196
+ ],
197
+ [
198
+ sg.Frame(
199
+ layout=[
200
+ [
201
+ sg.Text(i18n("响应阈值")),
202
+ sg.Slider(
203
+ range=(-60, 0),
204
+ key="threhold",
205
+ resolution=1,
206
+ orientation="h",
207
+ default_value=data.get("threhold", "-60"),
208
+ enable_events=True,
209
+ ),
210
+ ],
211
+ [
212
+ sg.Text(i18n("音调设置")),
213
+ sg.Slider(
214
+ range=(-24, 24),
215
+ key="pitch",
216
+ resolution=1,
217
+ orientation="h",
218
+ default_value=data.get("pitch", "0"),
219
+ enable_events=True,
220
+ ),
221
+ ],
222
+ [
223
+ sg.Text(i18n("Index Rate")),
224
+ sg.Slider(
225
+ range=(0.0, 1.0),
226
+ key="index_rate",
227
+ resolution=0.01,
228
+ orientation="h",
229
+ default_value=data.get("index_rate", "0"),
230
+ enable_events=True,
231
+ ),
232
+ ],
233
+ [
234
+ sg.Text(i18n("响度因子")),
235
+ sg.Slider(
236
+ range=(0.0, 1.0),
237
+ key="rms_mix_rate",
238
+ resolution=0.01,
239
+ orientation="h",
240
+ default_value=data.get("rms_mix_rate", "0"),
241
+ enable_events=True,
242
+ ),
243
+ ],
244
+ [
245
+ sg.Text(i18n("音高算法")),
246
+ sg.Radio(
247
+ "pm",
248
+ "f0method",
249
+ key="pm",
250
+ default=data.get("pm", "") == True,
251
+ enable_events=True,
252
+ ),
253
+ sg.Radio(
254
+ "harvest",
255
+ "f0method",
256
+ key="harvest",
257
+ default=data.get("harvest", "") == True,
258
+ enable_events=True,
259
+ ),
260
+ sg.Radio(
261
+ "crepe",
262
+ "f0method",
263
+ key="crepe",
264
+ default=data.get("crepe", "") == True,
265
+ enable_events=True,
266
+ ),
267
+ sg.Radio(
268
+ "rmvpe",
269
+ "f0method",
270
+ key="rmvpe",
271
+ default=data.get("rmvpe", "") == True,
272
+ enable_events=True,
273
+ ),
274
+ ],
275
+ ],
276
+ title=i18n("常规设置"),
277
+ ),
278
+ sg.Frame(
279
+ layout=[
280
+ [
281
+ sg.Text(i18n("采样长度")),
282
+ sg.Slider(
283
+ range=(0.05, 2.4),
284
+ key="block_time",
285
+ resolution=0.01,
286
+ orientation="h",
287
+ default_value=data.get("block_time", "0.25"),
288
+ enable_events=True,
289
+ ),
290
+ ],
291
+ [
292
+ sg.Text(i18n("harvest进程数")),
293
+ sg.Slider(
294
+ range=(1, n_cpu),
295
+ key="n_cpu",
296
+ resolution=1,
297
+ orientation="h",
298
+ default_value=data.get(
299
+ "n_cpu", min(self.config.n_cpu, n_cpu)
300
+ ),
301
+ enable_events=True,
302
+ ),
303
+ ],
304
+ [
305
+ sg.Text(i18n("淡入淡出长度")),
306
+ sg.Slider(
307
+ range=(0.01, 0.15),
308
+ key="crossfade_length",
309
+ resolution=0.01,
310
+ orientation="h",
311
+ default_value=data.get("crossfade_length", "0.04"),
312
+ enable_events=True,
313
+ ),
314
+ ],
315
+ [
316
+ sg.Text(i18n("额外推理时长")),
317
+ sg.Slider(
318
+ range=(0.05, 5.00),
319
+ key="extra_time",
320
+ resolution=0.01,
321
+ orientation="h",
322
+ default_value=data.get("extra_time", "2.0"),
323
+ enable_events=True,
324
+ ),
325
+ ],
326
+ [
327
+ sg.Checkbox(
328
+ i18n("输入降噪"),
329
+ key="I_noise_reduce",
330
+ enable_events=True,
331
+ ),
332
+ sg.Checkbox(
333
+ i18n("输出降噪"),
334
+ key="O_noise_reduce",
335
+ enable_events=True,
336
+ ),
337
+ ],
338
+ ],
339
+ title=i18n("性能设置"),
340
+ ),
341
+ ],
342
+ [
343
+ sg.Button(i18n("开始音频转换"), key="start_vc"),
344
+ sg.Button(i18n("停止音频转换"), key="stop_vc"),
345
+ sg.Text(i18n("推理时间(ms):")),
346
+ sg.Text("0", key="infer_time"),
347
+ ],
348
+ ]
349
+ self.window = sg.Window("RVC - GUI", layout=layout, finalize=True)
350
+ self.event_handler()
351
+
352
+ def event_handler(self):
353
+ while True:
354
+ event, values = self.window.read()
355
+ if event == sg.WINDOW_CLOSED:
356
+ self.flag_vc = False
357
+ exit()
358
+ if event == "reload_devices":
359
+ prev_input = self.window["sg_input_device"].get()
360
+ prev_output = self.window["sg_output_device"].get()
361
+ input_devices, output_devices, _, _ = self.get_devices(update=True)
362
+ if prev_input not in input_devices:
363
+ self.config.sg_input_device = input_devices[0]
364
+ else:
365
+ self.config.sg_input_device = prev_input
366
+ self.window["sg_input_device"].Update(values=input_devices)
367
+ self.window["sg_input_device"].Update(
368
+ value=self.config.sg_input_device
369
+ )
370
+ if prev_output not in output_devices:
371
+ self.config.sg_output_device = output_devices[0]
372
+ else:
373
+ self.config.sg_output_device = prev_output
374
+ self.window["sg_output_device"].Update(values=output_devices)
375
+ self.window["sg_output_device"].Update(
376
+ value=self.config.sg_output_device
377
+ )
378
+ if event == "start_vc" and self.flag_vc == False:
379
+ if self.set_values(values) == True:
380
+ logger.info("Use CUDA: %s", torch.cuda.is_available())
381
+ self.start_vc()
382
+ settings = {
383
+ "pth_path": values["pth_path"],
384
+ "index_path": values["index_path"],
385
+ "sg_input_device": values["sg_input_device"],
386
+ "sg_output_device": values["sg_output_device"],
387
+ "threhold": values["threhold"],
388
+ "pitch": values["pitch"],
389
+ "rms_mix_rate": values["rms_mix_rate"],
390
+ "index_rate": values["index_rate"],
391
+ "block_time": values["block_time"],
392
+ "crossfade_length": values["crossfade_length"],
393
+ "extra_time": values["extra_time"],
394
+ "n_cpu": values["n_cpu"],
395
+ "f0method": ["pm", "harvest", "crepe", "rmvpe"][
396
+ [
397
+ values["pm"],
398
+ values["harvest"],
399
+ values["crepe"],
400
+ values["rmvpe"],
401
+ ].index(True)
402
+ ],
403
+ }
404
+ with open("configs/config.json", "w") as j:
405
+ json.dump(settings, j)
406
+ if event == "stop_vc" and self.flag_vc == True:
407
+ self.flag_vc = False
408
+
409
+ # Parameter hot update
410
+ if event == "threhold":
411
+ self.config.threhold = values["threhold"]
412
+ elif event == "pitch":
413
+ self.config.pitch = values["pitch"]
414
+ if hasattr(self, "rvc"):
415
+ self.rvc.change_key(values["pitch"])
416
+ elif event == "index_rate":
417
+ self.config.index_rate = values["index_rate"]
418
+ if hasattr(self, "rvc"):
419
+ self.rvc.change_index_rate(values["index_rate"])
420
+ elif event == "rms_mix_rate":
421
+ self.config.rms_mix_rate = values["rms_mix_rate"]
422
+ elif event in ["pm", "harvest", "crepe", "rmvpe"]:
423
+ self.config.f0method = event
424
+ elif event == "I_noise_reduce":
425
+ self.config.I_noise_reduce = values["I_noise_reduce"]
426
+ elif event == "O_noise_reduce":
427
+ self.config.O_noise_reduce = values["O_noise_reduce"]
428
+ elif event != "start_vc" and self.flag_vc == True:
429
+ # Other parameters do not support hot update
430
+ self.flag_vc = False
431
+
432
+ def set_values(self, values):
433
+ if len(values["pth_path"].strip()) == 0:
434
+ sg.popup(i18n("请选择pth文件"))
435
+ return False
436
+ if len(values["index_path"].strip()) == 0:
437
+ sg.popup(i18n("请选择index文件"))
438
+ return False
439
+ pattern = re.compile("[^\x00-\x7F]+")
440
+ if pattern.findall(values["pth_path"]):
441
+ sg.popup(i18n("pth文件路径不可包含中文"))
442
+ return False
443
+ if pattern.findall(values["index_path"]):
444
+ sg.popup(i18n("index文件路径不可包含中文"))
445
+ return False
446
+ self.set_devices(values["sg_input_device"], values["sg_output_device"])
447
+ self.config.pth_path = values["pth_path"]
448
+ self.config.index_path = values["index_path"]
449
+ self.config.threhold = values["threhold"]
450
+ self.config.pitch = values["pitch"]
451
+ self.config.block_time = values["block_time"]
452
+ self.config.crossfade_time = values["crossfade_length"]
453
+ self.config.extra_time = values["extra_time"]
454
+ self.config.I_noise_reduce = values["I_noise_reduce"]
455
+ self.config.O_noise_reduce = values["O_noise_reduce"]
456
+ self.config.rms_mix_rate = values["rms_mix_rate"]
457
+ self.config.index_rate = values["index_rate"]
458
+ self.config.n_cpu = values["n_cpu"]
459
+ self.config.f0method = ["pm", "harvest", "crepe", "rmvpe"][
460
+ [
461
+ values["pm"],
462
+ values["harvest"],
463
+ values["crepe"],
464
+ values["rmvpe"],
465
+ ].index(True)
466
+ ]
467
+ return True
468
+
469
+ def start_vc(self):
470
+ torch.cuda.empty_cache()
471
+ self.flag_vc = True
472
+ self.rvc = rvc_for_realtime.RVC(
473
+ self.config.pitch,
474
+ self.config.pth_path,
475
+ self.config.index_path,
476
+ self.config.index_rate,
477
+ self.config.n_cpu,
478
+ inp_q,
479
+ opt_q,
480
+ device,
481
+ self.rvc if hasattr(self, "rvc") else None
482
+ )
483
+ self.config.samplerate = self.rvc.tgt_sr
484
+ self.zc = self.rvc.tgt_sr // 100
485
+ self.block_frame = int(np.round(self.config.block_time * self.config.samplerate / self.zc)) * self.zc
486
+ self.block_frame_16k = 160 * self.block_frame // self.zc
487
+ self.crossfade_frame = int(np.round(self.config.crossfade_time * self.config.samplerate / self.zc)) * self.zc
488
+ self.sola_search_frame = self.zc
489
+ self.extra_frame = int(np.round(self.config.extra_time * self.config.samplerate / self.zc)) * self.zc
490
+ self.input_wav: torch.Tensor = torch.zeros(
491
+ self.extra_frame
492
+ + self.crossfade_frame
493
+ + self.sola_search_frame
494
+ + self.block_frame,
495
+ device=device,
496
+ dtype=torch.float32,
497
+ )
498
+ self.input_wav_res: torch.Tensor= torch.zeros(160 * self.input_wav.shape[0] // self.zc, device=device,dtype=torch.float32)
499
+ self.pitch: np.ndarray = np.zeros(
500
+ self.input_wav.shape[0] // self.zc,
501
+ dtype="int32",
502
+ )
503
+ self.pitchf: np.ndarray = np.zeros(
504
+ self.input_wav.shape[0] // self.zc,
505
+ dtype="float64",
506
+ )
507
+ self.sola_buffer: torch.Tensor = torch.zeros(
508
+ self.crossfade_frame, device=device, dtype=torch.float32
509
+ )
510
+ self.nr_buffer: torch.Tensor = self.sola_buffer.clone()
511
+ self.output_buffer: torch.Tensor = self.input_wav.clone()
512
+ self.res_buffer: torch.Tensor = torch.zeros(2 * self.zc, device=device,dtype=torch.float32)
513
+ self.valid_rate = 1 - (self.extra_frame - 1) / self.input_wav.shape[0]
514
+ self.fade_in_window: torch.Tensor = (
515
+ torch.sin(
516
+ 0.5
517
+ * np.pi
518
+ * torch.linspace(
519
+ 0.0,
520
+ 1.0,
521
+ steps=self.crossfade_frame,
522
+ device=device,
523
+ dtype=torch.float32,
524
+ )
525
+ )
526
+ ** 2
527
+ )
528
+ self.fade_out_window: torch.Tensor = 1 - self.fade_in_window
529
+ self.resampler = tat.Resample(
530
+ orig_freq=self.config.samplerate, new_freq=16000, dtype=torch.float32
531
+ ).to(device)
532
+ self.tg = TorchGate(sr=self.config.samplerate, n_fft=4*self.zc, prop_decrease=0.9).to(device)
533
+ thread_vc = threading.Thread(target=self.soundinput)
534
+ thread_vc.start()
535
+
536
+ def soundinput(self):
537
+ """
538
+ 接受音频输入
539
+ """
540
+ channels = 1 if sys.platform == "darwin" else 2
541
+ with sd.Stream(
542
+ channels=channels,
543
+ callback=self.audio_callback,
544
+ blocksize=self.block_frame,
545
+ samplerate=self.config.samplerate,
546
+ dtype="float32",
547
+ ):
548
+ while self.flag_vc:
549
+ time.sleep(self.config.block_time)
550
+ logger.debug("Audio block passed.")
551
+ logger.debug("ENDing VC")
552
+
553
+ def audio_callback(
554
+ self, indata: np.ndarray, outdata: np.ndarray, frames, times, status
555
+ ):
556
+ """
557
+ 音频处理
558
+ """
559
+ start_time = time.perf_counter()
560
+ indata = librosa.to_mono(indata.T)
561
+ if self.config.threhold > -60:
562
+ rms = librosa.feature.rms(
563
+ y=indata, frame_length=4*self.zc, hop_length=self.zc
564
+ )
565
+ db_threhold = (
566
+ librosa.amplitude_to_db(rms, ref=1.0)[0] < self.config.threhold
567
+ )
568
+ for i in range(db_threhold.shape[0]):
569
+ if db_threhold[i]:
570
+ indata[i * self.zc : (i + 1) * self.zc] = 0
571
+ self.input_wav[: -self.block_frame] = self.input_wav[self.block_frame :].clone()
572
+ self.input_wav[-self.block_frame: ] = torch.from_numpy(indata).to(device)
573
+ self.input_wav_res[ : -self.block_frame_16k] = self.input_wav_res[self.block_frame_16k :].clone()
574
+ # input noise reduction and resampling
575
+ if self.config.I_noise_reduce:
576
+ input_wav = self.input_wav[-self.crossfade_frame -self.block_frame-2*self.zc: ]
577
+ input_wav = self.tg(input_wav.unsqueeze(0), self.input_wav.unsqueeze(0))[0, 2*self.zc:]
578
+ input_wav[: self.crossfade_frame] *= self.fade_in_window
579
+ input_wav[: self.crossfade_frame] += self.nr_buffer * self.fade_out_window
580
+ self.nr_buffer[:] = input_wav[-self.crossfade_frame: ]
581
+ input_wav = torch.cat((self.res_buffer[:], input_wav[: self.block_frame]))
582
+ self.res_buffer[:] = input_wav[-2*self.zc: ]
583
+ self.input_wav_res[-self.block_frame_16k-160: ] = self.resampler(input_wav)[160: ]
584
+ else:
585
+ self.input_wav_res[-self.block_frame_16k-160: ] = self.resampler(self.input_wav[-self.block_frame-2*self.zc: ])[160: ]
586
+ # infer
587
+ f0_extractor_frame = self.block_frame_16k + 800
588
+ if self.config.f0method == 'rmvpe':
589
+ f0_extractor_frame = 5120 * ((f0_extractor_frame - 1) // 5120 + 1)
590
+ infer_wav = self.rvc.infer(
591
+ self.input_wav_res,
592
+ self.input_wav_res[-f0_extractor_frame :].cpu().numpy(),
593
+ self.block_frame_16k,
594
+ self.valid_rate,
595
+ self.pitch,
596
+ self.pitchf,
597
+ self.config.f0method,
598
+ )
599
+ infer_wav = infer_wav[
600
+ -self.crossfade_frame - self.sola_search_frame - self.block_frame :
601
+ ]
602
+ # output noise reduction
603
+ if self.config.O_noise_reduce:
604
+ self.output_buffer[: -self.block_frame] = self.output_buffer[self.block_frame :].clone()
605
+ self.output_buffer[-self.block_frame: ] = infer_wav[-self.block_frame:]
606
+ infer_wav = self.tg(infer_wav.unsqueeze(0), self.output_buffer.unsqueeze(0)).squeeze(0)
607
+ # volume envelop mixing
608
+ if self.config.rms_mix_rate < 1:
609
+ rms1 = librosa.feature.rms(
610
+ y=self.input_wav_res[-160*infer_wav.shape[0]//self.zc :].cpu().numpy(),
611
+ frame_length=640,
612
+ hop_length=160,
613
+ )
614
+ rms1 = torch.from_numpy(rms1).to(device)
615
+ rms1 = F.interpolate(
616
+ rms1.unsqueeze(0), size=infer_wav.shape[0] + 1, mode="linear",align_corners=True,
617
+ )[0,0,:-1]
618
+ rms2 = librosa.feature.rms(
619
+ y=infer_wav[:].cpu().numpy(), frame_length=4*self.zc, hop_length=self.zc
620
+ )
621
+ rms2 = torch.from_numpy(rms2).to(device)
622
+ rms2 = F.interpolate(
623
+ rms2.unsqueeze(0), size=infer_wav.shape[0] + 1, mode="linear",align_corners=True,
624
+ )[0,0,:-1]
625
+ rms2 = torch.max(rms2, torch.zeros_like(rms2) + 1e-3)
626
+ infer_wav *= torch.pow(rms1 / rms2, torch.tensor(1 - self.config.rms_mix_rate))
627
+ # SOLA algorithm from https://github.com/yxlllc/DDSP-SVC
628
+ conv_input = infer_wav[None, None, : self.crossfade_frame + self.sola_search_frame]
629
+ cor_nom = F.conv1d(conv_input, self.sola_buffer[None, None, :])
630
+ cor_den = torch.sqrt(
631
+ F.conv1d(conv_input ** 2, torch.ones(1, 1, self.crossfade_frame, device=device)) + 1e-8)
632
+ if sys.platform == "darwin":
633
+ _, sola_offset = torch.max(cor_nom[0, 0] / cor_den[0, 0])
634
+ sola_offset = sola_offset.item()
635
+ else:
636
+ sola_offset = torch.argmax(cor_nom[0, 0] / cor_den[0, 0])
637
+ logger.debug("sola_offset = %d", int(sola_offset))
638
+ infer_wav = infer_wav[sola_offset: sola_offset + self.block_frame + self.crossfade_frame]
639
+ infer_wav[: self.crossfade_frame] *= self.fade_in_window
640
+ infer_wav[: self.crossfade_frame] += self.sola_buffer *self.fade_out_window
641
+ self.sola_buffer[:] = infer_wav[-self.crossfade_frame:]
642
+ if sys.platform == "darwin":
643
+ outdata[:] = infer_wav[:-self.crossfade_frame].cpu().numpy()[:, np.newaxis]
644
+ else:
645
+ outdata[:] = infer_wav[:-self.crossfade_frame].repeat(2, 1).t().cpu().numpy()
646
+ total_time = time.perf_counter() - start_time
647
+ self.window["infer_time"].update(int(total_time * 1000))
648
+ logger.info("Infer time: %.2f", total_time)
649
+
650
+ def get_devices(self, update: bool = True):
651
+ """获取设备列表"""
652
+ if update:
653
+ sd._terminate()
654
+ sd._initialize()
655
+ devices = sd.query_devices()
656
+ hostapis = sd.query_hostapis()
657
+ for hostapi in hostapis:
658
+ for device_idx in hostapi["devices"]:
659
+ devices[device_idx]["hostapi_name"] = hostapi["name"]
660
+ input_devices = [
661
+ f"{d['name']} ({d['hostapi_name']})"
662
+ for d in devices
663
+ if d["max_input_channels"] > 0
664
+ ]
665
+ output_devices = [
666
+ f"{d['name']} ({d['hostapi_name']})"
667
+ for d in devices
668
+ if d["max_output_channels"] > 0
669
+ ]
670
+ input_devices_indices = [
671
+ d["index"] if "index" in d else d["name"]
672
+ for d in devices
673
+ if d["max_input_channels"] > 0
674
+ ]
675
+ output_devices_indices = [
676
+ d["index"] if "index" in d else d["name"]
677
+ for d in devices
678
+ if d["max_output_channels"] > 0
679
+ ]
680
+ return (
681
+ input_devices,
682
+ output_devices,
683
+ input_devices_indices,
684
+ output_devices_indices,
685
+ )
686
+
687
+ def set_devices(self, input_device, output_device):
688
+ """设置输出设备"""
689
+ (
690
+ input_devices,
691
+ output_devices,
692
+ input_device_indices,
693
+ output_device_indices,
694
+ ) = self.get_devices()
695
+ sd.default.device[0] = input_device_indices[
696
+ input_devices.index(input_device)
697
+ ]
698
+ sd.default.device[1] = output_device_indices[
699
+ output_devices.index(output_device)
700
+ ]
701
+ logger.info(
702
+ "Input device: %s:%s", str(sd.default.device[0]), input_device
703
+ )
704
+ logger.info(
705
+ "Output device: %s:%s", str(sd.default.device[1]), output_device
706
+ )
707
+
708
+ gui = GUI()
infer-web.py ADDED
@@ -0,0 +1,1505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os, sys
2
+
3
+ now_dir = os.getcwd()
4
+ sys.path.append(now_dir)
5
+ import logging
6
+ import shutil
7
+ import threading
8
+ import traceback
9
+ import warnings
10
+ from random import shuffle
11
+ from subprocess import Popen
12
+ from time import sleep
13
+ import json
14
+ import pathlib
15
+
16
+ import fairseq
17
+ import faiss
18
+ import gradio as gr
19
+ import numpy as np
20
+ import torch
21
+ from dotenv import load_dotenv
22
+ from sklearn.cluster import MiniBatchKMeans
23
+
24
+ from configs.config import Config
25
+ from i18n.i18n import I18nAuto
26
+ from infer.lib.train.process_ckpt import (
27
+ change_info,
28
+ extract_small_model,
29
+ merge,
30
+ show_info,
31
+ )
32
+ from infer.modules.uvr5.modules import uvr
33
+ from infer.modules.vc.modules import VC
34
+
35
+ logging.getLogger("numba").setLevel(logging.WARNING)
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+ tmp = os.path.join(now_dir, "TEMP")
40
+ shutil.rmtree(tmp, ignore_errors=True)
41
+ shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)
42
+ shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)
43
+ os.makedirs(tmp, exist_ok=True)
44
+ os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)
45
+ os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)
46
+ os.environ["TEMP"] = tmp
47
+ warnings.filterwarnings("ignore")
48
+ torch.manual_seed(114514)
49
+
50
+
51
+ load_dotenv()
52
+ config = Config()
53
+ vc = VC(config)
54
+
55
+
56
+ if config.dml == True:
57
+
58
+ def forward_dml(ctx, x, scale):
59
+ ctx.scale = scale
60
+ res = x.clone().detach()
61
+ return res
62
+
63
+ fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml
64
+ i18n = I18nAuto()
65
+ logger.info(i18n)
66
+ # 判断是否有能用来训练和加速推理的N卡
67
+ ngpu = torch.cuda.device_count()
68
+ gpu_infos = []
69
+ mem = []
70
+ if_gpu_ok = False
71
+
72
+ if torch.cuda.is_available() or ngpu != 0:
73
+ for i in range(ngpu):
74
+ gpu_name = torch.cuda.get_device_name(i)
75
+ if any(
76
+ value in gpu_name.upper()
77
+ for value in [
78
+ "10",
79
+ "16",
80
+ "20",
81
+ "30",
82
+ "40",
83
+ "A2",
84
+ "A3",
85
+ "A4",
86
+ "P4",
87
+ "A50",
88
+ "500",
89
+ "A60",
90
+ "70",
91
+ "80",
92
+ "90",
93
+ "M4",
94
+ "T4",
95
+ "TITAN",
96
+ ]
97
+ ):
98
+ # A10#A100#V100#A40#P40#M40#K80#A4500
99
+ if_gpu_ok = True # 至少有一张能用的N卡
100
+ gpu_infos.append("%s\t%s" % (i, gpu_name))
101
+ mem.append(
102
+ int(
103
+ torch.cuda.get_device_properties(i).total_memory
104
+ / 1024
105
+ / 1024
106
+ / 1024
107
+ + 0.4
108
+ )
109
+ )
110
+ if if_gpu_ok and len(gpu_infos) > 0:
111
+ gpu_info = "\n".join(gpu_infos)
112
+ default_batch_size = min(mem) // 2
113
+ else:
114
+ gpu_info = i18n("很遗憾您这没有能用的显卡来支持您训练")
115
+ default_batch_size = 1
116
+ gpus = "-".join([i[0] for i in gpu_infos])
117
+
118
+
119
+ class ToolButton(gr.Button, gr.components.FormComponent):
120
+ """Small button with single emoji as text, fits inside gradio forms"""
121
+
122
+ def __init__(self, **kwargs):
123
+ super().__init__(variant="tool", **kwargs)
124
+
125
+ def get_block_name(self):
126
+ return "button"
127
+
128
+
129
+ weight_root = os.getenv("weight_root")
130
+ weight_uvr5_root = os.getenv("weight_uvr5_root")
131
+ index_root = os.getenv("index_root")
132
+
133
+ names = []
134
+ for name in os.listdir(weight_root):
135
+ if name.endswith(".pth"):
136
+ names.append(name)
137
+ index_paths = []
138
+ for root, dirs, files in os.walk(index_root, topdown=False):
139
+ for name in files:
140
+ if name.endswith(".index") and "trained" not in name:
141
+ index_paths.append("%s/%s" % (root, name))
142
+ uvr5_names = []
143
+ for name in os.listdir(weight_uvr5_root):
144
+ if name.endswith(".pth") or "onnx" in name:
145
+ uvr5_names.append(name.replace(".pth", ""))
146
+
147
+
148
+ def change_choices():
149
+ names = []
150
+ for name in os.listdir(weight_root):
151
+ if name.endswith(".pth"):
152
+ names.append(name)
153
+ index_paths = []
154
+ for root, dirs, files in os.walk(index_root, topdown=False):
155
+ for name in files:
156
+ if name.endswith(".index") and "trained" not in name:
157
+ index_paths.append("%s/%s" % (root, name))
158
+ return {"choices": sorted(names), "__type__": "update"}, {
159
+ "choices": sorted(index_paths),
160
+ "__type__": "update",
161
+ }
162
+
163
+
164
+ def clean():
165
+ return {"value": "", "__type__": "update"}
166
+
167
+
168
+ def export_onnx():
169
+ from infer.modules.onnx.export import export_onnx as eo
170
+
171
+ eo()
172
+
173
+
174
+ sr_dict = {
175
+ "32k": 32000,
176
+ "40k": 40000,
177
+ "48k": 48000,
178
+ }
179
+
180
+
181
+ def if_done(done, p):
182
+ while 1:
183
+ if p.poll() is None:
184
+ sleep(0.5)
185
+ else:
186
+ break
187
+ done[0] = True
188
+
189
+
190
+ def if_done_multi(done, ps):
191
+ while 1:
192
+ # poll==None代表进程未结束
193
+ # 只要有一个进程未结束都不停
194
+ flag = 1
195
+ for p in ps:
196
+ if p.poll() is None:
197
+ flag = 0
198
+ sleep(0.5)
199
+ break
200
+ if flag == 1:
201
+ break
202
+ done[0] = True
203
+
204
+
205
+ def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):
206
+ sr = sr_dict[sr]
207
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
208
+ f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")
209
+ f.close()
210
+ per = 3.0 if config.is_half else 3.7
211
+ cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (
212
+ config.python_cmd,
213
+ trainset_dir,
214
+ sr,
215
+ n_p,
216
+ now_dir,
217
+ exp_dir,
218
+ config.noparallel,
219
+ per,
220
+ )
221
+ logger.info(cmd)
222
+ p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir
223
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
224
+ done = [False]
225
+ threading.Thread(
226
+ target=if_done,
227
+ args=(
228
+ done,
229
+ p,
230
+ ),
231
+ ).start()
232
+ while 1:
233
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
234
+ yield (f.read())
235
+ sleep(1)
236
+ if done[0]:
237
+ break
238
+ with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:
239
+ log = f.read()
240
+ logger.info(log)
241
+ yield log
242
+
243
+
244
+ # but2.click(extract_f0,[gpus6,np7,f0method8,if_f0_3,trainset_dir4],[info2])
245
+ def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, gpus_rmvpe):
246
+ gpus = gpus.split("-")
247
+ os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)
248
+ f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")
249
+ f.close()
250
+ if if_f0:
251
+ if f0method != "rmvpe_gpu":
252
+ cmd = (
253
+ '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'
254
+ % (
255
+ config.python_cmd,
256
+ now_dir,
257
+ exp_dir,
258
+ n_p,
259
+ f0method,
260
+ )
261
+ )
262
+ logger.info(cmd)
263
+ p = Popen(
264
+ cmd, shell=True, cwd=now_dir
265
+ ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE
266
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
267
+ done = [False]
268
+ threading.Thread(
269
+ target=if_done,
270
+ args=(
271
+ done,
272
+ p,
273
+ ),
274
+ ).start()
275
+ else:
276
+ if gpus_rmvpe != "-":
277
+ gpus_rmvpe = gpus_rmvpe.split("-")
278
+ leng = len(gpus_rmvpe)
279
+ ps = []
280
+ for idx, n_g in enumerate(gpus_rmvpe):
281
+ cmd = (
282
+ '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '
283
+ % (
284
+ config.python_cmd,
285
+ leng,
286
+ idx,
287
+ n_g,
288
+ now_dir,
289
+ exp_dir,
290
+ config.is_half,
291
+ )
292
+ )
293
+ logger.info(cmd)
294
+ p = Popen(
295
+ cmd, shell=True, cwd=now_dir
296
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
297
+ ps.append(p)
298
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
299
+ done = [False]
300
+ threading.Thread(
301
+ target=if_done_multi, #
302
+ args=(
303
+ done,
304
+ ps,
305
+ ),
306
+ ).start()
307
+ else:
308
+ cmd = (
309
+ config.python_cmd
310
+ + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '
311
+ % (
312
+ now_dir,
313
+ exp_dir,
314
+ )
315
+ )
316
+ logger.info(cmd)
317
+ p = Popen(
318
+ cmd, shell=True, cwd=now_dir
319
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
320
+ p.wait()
321
+ done = [True]
322
+ while 1:
323
+ with open(
324
+ "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"
325
+ ) as f:
326
+ yield (f.read())
327
+ sleep(1)
328
+ if done[0]:
329
+ break
330
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
331
+ log = f.read()
332
+ logger.info(log)
333
+ yield log
334
+ ####对不同part分别开多进程
335
+ """
336
+ n_part=int(sys.argv[1])
337
+ i_part=int(sys.argv[2])
338
+ i_gpu=sys.argv[3]
339
+ exp_dir=sys.argv[4]
340
+ os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)
341
+ """
342
+ leng = len(gpus)
343
+ ps = []
344
+ for idx, n_g in enumerate(gpus):
345
+ cmd = (
346
+ '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'
347
+ % (
348
+ config.python_cmd,
349
+ config.device,
350
+ leng,
351
+ idx,
352
+ n_g,
353
+ now_dir,
354
+ exp_dir,
355
+ version19,
356
+ )
357
+ )
358
+ logger.info(cmd)
359
+ p = Popen(
360
+ cmd, shell=True, cwd=now_dir
361
+ ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir
362
+ ps.append(p)
363
+ ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读
364
+ done = [False]
365
+ threading.Thread(
366
+ target=if_done_multi,
367
+ args=(
368
+ done,
369
+ ps,
370
+ ),
371
+ ).start()
372
+ while 1:
373
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
374
+ yield (f.read())
375
+ sleep(1)
376
+ if done[0]:
377
+ break
378
+ with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:
379
+ log = f.read()
380
+ logger.info(log)
381
+ yield log
382
+
383
+
384
+ def get_pretrained_models(path_str, f0_str, sr2):
385
+ if_pretrained_generator_exist = os.access(
386
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK
387
+ )
388
+ if_pretrained_discriminator_exist = os.access(
389
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK
390
+ )
391
+ if not if_pretrained_generator_exist:
392
+ logger.warn(
393
+ "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",
394
+ path_str,
395
+ f0_str,
396
+ sr2,
397
+ )
398
+ if not if_pretrained_discriminator_exist:
399
+ logger.warn(
400
+ "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",
401
+ path_str,
402
+ f0_str,
403
+ sr2,
404
+ )
405
+ return (
406
+ "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)
407
+ if if_pretrained_generator_exist
408
+ else "",
409
+ "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)
410
+ if if_pretrained_discriminator_exist
411
+ else "",
412
+ )
413
+
414
+
415
+ def change_sr2(sr2, if_f0_3, version19):
416
+ path_str = "" if version19 == "v1" else "_v2"
417
+ f0_str = "f0" if if_f0_3 else ""
418
+ return get_pretrained_models(path_str, f0_str, sr2)
419
+
420
+
421
+ def change_version19(sr2, if_f0_3, version19):
422
+ path_str = "" if version19 == "v1" else "_v2"
423
+ if sr2 == "32k" and version19 == "v1":
424
+ sr2 = "40k"
425
+ to_return_sr2 = (
426
+ {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}
427
+ if version19 == "v1"
428
+ else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}
429
+ )
430
+ f0_str = "f0" if if_f0_3 else ""
431
+ return (
432
+ *get_pretrained_models(path_str, f0_str, sr2),
433
+ to_return_sr2,
434
+ )
435
+
436
+
437
+ def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15
438
+ path_str = "" if version19 == "v1" else "_v2"
439
+ return (
440
+ {"visible": if_f0_3, "__type__": "update"},
441
+ *get_pretrained_models(path_str, "f0", sr2),
442
+ )
443
+
444
+
445
+ # but3.click(click_train,[exp_dir1,sr2,if_f0_3,save_epoch10,total_epoch11,batch_size12,if_save_latest13,pretrained_G14,pretrained_D15,gpus16])
446
+ def click_train(
447
+ exp_dir1,
448
+ sr2,
449
+ if_f0_3,
450
+ spk_id5,
451
+ save_epoch10,
452
+ total_epoch11,
453
+ batch_size12,
454
+ if_save_latest13,
455
+ pretrained_G14,
456
+ pretrained_D15,
457
+ gpus16,
458
+ if_cache_gpu17,
459
+ if_save_every_weights18,
460
+ version19,
461
+ ):
462
+ # 生成filelist
463
+ exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
464
+ os.makedirs(exp_dir, exist_ok=True)
465
+ gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)
466
+ feature_dir = (
467
+ "%s/3_feature256" % (exp_dir)
468
+ if version19 == "v1"
469
+ else "%s/3_feature768" % (exp_dir)
470
+ )
471
+ if if_f0_3:
472
+ f0_dir = "%s/2a_f0" % (exp_dir)
473
+ f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)
474
+ names = (
475
+ set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])
476
+ & set([name.split(".")[0] for name in os.listdir(feature_dir)])
477
+ & set([name.split(".")[0] for name in os.listdir(f0_dir)])
478
+ & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])
479
+ )
480
+ else:
481
+ names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(
482
+ [name.split(".")[0] for name in os.listdir(feature_dir)]
483
+ )
484
+ opt = []
485
+ for name in names:
486
+ if if_f0_3:
487
+ opt.append(
488
+ "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"
489
+ % (
490
+ gt_wavs_dir.replace("\\", "\\\\"),
491
+ name,
492
+ feature_dir.replace("\\", "\\\\"),
493
+ name,
494
+ f0_dir.replace("\\", "\\\\"),
495
+ name,
496
+ f0nsf_dir.replace("\\", "\\\\"),
497
+ name,
498
+ spk_id5,
499
+ )
500
+ )
501
+ else:
502
+ opt.append(
503
+ "%s/%s.wav|%s/%s.npy|%s"
504
+ % (
505
+ gt_wavs_dir.replace("\\", "\\\\"),
506
+ name,
507
+ feature_dir.replace("\\", "\\\\"),
508
+ name,
509
+ spk_id5,
510
+ )
511
+ )
512
+ fea_dim = 256 if version19 == "v1" else 768
513
+ if if_f0_3:
514
+ for _ in range(2):
515
+ opt.append(
516
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s/logs/mute/2a_f0/mute.wav.npy|%s/logs/mute/2b-f0nsf/mute.wav.npy|%s"
517
+ % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)
518
+ )
519
+ else:
520
+ for _ in range(2):
521
+ opt.append(
522
+ "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"
523
+ % (now_dir, sr2, now_dir, fea_dim, spk_id5)
524
+ )
525
+ shuffle(opt)
526
+ with open("%s/filelist.txt" % exp_dir, "w") as f:
527
+ f.write("\n".join(opt))
528
+ logger.debug("Write filelist done")
529
+ # 生成config#无需生成config
530
+ # cmd = python_cmd + " train_nsf_sim_cache_sid_load_pretrain.py -e mi-test -sr 40k -f0 1 -bs 4 -g 0 -te 10 -se 5 -pg pretrained/f0G40k.pth -pd pretrained/f0D40k.pth -l 1 -c 0"
531
+ logger.info("Use gpus: %s", str(gpus16))
532
+ if pretrained_G14 == "":
533
+ logger.info("No pretrained Generator")
534
+ if pretrained_D15 == "":
535
+ logger.info("No pretrained Discriminator")
536
+ if version19 == "v1" or sr2 == "40k":
537
+ config_path = "v1/%s.json" % sr2
538
+ else:
539
+ config_path = "v2/%s.json" % sr2
540
+ config_save_path = os.path.join(exp_dir, "config.json")
541
+ if not pathlib.Path(config_save_path).exists():
542
+ with open(config_save_path, "w", encoding="utf-8") as f:
543
+ json.dump(
544
+ config.json_config[config_path],
545
+ f,
546
+ ensure_ascii=False,
547
+ indent=4,
548
+ sort_keys=True,
549
+ )
550
+ f.write("\n")
551
+ if gpus16:
552
+ cmd = (
553
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
554
+ % (
555
+ config.python_cmd,
556
+ exp_dir1,
557
+ sr2,
558
+ 1 if if_f0_3 else 0,
559
+ batch_size12,
560
+ gpus16,
561
+ total_epoch11,
562
+ save_epoch10,
563
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
564
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
565
+ 1 if if_save_latest13 == i18n("是") else 0,
566
+ 1 if if_cache_gpu17 == i18n("是") else 0,
567
+ 1 if if_save_every_weights18 == i18n("是") else 0,
568
+ version19,
569
+ )
570
+ )
571
+ else:
572
+ cmd = (
573
+ '"%s" infer/modules/train/train.py -e "%s" -sr %s -f0 %s -bs %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s'
574
+ % (
575
+ config.python_cmd,
576
+ exp_dir1,
577
+ sr2,
578
+ 1 if if_f0_3 else 0,
579
+ batch_size12,
580
+ total_epoch11,
581
+ save_epoch10,
582
+ "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",
583
+ "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",
584
+ 1 if if_save_latest13 == i18n("是") else 0,
585
+ 1 if if_cache_gpu17 == i18n("是") else 0,
586
+ 1 if if_save_every_weights18 == i18n("是") else 0,
587
+ version19,
588
+ )
589
+ )
590
+ logger.info(cmd)
591
+ p = Popen(cmd, shell=True, cwd=now_dir)
592
+ p.wait()
593
+ return "训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"
594
+
595
+
596
+ # but4.click(train_index, [exp_dir1], info3)
597
+ def train_index(exp_dir1, version19):
598
+ # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)
599
+ exp_dir = "logs/%s" % (exp_dir1)
600
+ os.makedirs(exp_dir, exist_ok=True)
601
+ feature_dir = (
602
+ "%s/3_feature256" % (exp_dir)
603
+ if version19 == "v1"
604
+ else "%s/3_feature768" % (exp_dir)
605
+ )
606
+ if not os.path.exists(feature_dir):
607
+ return "请先进行特征提取!"
608
+ listdir_res = list(os.listdir(feature_dir))
609
+ if len(listdir_res) == 0:
610
+ return "请先进行特征提取!"
611
+ infos = []
612
+ npys = []
613
+ for name in sorted(listdir_res):
614
+ phone = np.load("%s/%s" % (feature_dir, name))
615
+ npys.append(phone)
616
+ big_npy = np.concatenate(npys, 0)
617
+ big_npy_idx = np.arange(big_npy.shape[0])
618
+ np.random.shuffle(big_npy_idx)
619
+ big_npy = big_npy[big_npy_idx]
620
+ if big_npy.shape[0] > 2e5:
621
+ infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])
622
+ yield "\n".join(infos)
623
+ try:
624
+ big_npy = (
625
+ MiniBatchKMeans(
626
+ n_clusters=10000,
627
+ verbose=True,
628
+ batch_size=256 * config.n_cpu,
629
+ compute_labels=False,
630
+ init="random",
631
+ )
632
+ .fit(big_npy)
633
+ .cluster_centers_
634
+ )
635
+ except:
636
+ info = traceback.format_exc()
637
+ logger.info(info)
638
+ infos.append(info)
639
+ yield "\n".join(infos)
640
+
641
+ np.save("%s/total_fea.npy" % exp_dir, big_npy)
642
+ n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
643
+ infos.append("%s,%s" % (big_npy.shape, n_ivf))
644
+ yield "\n".join(infos)
645
+ index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)
646
+ # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)
647
+ infos.append("training")
648
+ yield "\n".join(infos)
649
+ index_ivf = faiss.extract_index_ivf(index) #
650
+ index_ivf.nprobe = 1
651
+ index.train(big_npy)
652
+ faiss.write_index(
653
+ index,
654
+ "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"
655
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
656
+ )
657
+
658
+ infos.append("adding")
659
+ yield "\n".join(infos)
660
+ batch_size_add = 8192
661
+ for i in range(0, big_npy.shape[0], batch_size_add):
662
+ index.add(big_npy[i : i + batch_size_add])
663
+ faiss.write_index(
664
+ index,
665
+ "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"
666
+ % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
667
+ )
668
+ infos.append(
669
+ "成功构建索引,added_IVF%s_Flat_nprobe_%s_%s_%s.index"
670
+ % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
671
+ )
672
+ # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))
673
+ # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))
674
+ yield "\n".join(infos)
675
+
676
+
677
+ # but5.click(train1key, [exp_dir1, sr2, if_f0_3, trainset_dir4, spk_id5, gpus6, np7, f0method8, save_epoch10, total_epoch11, batch_size12, if_save_latest13, pretrained_G14, pretrained_D15, gpus16, if_cache_gpu17], info3)
678
+ def train1key(
679
+ exp_dir1,
680
+ sr2,
681
+ if_f0_3,
682
+ trainset_dir4,
683
+ spk_id5,
684
+ np7,
685
+ f0method8,
686
+ save_epoch10,
687
+ total_epoch11,
688
+ batch_size12,
689
+ if_save_latest13,
690
+ pretrained_G14,
691
+ pretrained_D15,
692
+ gpus16,
693
+ if_cache_gpu17,
694
+ if_save_every_weights18,
695
+ version19,
696
+ gpus_rmvpe,
697
+ ):
698
+ infos = []
699
+
700
+ def get_info_str(strr):
701
+ infos.append(strr)
702
+ return "\n".join(infos)
703
+
704
+ ####### step1:处理数据
705
+ yield get_info_str(i18n("step1:正在处理数据"))
706
+ [get_info_str(_) for _ in preprocess_dataset(trainset_dir4, exp_dir1, sr2, np7)]
707
+
708
+ ####### step2a:提取音高
709
+ yield get_info_str(i18n("step2:正在提取音高&正在提取特征"))
710
+ [
711
+ get_info_str(_)
712
+ for _ in extract_f0_feature(
713
+ gpus16, np7, f0method8, if_f0_3, exp_dir1, version19, gpus_rmvpe
714
+ )
715
+ ]
716
+
717
+ ####### step3a:训练模型
718
+ yield get_info_str(i18n("step3a:正在训练模型"))
719
+ click_train(
720
+ exp_dir1,
721
+ sr2,
722
+ if_f0_3,
723
+ spk_id5,
724
+ save_epoch10,
725
+ total_epoch11,
726
+ batch_size12,
727
+ if_save_latest13,
728
+ pretrained_G14,
729
+ pretrained_D15,
730
+ gpus16,
731
+ if_cache_gpu17,
732
+ if_save_every_weights18,
733
+ version19,
734
+ )
735
+ yield get_info_str(i18n("训练结束, 您可查看控制台训练日志或实验文件夹下的train.log"))
736
+
737
+ ####### step3b:训练索引
738
+ [get_info_str(_) for _ in train_index(exp_dir1, version19)]
739
+ yield get_info_str(i18n("全流程结束!"))
740
+
741
+
742
+ # ckpt_path2.change(change_info_,[ckpt_path2],[sr__,if_f0__])
743
+ def change_info_(ckpt_path):
744
+ if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):
745
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
746
+ try:
747
+ with open(
748
+ ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"
749
+ ) as f:
750
+ info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])
751
+ sr, f0 = info["sample_rate"], info["if_f0"]
752
+ version = "v2" if ("version" in info and info["version"] == "v2") else "v1"
753
+ return sr, str(f0), version
754
+ except:
755
+ traceback.print_exc()
756
+ return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
757
+
758
+
759
+ F0GPUVisible = config.dml == False
760
+
761
+
762
+ def change_f0_method(f0method8):
763
+ if f0method8 == "rmvpe_gpu":
764
+ visible = F0GPUVisible
765
+ else:
766
+ visible = False
767
+ return {"visible": visible, "__type__": "update"}
768
+
769
+
770
+ with gr.Blocks(title="RVC WebUI") as app:
771
+ gr.Markdown(
772
+ value=i18n(
773
+ "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该���款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>LICENSE</b>."
774
+ )
775
+ )
776
+ with gr.Tabs():
777
+ with gr.TabItem(i18n("模型推理")):
778
+ with gr.Row():
779
+ sid0 = gr.Dropdown(label=i18n("推理音色"), choices=sorted(names))
780
+ refresh_button = gr.Button(i18n("刷新音色列表和索引路径"), variant="primary")
781
+ clean_button = gr.Button(i18n("卸载音色省显存"), variant="primary")
782
+ spk_item = gr.Slider(
783
+ minimum=0,
784
+ maximum=2333,
785
+ step=1,
786
+ label=i18n("请选择说话人id"),
787
+ value=0,
788
+ visible=False,
789
+ interactive=True,
790
+ )
791
+ clean_button.click(
792
+ fn=clean, inputs=[], outputs=[sid0], api_name="infer_clean"
793
+ )
794
+ with gr.Group():
795
+ gr.Markdown(
796
+ value=i18n("男转女推荐+12key, 女转男推荐-12key, 如果音域爆炸导致音色失真也可以自己调整到合适音域. ")
797
+ )
798
+ with gr.Row():
799
+ with gr.Column():
800
+ vc_transform0 = gr.Number(
801
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
802
+ )
803
+ input_audio0 = gr.Textbox(
804
+ label=i18n("输入待处理音频文件路径(默认是正确格式示例)"),
805
+ value="E:\\codes\\py39\\test-20230416b\\todo-songs\\冬之花clip1.wav",
806
+ )
807
+ f0method0 = gr.Radio(
808
+ label=i18n(
809
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
810
+ ),
811
+ choices=["pm", "harvest", "crepe", "rmvpe"]
812
+ if config.dml == False
813
+ else ["pm", "harvest", "rmvpe"],
814
+ value="pm",
815
+ interactive=True,
816
+ )
817
+ filter_radius0 = gr.Slider(
818
+ minimum=0,
819
+ maximum=7,
820
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
821
+ value=3,
822
+ step=1,
823
+ interactive=True,
824
+ )
825
+ with gr.Column():
826
+ file_index1 = gr.Textbox(
827
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
828
+ value="",
829
+ interactive=True,
830
+ )
831
+ file_index2 = gr.Dropdown(
832
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
833
+ choices=sorted(index_paths),
834
+ interactive=True,
835
+ )
836
+ refresh_button.click(
837
+ fn=change_choices,
838
+ inputs=[],
839
+ outputs=[sid0, file_index2],
840
+ api_name="infer_refresh",
841
+ )
842
+ # file_big_npy1 = gr.Textbox(
843
+ # label=i18n("特征文件路径"),
844
+ # value="E:\\codes\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
845
+ # interactive=True,
846
+ # )
847
+ index_rate1 = gr.Slider(
848
+ minimum=0,
849
+ maximum=1,
850
+ label=i18n("检索特征占比"),
851
+ value=0.75,
852
+ interactive=True,
853
+ )
854
+ with gr.Column():
855
+ resample_sr0 = gr.Slider(
856
+ minimum=0,
857
+ maximum=48000,
858
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
859
+ value=0,
860
+ step=1,
861
+ interactive=True,
862
+ )
863
+ rms_mix_rate0 = gr.Slider(
864
+ minimum=0,
865
+ maximum=1,
866
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
867
+ value=0.25,
868
+ interactive=True,
869
+ )
870
+ protect0 = gr.Slider(
871
+ minimum=0,
872
+ maximum=0.5,
873
+ label=i18n(
874
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
875
+ ),
876
+ value=0.33,
877
+ step=0.01,
878
+ interactive=True,
879
+ )
880
+ f0_file = gr.File(label=i18n("F0曲线文件, 可选, 一行一个音高, 代替默认F0及升降调"))
881
+ but0 = gr.Button(i18n("转换"), variant="primary")
882
+ with gr.Row():
883
+ vc_output1 = gr.Textbox(label=i18n("输出信息"))
884
+ vc_output2 = gr.Audio(label=i18n("输出音频(右下角三个点,点了可以下载)"))
885
+ but0.click(
886
+ vc.vc_single,
887
+ [
888
+ spk_item,
889
+ input_audio0,
890
+ vc_transform0,
891
+ f0_file,
892
+ f0method0,
893
+ file_index1,
894
+ file_index2,
895
+ # file_big_npy1,
896
+ index_rate1,
897
+ filter_radius0,
898
+ resample_sr0,
899
+ rms_mix_rate0,
900
+ protect0,
901
+ ],
902
+ [vc_output1, vc_output2],
903
+ api_name="infer_convert",
904
+ )
905
+ with gr.Group():
906
+ gr.Markdown(
907
+ value=i18n("批量转换, 输入待转换音频文件夹, 或上传多个音频文件, 在指定文件夹(默认opt)下输出转换的音频. ")
908
+ )
909
+ with gr.Row():
910
+ with gr.Column():
911
+ vc_transform1 = gr.Number(
912
+ label=i18n("变调(整数, 半音数量, 升八度12降八度-12)"), value=0
913
+ )
914
+ opt_input = gr.Textbox(label=i18n("指定输出文件夹"), value="opt")
915
+ f0method1 = gr.Radio(
916
+ label=i18n(
917
+ "选择音高提取算法,输入歌声可用pm提速,harvest低音好但巨慢无比,crepe效果好但吃GPU,rmvpe效果最好且微吃GPU"
918
+ ),
919
+ choices=["pm", "harvest", "crepe", "rmvpe"]
920
+ if config.dml == False
921
+ else ["pm", "harvest", "rmvpe"],
922
+ value="pm",
923
+ interactive=True,
924
+ )
925
+ filter_radius1 = gr.Slider(
926
+ minimum=0,
927
+ maximum=7,
928
+ label=i18n(">=3则使用对harvest音高识别的结果使用中值滤波,数值为滤波半径,使用可以削弱哑音"),
929
+ value=3,
930
+ step=1,
931
+ interactive=True,
932
+ )
933
+ with gr.Column():
934
+ file_index3 = gr.Textbox(
935
+ label=i18n("特征检索库文件路径,为空则使用下拉的选择结果"),
936
+ value="",
937
+ interactive=True,
938
+ )
939
+ file_index4 = gr.Dropdown(
940
+ label=i18n("自动检测index路径,下拉式选择(dropdown)"),
941
+ choices=sorted(index_paths),
942
+ interactive=True,
943
+ )
944
+ refresh_button.click(
945
+ fn=lambda: change_choices()[1],
946
+ inputs=[],
947
+ outputs=file_index4,
948
+ api_name="infer_refresh_batch",
949
+ )
950
+ # file_big_npy2 = gr.Textbox(
951
+ # label=i18n("特征文件路径"),
952
+ # value="E:\\codes\\py39\\vits_vc_gpu_train\\logs\\mi-test-1key\\total_fea.npy",
953
+ # interactive=True,
954
+ # )
955
+ index_rate2 = gr.Slider(
956
+ minimum=0,
957
+ maximum=1,
958
+ label=i18n("检索特征占比"),
959
+ value=1,
960
+ interactive=True,
961
+ )
962
+ with gr.Column():
963
+ resample_sr1 = gr.Slider(
964
+ minimum=0,
965
+ maximum=48000,
966
+ label=i18n("后处理重采样至最终采样率,0为不进行重采样"),
967
+ value=0,
968
+ step=1,
969
+ interactive=True,
970
+ )
971
+ rms_mix_rate1 = gr.Slider(
972
+ minimum=0,
973
+ maximum=1,
974
+ label=i18n("输入源音量包络替换输出音量包络融合比例,越靠近1越使用输出包络"),
975
+ value=1,
976
+ interactive=True,
977
+ )
978
+ protect1 = gr.Slider(
979
+ minimum=0,
980
+ maximum=0.5,
981
+ label=i18n(
982
+ "保护清辅音和呼吸声,防止电音撕裂等artifact,拉满0.5不开启,调低加大保护力度但可能降低索引效果"
983
+ ),
984
+ value=0.33,
985
+ step=0.01,
986
+ interactive=True,
987
+ )
988
+ with gr.Column():
989
+ dir_input = gr.Textbox(
990
+ label=i18n("输入待处理音频文件夹路径(去文件管理器地址栏拷就行了)"),
991
+ value="E:\codes\py39\\test-20230416b\\todo-songs",
992
+ )
993
+ inputs = gr.File(
994
+ file_count="multiple", label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹")
995
+ )
996
+ with gr.Row():
997
+ format1 = gr.Radio(
998
+ label=i18n("导出文件格式"),
999
+ choices=["wav", "flac", "mp3", "m4a"],
1000
+ value="flac",
1001
+ interactive=True,
1002
+ )
1003
+ but1 = gr.Button(i18n("转换"), variant="primary")
1004
+ vc_output3 = gr.Textbox(label=i18n("输出信息"))
1005
+ but1.click(
1006
+ vc.vc_multi,
1007
+ [
1008
+ spk_item,
1009
+ dir_input,
1010
+ opt_input,
1011
+ inputs,
1012
+ vc_transform1,
1013
+ f0method1,
1014
+ file_index3,
1015
+ file_index4,
1016
+ # file_big_npy2,
1017
+ index_rate2,
1018
+ filter_radius1,
1019
+ resample_sr1,
1020
+ rms_mix_rate1,
1021
+ protect1,
1022
+ format1,
1023
+ ],
1024
+ [vc_output3],
1025
+ api_name="infer_convert_batch",
1026
+ )
1027
+ sid0.change(
1028
+ fn=vc.get_vc,
1029
+ inputs=[sid0, protect0, protect1],
1030
+ outputs=[spk_item, protect0, protect1, file_index2, file_index4],
1031
+ )
1032
+ with gr.TabItem(i18n("伴奏人声分离&去混响&去回声")):
1033
+ with gr.Group():
1034
+ gr.Markdown(
1035
+ value=i18n(
1036
+ "人声伴奏分离批量处理, 使用UVR5模型。 <br>合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。 <br>模型分为三类: <br>1、保留人声:不带和声的音频选这个,对主人声保留比HP5更好。内置HP2和HP3两个模型,HP3可能轻微漏伴奏但对主人声保留比HP2稍微好一丁点; <br>2、仅保留主人声:带和声的音频选这个,对主人声可能有削弱。内置HP5一个模型; <br> 3、去混响、去延迟模型(by FoxJoy):<br>  (1)MDX-Net(onnx_dereverb):对于双通道混响是最好的选择,不能去除单通道混响;<br>&emsp;(234)DeEcho:去除延迟效果。Aggressive比Normal去除得更彻底,DeReverb额外去除混响,可去除单声道混响,但是对高频重的板式混响去不干净。<br>去混响/去延迟,附:<br>1、DeEcho-DeReverb模型的耗时是另外2个DeEcho模型的接近2倍;<br>2、MDX-Net-Dereverb模型挺慢的;<br>3、个人推荐的最干净的配置是先MDX-Net再DeEcho-Aggressive。"
1037
+ )
1038
+ )
1039
+ with gr.Row():
1040
+ with gr.Column():
1041
+ dir_wav_input = gr.Textbox(
1042
+ label=i18n("输入待处理音频文件夹路径"),
1043
+ value="E:\\codes\\py39\\test-20230416b\\todo-songs\\todo-songs",
1044
+ )
1045
+ wav_inputs = gr.File(
1046
+ file_count="multiple", label=i18n("也可批量输入音频文件, 二选一, 优先读文件夹")
1047
+ )
1048
+ with gr.Column():
1049
+ model_choose = gr.Dropdown(label=i18n("模型"), choices=uvr5_names)
1050
+ agg = gr.Slider(
1051
+ minimum=0,
1052
+ maximum=20,
1053
+ step=1,
1054
+ label="人声提取激进程度",
1055
+ value=10,
1056
+ interactive=True,
1057
+ visible=False, # 先不开放调整
1058
+ )
1059
+ opt_vocal_root = gr.Textbox(
1060
+ label=i18n("指定输出主人声文件夹"), value="opt"
1061
+ )
1062
+ opt_ins_root = gr.Textbox(
1063
+ label=i18n("指定输出非主人声文件夹"), value="opt"
1064
+ )
1065
+ format0 = gr.Radio(
1066
+ label=i18n("导出文件格式"),
1067
+ choices=["wav", "flac", "mp3", "m4a"],
1068
+ value="flac",
1069
+ interactive=True,
1070
+ )
1071
+ but2 = gr.Button(i18n("转换"), variant="primary")
1072
+ vc_output4 = gr.Textbox(label=i18n("输出信息"))
1073
+ but2.click(
1074
+ uvr,
1075
+ [
1076
+ model_choose,
1077
+ dir_wav_input,
1078
+ opt_vocal_root,
1079
+ wav_inputs,
1080
+ opt_ins_root,
1081
+ agg,
1082
+ format0,
1083
+ ],
1084
+ [vc_output4],
1085
+ api_name="uvr_convert",
1086
+ )
1087
+ with gr.TabItem(i18n("训练")):
1088
+ gr.Markdown(
1089
+ value=i18n(
1090
+ "step1: 填写实验配置. 实验数据放在logs下, 每个实验一个文件夹, 需手工输入实验名路径, 内含实验配置, 日志, 训练得到的模型文件. "
1091
+ )
1092
+ )
1093
+ with gr.Row():
1094
+ exp_dir1 = gr.Textbox(label=i18n("输入实验名"), value="mi-test")
1095
+ sr2 = gr.Radio(
1096
+ label=i18n("目标采样率"),
1097
+ choices=["40k", "48k"],
1098
+ value="40k",
1099
+ interactive=True,
1100
+ )
1101
+ if_f0_3 = gr.Radio(
1102
+ label=i18n("模型是否带音高指导(唱歌一定要, 语音可以不要)"),
1103
+ choices=[True, False],
1104
+ value=True,
1105
+ interactive=True,
1106
+ )
1107
+ version19 = gr.Radio(
1108
+ label=i18n("版本"),
1109
+ choices=["v1", "v2"],
1110
+ value="v2",
1111
+ interactive=True,
1112
+ visible=True,
1113
+ )
1114
+ np7 = gr.Slider(
1115
+ minimum=0,
1116
+ maximum=config.n_cpu,
1117
+ step=1,
1118
+ label=i18n("提取音高和处理数据使用的CPU进程数"),
1119
+ value=int(np.ceil(config.n_cpu / 1.5)),
1120
+ interactive=True,
1121
+ )
1122
+ with gr.Group(): # 暂时单人的, 后面支持最多4人的#数据处理
1123
+ gr.Markdown(
1124
+ value=i18n(
1125
+ "step2a: 自动遍历训练文件夹下所有可解码成音频的文件并进行切片归一化, 在实验目录下生成2个wav文件夹; 暂时只支持单人训练. "
1126
+ )
1127
+ )
1128
+ with gr.Row():
1129
+ trainset_dir4 = gr.Textbox(
1130
+ label=i18n("输入训练文件夹路径"), value="E:\\语音音频+标注\\米津玄师\\src"
1131
+ )
1132
+ spk_id5 = gr.Slider(
1133
+ minimum=0,
1134
+ maximum=4,
1135
+ step=1,
1136
+ label=i18n("请指定说话人id"),
1137
+ value=0,
1138
+ interactive=True,
1139
+ )
1140
+ but1 = gr.Button(i18n("处理数据"), variant="primary")
1141
+ info1 = gr.Textbox(label=i18n("输出信息"), value="")
1142
+ but1.click(
1143
+ preprocess_dataset,
1144
+ [trainset_dir4, exp_dir1, sr2, np7],
1145
+ [info1],
1146
+ api_name="train_preprocess",
1147
+ )
1148
+ with gr.Group():
1149
+ gr.Markdown(value=i18n("step2b: 使用CPU提取音高(如果模型带音高), 使用GPU提取特征(选择卡号)"))
1150
+ with gr.Row():
1151
+ with gr.Column():
1152
+ gpus6 = gr.Textbox(
1153
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1154
+ value=gpus,
1155
+ interactive=True,
1156
+ visible=F0GPUVisible,
1157
+ )
1158
+ gpu_info9 = gr.Textbox(
1159
+ label=i18n("显卡信息"), value=gpu_info, visible=F0GPUVisible
1160
+ )
1161
+ with gr.Column():
1162
+ f0method8 = gr.Radio(
1163
+ label=i18n(
1164
+ "选择音高提取算法:输入歌声可用pm提速,高质量语音但CPU差可用dio提速,harvest质量更好但慢,rmvpe效果最好且微吃CPU/GPU"
1165
+ ),
1166
+ choices=["pm", "harvest", "dio", "rmvpe", "rmvpe_gpu"],
1167
+ value="rmvpe_gpu",
1168
+ interactive=True,
1169
+ )
1170
+ gpus_rmvpe = gr.Textbox(
1171
+ label=i18n(
1172
+ "rmvpe卡号配置:以-分隔输入使用的不同进程卡号,例如0-0-1使用在卡0上跑2个进程并在卡1上跑1个进程"
1173
+ ),
1174
+ value="%s-%s" % (gpus, gpus),
1175
+ interactive=True,
1176
+ visible=F0GPUVisible,
1177
+ )
1178
+ but2 = gr.Button(i18n("特征提取"), variant="primary")
1179
+ info2 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1180
+ f0method8.change(
1181
+ fn=change_f0_method,
1182
+ inputs=[f0method8],
1183
+ outputs=[gpus_rmvpe],
1184
+ )
1185
+ but2.click(
1186
+ extract_f0_feature,
1187
+ [
1188
+ gpus6,
1189
+ np7,
1190
+ f0method8,
1191
+ if_f0_3,
1192
+ exp_dir1,
1193
+ version19,
1194
+ gpus_rmvpe,
1195
+ ],
1196
+ [info2],
1197
+ api_name="train_extract_f0_feature",
1198
+ )
1199
+ with gr.Group():
1200
+ gr.Markdown(value=i18n("step3: 填写训练设置, 开始训练模型和索引"))
1201
+ with gr.Row():
1202
+ save_epoch10 = gr.Slider(
1203
+ minimum=1,
1204
+ maximum=50,
1205
+ step=1,
1206
+ label=i18n("保存频率save_every_epoch"),
1207
+ value=5,
1208
+ interactive=True,
1209
+ )
1210
+ total_epoch11 = gr.Slider(
1211
+ minimum=2,
1212
+ maximum=1000,
1213
+ step=1,
1214
+ label=i18n("总训练轮数total_epoch"),
1215
+ value=20,
1216
+ interactive=True,
1217
+ )
1218
+ batch_size12 = gr.Slider(
1219
+ minimum=1,
1220
+ maximum=40,
1221
+ step=1,
1222
+ label=i18n("每张显卡的batch_size"),
1223
+ value=default_batch_size,
1224
+ interactive=True,
1225
+ )
1226
+ if_save_latest13 = gr.Radio(
1227
+ label=i18n("是否仅保存最新的ckpt文件以节省硬盘空间"),
1228
+ choices=[i18n("是"), i18n("否")],
1229
+ value=i18n("否"),
1230
+ interactive=True,
1231
+ )
1232
+ if_cache_gpu17 = gr.Radio(
1233
+ label=i18n(
1234
+ "是否缓存所有训练集至显存. 10min以下小数据可缓存以加速训练, 大数据缓存会炸显存也加不了多少速"
1235
+ ),
1236
+ choices=[i18n("是"), i18n("否")],
1237
+ value=i18n("否"),
1238
+ interactive=True,
1239
+ )
1240
+ if_save_every_weights18 = gr.Radio(
1241
+ label=i18n("是否在每次保存时间点将最终小模型保存至weights文件夹"),
1242
+ choices=[i18n("是"), i18n("否")],
1243
+ value=i18n("否"),
1244
+ interactive=True,
1245
+ )
1246
+ with gr.Row():
1247
+ pretrained_G14 = gr.Textbox(
1248
+ label=i18n("加载预训练底模G路径"),
1249
+ value="assets/pretrained_v2/f0G40k.pth",
1250
+ interactive=True,
1251
+ )
1252
+ pretrained_D15 = gr.Textbox(
1253
+ label=i18n("加载预训练底模D路径"),
1254
+ value="assets/pretrained_v2/f0D40k.pth",
1255
+ interactive=True,
1256
+ )
1257
+ sr2.change(
1258
+ change_sr2,
1259
+ [sr2, if_f0_3, version19],
1260
+ [pretrained_G14, pretrained_D15],
1261
+ )
1262
+ version19.change(
1263
+ change_version19,
1264
+ [sr2, if_f0_3, version19],
1265
+ [pretrained_G14, pretrained_D15, sr2],
1266
+ )
1267
+ if_f0_3.change(
1268
+ change_f0,
1269
+ [if_f0_3, sr2, version19],
1270
+ [f0method8, pretrained_G14, pretrained_D15],
1271
+ )
1272
+ gpus16 = gr.Textbox(
1273
+ label=i18n("以-分隔输入使用的卡号, 例如 0-1-2 使用卡0和卡1和卡2"),
1274
+ value=gpus,
1275
+ interactive=True,
1276
+ )
1277
+ but3 = gr.Button(i18n("训练模型"), variant="primary")
1278
+ but4 = gr.Button(i18n("训练特征索引"), variant="primary")
1279
+ but5 = gr.Button(i18n("一键训练"), variant="primary")
1280
+ info3 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=10)
1281
+ but3.click(
1282
+ click_train,
1283
+ [
1284
+ exp_dir1,
1285
+ sr2,
1286
+ if_f0_3,
1287
+ spk_id5,
1288
+ save_epoch10,
1289
+ total_epoch11,
1290
+ batch_size12,
1291
+ if_save_latest13,
1292
+ pretrained_G14,
1293
+ pretrained_D15,
1294
+ gpus16,
1295
+ if_cache_gpu17,
1296
+ if_save_every_weights18,
1297
+ version19,
1298
+ ],
1299
+ info3,
1300
+ api_name="train_start",
1301
+ )
1302
+ but4.click(train_index, [exp_dir1, version19], info3)
1303
+ but5.click(
1304
+ train1key,
1305
+ [
1306
+ exp_dir1,
1307
+ sr2,
1308
+ if_f0_3,
1309
+ trainset_dir4,
1310
+ spk_id5,
1311
+ np7,
1312
+ f0method8,
1313
+ save_epoch10,
1314
+ total_epoch11,
1315
+ batch_size12,
1316
+ if_save_latest13,
1317
+ pretrained_G14,
1318
+ pretrained_D15,
1319
+ gpus16,
1320
+ if_cache_gpu17,
1321
+ if_save_every_weights18,
1322
+ version19,
1323
+ gpus_rmvpe,
1324
+ ],
1325
+ info3,
1326
+ api_name="train_start_all",
1327
+ )
1328
+
1329
+ with gr.TabItem(i18n("ckpt处理")):
1330
+ with gr.Group():
1331
+ gr.Markdown(value=i18n("模型融合, 可用于测试音色融合"))
1332
+ with gr.Row():
1333
+ ckpt_a = gr.Textbox(label=i18n("A模型路径"), value="", interactive=True)
1334
+ ckpt_b = gr.Textbox(label=i18n("B模型路径"), value="", interactive=True)
1335
+ alpha_a = gr.Slider(
1336
+ minimum=0,
1337
+ maximum=1,
1338
+ label=i18n("A模型权重"),
1339
+ value=0.5,
1340
+ interactive=True,
1341
+ )
1342
+ with gr.Row():
1343
+ sr_ = gr.Radio(
1344
+ label=i18n("目标采样率"),
1345
+ choices=["40k", "48k"],
1346
+ value="40k",
1347
+ interactive=True,
1348
+ )
1349
+ if_f0_ = gr.Radio(
1350
+ label=i18n("模型是否带音高指导"),
1351
+ choices=[i18n("是"), i18n("否")],
1352
+ value=i18n("是"),
1353
+ interactive=True,
1354
+ )
1355
+ info__ = gr.Textbox(
1356
+ label=i18n("要置入的模型信息"), value="", max_lines=8, interactive=True
1357
+ )
1358
+ name_to_save0 = gr.Textbox(
1359
+ label=i18n("保存的模型名不带后缀"),
1360
+ value="",
1361
+ max_lines=1,
1362
+ interactive=True,
1363
+ )
1364
+ version_2 = gr.Radio(
1365
+ label=i18n("模型版本型号"),
1366
+ choices=["v1", "v2"],
1367
+ value="v1",
1368
+ interactive=True,
1369
+ )
1370
+ with gr.Row():
1371
+ but6 = gr.Button(i18n("融合"), variant="primary")
1372
+ info4 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1373
+ but6.click(
1374
+ merge,
1375
+ [
1376
+ ckpt_a,
1377
+ ckpt_b,
1378
+ alpha_a,
1379
+ sr_,
1380
+ if_f0_,
1381
+ info__,
1382
+ name_to_save0,
1383
+ version_2,
1384
+ ],
1385
+ info4,
1386
+ api_name="ckpt_merge",
1387
+ ) # def merge(path1,path2,alpha1,sr,f0,info):
1388
+ with gr.Group():
1389
+ gr.Markdown(value=i18n("修改模型信息(仅支持weights文件夹下提取的小模型文件)"))
1390
+ with gr.Row():
1391
+ ckpt_path0 = gr.Textbox(
1392
+ label=i18n("模型路径"), value="", interactive=True
1393
+ )
1394
+ info_ = gr.Textbox(
1395
+ label=i18n("要改的模型信息"), value="", max_lines=8, interactive=True
1396
+ )
1397
+ name_to_save1 = gr.Textbox(
1398
+ label=i18n("保存的文件名, 默认空为和源文件同名"),
1399
+ value="",
1400
+ max_lines=8,
1401
+ interactive=True,
1402
+ )
1403
+ with gr.Row():
1404
+ but7 = gr.Button(i18n("修改"), variant="primary")
1405
+ info5 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1406
+ but7.click(
1407
+ change_info,
1408
+ [ckpt_path0, info_, name_to_save1],
1409
+ info5,
1410
+ api_name="ckpt_modify",
1411
+ )
1412
+ with gr.Group():
1413
+ gr.Markdown(value=i18n("查看模型信息(仅支持weights文件夹下提取的小模型文件)"))
1414
+ with gr.Row():
1415
+ ckpt_path1 = gr.Textbox(
1416
+ label=i18n("模型路径"), value="", interactive=True
1417
+ )
1418
+ but8 = gr.Button(i18n("查看"), variant="primary")
1419
+ info6 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1420
+ but8.click(show_info, [ckpt_path1], info6, api_name="ckpt_show")
1421
+ with gr.Group():
1422
+ gr.Markdown(
1423
+ value=i18n(
1424
+ "模型提取(输入logs文件夹下大文件模型路径),适用于训一半不想训了模型没有自动提取保存小文件模型,或者想测试中间模型的情况"
1425
+ )
1426
+ )
1427
+ with gr.Row():
1428
+ ckpt_path2 = gr.Textbox(
1429
+ label=i18n("模型路径"),
1430
+ value="E:\\codes\\py39\\logs\\mi-test_f0_48k\\G_23333.pth",
1431
+ interactive=True,
1432
+ )
1433
+ save_name = gr.Textbox(
1434
+ label=i18n("保存名"), value="", interactive=True
1435
+ )
1436
+ sr__ = gr.Radio(
1437
+ label=i18n("目标采样率"),
1438
+ choices=["32k", "40k", "48k"],
1439
+ value="40k",
1440
+ interactive=True,
1441
+ )
1442
+ if_f0__ = gr.Radio(
1443
+ label=i18n("模型是否带音高指导,1是0否"),
1444
+ choices=["1", "0"],
1445
+ value="1",
1446
+ interactive=True,
1447
+ )
1448
+ version_1 = gr.Radio(
1449
+ label=i18n("模型版本型号"),
1450
+ choices=["v1", "v2"],
1451
+ value="v2",
1452
+ interactive=True,
1453
+ )
1454
+ info___ = gr.Textbox(
1455
+ label=i18n("要置入的模型信息"), value="", max_lines=8, interactive=True
1456
+ )
1457
+ but9 = gr.Button(i18n("提取"), variant="primary")
1458
+ info7 = gr.Textbox(label=i18n("输出信息"), value="", max_lines=8)
1459
+ ckpt_path2.change(
1460
+ change_info_, [ckpt_path2], [sr__, if_f0__, version_1]
1461
+ )
1462
+ but9.click(
1463
+ extract_small_model,
1464
+ [ckpt_path2, save_name, sr__, if_f0__, info___, version_1],
1465
+ info7,
1466
+ api_name="ckpt_extract",
1467
+ )
1468
+
1469
+ with gr.TabItem(i18n("Onnx导出")):
1470
+ with gr.Row():
1471
+ ckpt_dir = gr.Textbox(label=i18n("RVC模型路径"), value="", interactive=True)
1472
+ with gr.Row():
1473
+ onnx_dir = gr.Textbox(
1474
+ label=i18n("Onnx输出路径"), value="", interactive=True
1475
+ )
1476
+ with gr.Row():
1477
+ infoOnnx = gr.Label(label="info")
1478
+ with gr.Row():
1479
+ butOnnx = gr.Button(i18n("导出Onnx模型"), variant="primary")
1480
+ butOnnx.click(
1481
+ export_onnx, [ckpt_dir, onnx_dir], infoOnnx, api_name="export_onnx"
1482
+ )
1483
+
1484
+ tab_faq = i18n("常见问题解答")
1485
+ with gr.TabItem(tab_faq):
1486
+ try:
1487
+ if tab_faq == "常见问题解答":
1488
+ with open("docs/cn/faq.md", "r", encoding="utf8") as f:
1489
+ info = f.read()
1490
+ else:
1491
+ with open("docs/en/faq_en.md", "r", encoding="utf8") as f:
1492
+ info = f.read()
1493
+ gr.Markdown(value=info)
1494
+ except:
1495
+ gr.Markdown(traceback.format_exc())
1496
+
1497
+ if config.iscolab:
1498
+ app.queue(concurrency_count=511, max_size=1022).launch(share=True)
1499
+ else:
1500
+ app.queue(concurrency_count=511, max_size=1022).launch(
1501
+ server_name="0.0.0.0",
1502
+ inbrowser=not config.noautoopen,
1503
+ server_port=config.listen_port,
1504
+ quiet=True,
1505
+ )
lp.gif ADDED
poetry.lock ADDED
The diff for this file is too large to render. See raw diff
 
pyproject.toml ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [tool.poetry]
2
+ name = "rvc-beta"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = ["lj1995"]
6
+ license = "MIT"
7
+
8
+ [tool.poetry.dependencies]
9
+ python = "^3.8"
10
+ torch = "^2.0.0"
11
+ torchaudio = "^2.0.1"
12
+ Cython = "^0.29.34"
13
+ gradio = "^3.34.0"
14
+ future = "^0.18.3"
15
+ pydub = "^0.25.1"
16
+ soundfile = "^0.12.1"
17
+ ffmpeg-python = "^0.2.0"
18
+ tensorboardX = "^2.6"
19
+ functorch = "^2.0.0"
20
+ fairseq = "^0.12.2"
21
+ faiss-cpu = "^1.7.2"
22
+ Jinja2 = "^3.1.2"
23
+ json5 = "^0.9.11"
24
+ librosa = "0.9.1"
25
+ llvmlite = "0.39.0"
26
+ Markdown = "^3.4.3"
27
+ matplotlib = "^3.7.1"
28
+ matplotlib-inline = "^0.1.6"
29
+ numba = "0.56.4"
30
+ numpy = "1.23.5"
31
+ scipy = "1.9.3"
32
+ praat-parselmouth = "^0.4.3"
33
+ Pillow = "9.3.0"
34
+ pyworld = "^0.3.2"
35
+ resampy = "^0.4.2"
36
+ scikit-learn = "^1.2.2"
37
+ starlette = "^0.27.0"
38
+ tensorboard = "^2.12.1"
39
+ tensorboard-data-server = "^0.7.0"
40
+ tensorboard-plugin-wit = "^1.8.1"
41
+ torchgen = "^0.0.1"
42
+ tqdm = "^4.65.0"
43
+ tornado = "^6.3"
44
+ Werkzeug = "^2.2.3"
45
+ uc-micro-py = "^1.0.1"
46
+ sympy = "^1.11.1"
47
+ tabulate = "^0.9.0"
48
+ PyYAML = "^6.0"
49
+ pyasn1 = "^0.4.8"
50
+ pyasn1-modules = "^0.2.8"
51
+ fsspec = "^2023.3.0"
52
+ absl-py = "^1.4.0"
53
+ audioread = "^3.0.0"
54
+ uvicorn = "^0.21.1"
55
+ colorama = "^0.4.6"
56
+ torchcrepe = "0.0.20"
57
+ python-dotenv = "^1.0.0"
58
+
59
+ [tool.poetry.dev-dependencies]
60
+
61
+ [build-system]
62
+ requires = ["poetry-core>=1.0.0"]
63
+ build-backend = "poetry.core.masonry.api"
requirements-dml.txt ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gdown
2
+ mega.py
3
+ joblib>=1.1.0
4
+ numba==0.56.4
5
+ numpy==1.23.5
6
+ scipy
7
+ librosa==0.9.1
8
+ llvmlite==0.39.0
9
+ fairseq==0.12.2
10
+ faiss-cpu==1.7.3
11
+ gradio==3.34.0
12
+ Cython
13
+ pydub>=0.25.1
14
+ soundfile>=0.12.1
15
+ ffmpeg-python>=0.2.0
16
+ tensorboardX
17
+ Jinja2>=3.1.2
18
+ json5
19
+ Markdown
20
+ matplotlib>=3.7.0
21
+ matplotlib-inline>=0.1.3
22
+ praat-parselmouth>=0.4.2
23
+ Pillow>=9.1.1
24
+ resampy>=0.4.2
25
+ scikit-learn
26
+ tensorboard
27
+ tqdm>=4.63.1
28
+ tornado>=6.1
29
+ Werkzeug>=2.2.3
30
+ uc-micro-py>=1.0.1
31
+ sympy>=1.11.1
32
+ tabulate>=0.8.10
33
+ PyYAML>=6.0
34
+ pyasn1>=0.4.8
35
+ pyasn1-modules>=0.2.8
36
+ fsspec>=2022.11.0
37
+ absl-py>=1.2.0
38
+ audioread
39
+ uvicorn>=0.21.1
40
+ colorama>=0.4.5
41
+ pyworld==0.3.2
42
+ httpx
43
+ onnxruntime-directml
44
+ torchcrepe==0.0.20
45
+ fastapi==0.88
46
+ ffmpy==0.3.1
47
+ python-dotenv>=1.0.0
48
+ av
requirements-ipex.txt ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch==2.0.1a0
2
+ intel_extension_for_pytorch==2.0.110+xpu
3
+ torchvision==0.15.2a0
4
+ https://github.com/Disty0/Retrieval-based-Voice-Conversion-WebUI/releases/download/torchaudio_wheels_for_ipex/torchaudio-2.0.2+31de77d-cp310-cp310-linux_x86_64.whl
5
+ -f https://developer.intel.com/ipex-whl-stable-xpu
6
+ joblib>=1.1.0
7
+ numba==0.56.4
8
+ numpy==1.23.5
9
+ scipy
10
+ librosa==0.9.1
11
+ llvmlite==0.39.0
12
+ fairseq==0.12.2
13
+ faiss-cpu==1.7.3
14
+ gradio==3.34.0
15
+ Cython
16
+ pydub>=0.25.1
17
+ soundfile>=0.12.1
18
+ ffmpeg-python>=0.2.0
19
+ tensorboardX
20
+ Jinja2>=3.1.2
21
+ json5
22
+ Markdown
23
+ matplotlib>=3.7.0
24
+ matplotlib-inline>=0.1.3
25
+ praat-parselmouth>=0.4.2
26
+ Pillow>=9.1.1
27
+ resampy>=0.4.2
28
+ scikit-learn
29
+ tensorboard
30
+ tqdm>=4.63.1
31
+ tornado>=6.1
32
+ Werkzeug>=2.2.3
33
+ uc-micro-py>=1.0.1
34
+ sympy>=1.11.1
35
+ tabulate>=0.8.10
36
+ PyYAML>=6.0
37
+ pyasn1>=0.4.8
38
+ pyasn1-modules>=0.2.8
39
+ fsspec>=2022.11.0
40
+ absl-py>=1.2.0
41
+ audioread
42
+ uvicorn>=0.21.1
43
+ colorama>=0.4.5
44
+ pyworld==0.3.2
45
+ httpx
46
+ onnxruntime; sys_platform == 'darwin'
47
+ onnxruntime-gpu; sys_platform != 'darwin'
48
+ torchcrepe==0.0.20
49
+ fastapi==0.88
50
+ ffmpy==0.3.1
51
+ python-dotenv>=1.0.0
52
+ av
53
+ PySimpleGUI
54
+ sounddevice
requirements-safe.txt ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ torchaudio
4
+ gdown
5
+ mega.py
6
+ joblib>=1.1.0
7
+ numba==0.56.4
8
+ numpy==1.22.0
9
+ scipy
10
+ librosa==0.9.1
11
+ llvmlite==0.39.0
12
+ fairseq==0.12.2
13
+ faiss-cpu==1.7.3
14
+ Cython
15
+ pydub>=0.25.1
16
+ soundfile>=0.12.1
17
+ ffmpeg-python>=0.2.0
18
+ tensorboardX
19
+ Jinja2>=3.1.2
20
+ json5
21
+ Markdown
22
+ matplotlib>=3.7.0
23
+ matplotlib-inline>=0.1.3
24
+ praat-parselmouth>=0.4.2
25
+ Pillow>=9.1.1
26
+ resampy>=0.4.2
27
+ scikit-learn
28
+ tensorboard
29
+ tqdm>=4.63.1
30
+ tornado>=6.1
31
+ Werkzeug>=2.2.3
32
+ uc-micro-py>=1.0.1
33
+ sympy>=1.11.1
34
+ tabulate>=0.8.10
35
+ PyYAML>=6.0
36
+ pyasn1>=0.4.8
37
+ pyasn1-modules>=0.2.8
38
+ fsspec>=2022.11.0
39
+ absl-py>=1.2.0
40
+ audioread
41
+ uvicorn>=0.21.1
42
+ colorama>=0.4.5
43
+ pyworld==0.3.2
44
+ httpx
45
+ onnxruntime; sys_platform == 'darwin'
46
+ onnxruntime-gpu; sys_platform != 'darwin'
47
+ torchcrepe==0.0.20
48
+ fastapi==0.88
49
+ ffmpy==0.3.1
50
+ python-dotenv>=1.0.0
51
+ av
52
+ pydantic==1.10.12
requirements-win-for-realtime_vc_gui-dml.txt ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #1.Install torch from pytorch.org:
2
+ #torch 2.0 with cuda 11.8
3
+ #pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
4
+ #torch 1.11.0 with cuda 11.3
5
+ #pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 torchaudio==0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113
6
+ einops
7
+ fairseq
8
+ flask
9
+ flask_cors
10
+ gin
11
+ gin_config
12
+ librosa
13
+ local_attention
14
+ matplotlib
15
+ praat-parselmouth
16
+ pyworld
17
+ PyYAML
18
+ resampy
19
+ scikit_learn
20
+ scipy
21
+ SoundFile
22
+ tensorboard
23
+ tqdm
24
+ wave
25
+ PySimpleGUI
26
+ sounddevice
27
+ gradio
28
+ noisereduce
29
+ onnxruntime-directml
requirements-win-for-realtime_vc_gui.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #1.Install torch from pytorch.org:
2
+ #torch 2.0 with cuda 11.8
3
+ #pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
4
+ #torch 1.11.0 with cuda 11.3
5
+ #pip install torch==1.11.0+cu113 torchvision==0.12.0+cu113 torchaudio==0.11.0 --extra-index-url https://download.pytorch.org/whl/cu113
6
+ einops
7
+ fairseq
8
+ flask
9
+ flask_cors
10
+ gin
11
+ gin_config
12
+ librosa
13
+ local_attention
14
+ matplotlib
15
+ praat-parselmouth
16
+ pyworld
17
+ PyYAML
18
+ resampy
19
+ scikit_learn
20
+ scipy
21
+ SoundFile
22
+ tensorboard
23
+ tqdm
24
+ wave
25
+ PySimpleGUI
26
+ sounddevice
27
+ gradio
28
+ noisereduce
requirements.txt ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ torchaudio
4
+ gdown
5
+ mega.py
6
+ joblib>=1.1.0
7
+ numba==0.56.4
8
+ numpy==1.22.0
9
+ scipy
10
+ librosa==0.9.1
11
+ llvmlite==0.39.0
12
+ fairseq==0.12.2
13
+ faiss-cpu==1.7.3
14
+ gradio==3.43.2
15
+ Cython
16
+ pydub>=0.25.1
17
+ soundfile>=0.12.1
18
+ ffmpeg-python>=0.2.0
19
+ tensorboardX
20
+ Jinja2>=3.1.2
21
+ json5
22
+ Markdown
23
+ matplotlib>=3.7.0
24
+ matplotlib-inline>=0.1.3
25
+ praat-parselmouth>=0.4.2
26
+ Pillow>=9.1.1
27
+ resampy>=0.4.2
28
+ scikit-learn
29
+ tensorboard
30
+ tqdm>=4.63.1
31
+ tornado>=6.1
32
+ Werkzeug>=2.2.3
33
+ uc-micro-py>=1.0.1
34
+ sympy>=1.11.1
35
+ tabulate>=0.8.10
36
+ PyYAML>=6.0
37
+ pyasn1>=0.4.8
38
+ pyasn1-modules>=0.2.8
39
+ fsspec>=2022.11.0
40
+ absl-py>=1.2.0
41
+ audioread
42
+ uvicorn>=0.21.1
43
+ colorama>=0.4.5
44
+ pyworld==0.3.2
45
+ httpx
46
+ onnxruntime; sys_platform == 'darwin'
47
+ onnxruntime-gpu; sys_platform != 'darwin'
48
+ torchcrepe==0.0.20
49
+ fastapi==0.88
50
+ ffmpy==0.3.1
51
+ python-dotenv>=1.0.0
52
+ av
53
+ pydantic==1.10.12
run.sh ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ if [[ "$(uname)" == "Darwin" ]]; then
4
+ # macOS specific env:
5
+ export PYTORCH_ENABLE_MPS_FALLBACK=1
6
+ export PYTORCH_MPS_HIGH_WATERMARK_RATIO=0.0
7
+ elif [[ "$(uname)" != "Linux" ]]; then
8
+ echo "Unsupported operating system."
9
+ exit 1
10
+ fi
11
+
12
+ if [ -d ".venv" ]; then
13
+ echo "Activate venv..."
14
+ source .venv/bin/activate
15
+ else
16
+ echo "Create venv..."
17
+ requirements_file="requirements.txt"
18
+
19
+ # Check if Python 3.8 is installed
20
+ if ! command -v python3 &> /dev/null; then
21
+ echo "Python 3 not found. Attempting to install 3.8..."
22
+ if [[ "$(uname)" == "Darwin" ]] && command -v brew &> /dev/null; then
23
+ brew install [email protected]
24
+ elif [[ "$(uname)" == "Linux" ]] && command -v apt-get &> /dev/null; then
25
+ sudo apt-get update
26
+ sudo apt-get install python3.8
27
+ else
28
+ echo "Please install Python 3.8 manually."
29
+ exit 1
30
+ fi
31
+ fi
32
+
33
+ python3 -m venv .venv
34
+ source .venv/bin/activate
35
+
36
+ # Check if required packages are installed and install them if not
37
+ if [ -f "${requirements_file}" ]; then
38
+ installed_packages=$(python3 -m pip freeze)
39
+ while IFS= read -r package; do
40
+ [[ "${package}" =~ ^#.* ]] && continue
41
+ package_name=$(echo "${package}" | sed 's/[<>=!].*//')
42
+ if ! echo "${installed_packages}" | grep -q "${package_name}"; then
43
+ echo "${package_name} not found. Attempting to install..."
44
+ python3 -m pip install --upgrade "${package}"
45
+ fi
46
+ done < "${requirements_file}"
47
+ else
48
+ echo "${requirements_file} not found. Please ensure the requirements file with required packages exists."
49
+ exit 1
50
+ fi
51
+ fi
52
+
53
+ # Download models
54
+ ./tools/dlmodels.sh
55
+
56
+ if [[ $? -ne 0 ]]; then
57
+ exit 1
58
+ fi
59
+
60
+ # Run the main script
61
+ python3 infer-web.py --pycmd python3
venv.sh ADDED
@@ -0,0 +1 @@
 
 
1
+ python3.8 -m venv .venv