Paolify/RVC_4
0
1import os, sys2os.system("pip install pyworld") # ==0.3.33 4now_dir = os.getcwd()5sys.path.append(now_dir)6os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'7os.environ["OPENBLAS_NUM_THREADS"] = "1"8os.environ["no_proxy"] = "localhost, 127.0.0.1, ::1"9 10# Download models11shell_script = './tools/dlmodels.sh'12os.system(f'chmod +x {shell_script}')13os.system('apt install git-lfs')14os.system('git lfs install')15os.system('apt-get -y install aria2')16os.system('aria2c --console-log-level=error -c -x 16 -s 16 -k 1M https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main/hubert_base.pt -d . -o hubert_base.pt')17try:18 return_code = os.system(shell_script)19 if return_code == 0:20 print("Shell script executed successfully.")21 else:22 print(f"Shell script failed with return code {return_code}")23except Exception as e:24 print(f"An error occurred: {e}")25 26 27import logging28import shutil29import threading30import lib.globals.globals as rvc_globals31from LazyImport import lazyload32import mdx33from mdx_processing_script import get_model_list,id_to_ptm,prepare_mdx,run_mdx34math = lazyload('math')35import traceback36import warnings37tensorlowest = lazyload('tensorlowest')38from random import shuffle39from subprocess import Popen40from time import sleep41import json42import pathlib43 44import fairseq45logging.getLogger("faiss").setLevel(logging.WARNING)46import faiss47gr = lazyload("gradio")48np = lazyload("numpy")49torch = lazyload('torch')50re = lazyload('regex')51SF = lazyload("soundfile")52SFWrite = SF.write53from dotenv import load_dotenv54from sklearn.cluster import MiniBatchKMeans55import datetime56 57 58from glob import glob159import signal60from signal import SIGTERM61import librosa62 63from configs.config import Config64from i18n import I18nAuto65from infer.lib.train.process_ckpt import (66 change_info,67 extract_small_model,68 merge,69 show_info,70)71#from infer.modules.uvr5.modules import uvr72from infer.modules.vc.modules import VC73from infer.modules.vc.utils import *74from infer.modules.vc.pipeline import Pipeline75import lib.globals.globals as rvc_globals76math = lazyload('math')77ffmpeg = lazyload('ffmpeg')78import nltk79nltk.download('punkt', quiet=True)80from nltk.tokenize import sent_tokenize81from bark import SAMPLE_RATE82 83import easy_infer84import audioEffects85from infer.lib.csvutil import CSVutil86 87from lib.infer_pack.models import (88 SynthesizerTrnMs256NSFsid,89 SynthesizerTrnMs256NSFsid_nono,90 SynthesizerTrnMs768NSFsid,91 SynthesizerTrnMs768NSFsid_nono,92)93from lib.infer_pack.models_onnx import SynthesizerTrnMsNSFsidM94from infer_uvr5 import _audio_pre_, _audio_pre_new95from MDXNet import MDXNetDereverb96from infer.lib.audio import load_audio97 98 99from sklearn.cluster import MiniBatchKMeans100 101import time102import csv103 104from shlex import quote as SQuote105 106 107 108 109RQuote = lambda val: SQuote(str(val))110 111tmp = os.path.join(now_dir, "TEMP")112runtime_dir = os.path.join(now_dir, "runtime/Lib/site-packages")113directories = ['logs', 'audios', 'datasets', 'weights', 'audio-others' , 'audio-outputs']114 115shutil.rmtree(tmp, ignore_errors=True)116shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)117shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)118 119os.makedirs(tmp, exist_ok=True)120for folder in directories:121 os.makedirs(os.path.join(now_dir, folder), exist_ok=True)122 123 124os.makedirs(tmp, exist_ok=True)125os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)126os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)127os.environ["TEMP"] = tmp128warnings.filterwarnings("ignore")129torch.manual_seed(114514)130logging.getLogger("numba").setLevel(logging.WARNING)131 132logger = logging.getLogger(__name__)133 134 135if not os.path.isdir("csvdb/"):136 os.makedirs("csvdb")137 frmnt, stp = open("csvdb/formanting.csv", "w"), open("csvdb/stop.csv", "w")138 frmnt.close()139 stp.close()140 141global DoFormant, Quefrency, Timbre142 143try:144 DoFormant, Quefrency, Timbre = CSVutil("csvdb/formanting.csv", "r", "formanting")145 DoFormant = (146 lambda DoFormant: True147 if DoFormant.lower() == "true"148 else (False if DoFormant.lower() == "false" else DoFormant)149 )(DoFormant)150except (ValueError, TypeError, IndexError):151 DoFormant, Quefrency, Timbre = False, 1.0, 1.0152 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, Quefrency, Timbre)153 154load_dotenv()155config = Config()156vc = VC(config)157 158if config.dml == True:159 160 def forward_dml(ctx, x, scale):161 ctx.scale = scale162 res = x.clone().detach()163 return res164 165 fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml166 167i18n = I18nAuto()168i18n.print()169# 判断是否有能用来训练和加速推理的N卡170ngpu = torch.cuda.device_count()171gpu_infos = []172mem = []173if_gpu_ok = False174 175isinterrupted = 0176 177 178if torch.cuda.is_available() or ngpu != 0:179 for i in range(ngpu):180 gpu_name = torch.cuda.get_device_name(i)181 if any(182 value in gpu_name.upper()183 for value in [184 "10",185 "16",186 "20",187 "30",188 "40",189 "A2",190 "A3",191 "A4",192 "P4",193 "A50",194 "500",195 "A60",196 "70",197 "80",198 "90",199 "M4",200 "T4",201 "TITAN",202 ]203 ):204 # A10#A100#V100#A40#P40#M40#K80#A4500205 if_gpu_ok = True # 至少有一张能用的N卡206 gpu_infos.append("%s\t%s" % (i, gpu_name))207 mem.append(208 int(209 torch.cuda.get_device_properties(i).total_memory210 / 1024211 / 1024212 / 1024213 + 0.4214 )215 )216if if_gpu_ok and len(gpu_infos) > 0:217 gpu_info = "\n".join(gpu_infos)218 default_batch_size = min(mem) // 2219else:220 gpu_info = "Unfortunately, there is no compatible GPU available to support your training."221 default_batch_size = 1222gpus = "-".join([i[0] for i in gpu_infos])223 224class ToolButton(gr.Button, gr.components.FormComponent):225 """Small button with single emoji as text, fits inside gradio forms"""226 227 def __init__(self, **kwargs):228 super().__init__(variant="tool", **kwargs)229 230 def get_block_name(self):231 return "button"232 233 234hubert_model = None235weight_root = os.getenv("weight_root")236weight_uvr5_root = os.getenv("weight_uvr5_root")237index_root = os.getenv("index_root")238datasets_root = "datasets"239fshift_root = "formantshiftcfg"240audio_root = "audios"241audio_others_root = "audio-others"242 243sup_audioext = {'wav', 'mp3', 'flac', 'ogg', 'opus',244 'm4a', 'mp4', 'aac', 'alac', 'wma',245 'aiff', 'webm', 'ac3'}246 247names = [os.path.join(root, file)248 for root, _, files in os.walk(weight_root)249 for file in files250 if file.endswith((".pth", ".onnx"))]251 252indexes_list = [os.path.join(root, name)253 for root, _, files in os.walk(index_root, topdown=False) 254 for name in files 255 if name.endswith(".index") and "trained" not in name]256 257audio_paths = [os.path.join(root, name)258 for root, _, files in os.walk(audio_root, topdown=False) 259 for name in files260 if name.endswith(tuple(sup_audioext))]261 262audio_others_paths = [os.path.join(root, name)263 for root, _, files in os.walk(audio_others_root, topdown=False) 264 for name in files265 if name.endswith(tuple(sup_audioext))]266 267uvr5_names = [name.replace(".pth", "") 268 for name in os.listdir(weight_uvr5_root) 269 if name.endswith(".pth") or "onnx" in name]270 271 272check_for_name = lambda: sorted(names)[0] if names else ''273 274datasets=[]275for foldername in os.listdir(os.path.join(now_dir, datasets_root)):276 if "." not in foldername:277 datasets.append(os.path.join(easy_infer.find_folder_parent(".","pretrained"),"datasets",foldername))278 279def get_dataset():280 if len(datasets) > 0:281 return sorted(datasets)[0]282 else:283 return ''284 285def update_model_choices(select_value):286 model_ids = get_model_list()287 model_ids_list = list(model_ids)288 if select_value == "VR":289 return {"choices": uvr5_names, "__type__": "update"}290 elif select_value == "MDX":291 return {"choices": model_ids_list, "__type__": "update"}292 293set_bark_voice = easy_infer.get_bark_voice()294set_edge_voice = easy_infer.get_edge_voice()295 296def update_tts_methods_voice(select_value):297 #["Edge-tts", "RVG-tts", "Bark-tts"]298 if select_value == "Edge-tts":299 return {"choices": set_edge_voice, "value": "", "__type__": "update"}300 elif select_value == "Bark-tts":301 return {"choices": set_bark_voice, "value": "", "__type__": "update"}302 303 304def update_dataset_list(name):305 new_datasets = []306 for foldername in os.listdir(os.path.join(now_dir, datasets_root)):307 if "." not in foldername:308 new_datasets.append(os.path.join(easy_infer.find_folder_parent(".","pretrained"),"datasets",foldername))309 return gr.Dropdown.update(choices=new_datasets)310 311def get_indexes():312 indexes_list = [313 os.path.join(dirpath, filename)314 for dirpath, _, filenames in os.walk(index_root)315 for filename in filenames316 if filename.endswith(".index") and "trained" not in filename317 ]318 319 return indexes_list if indexes_list else ''320 321def get_fshift_presets():322 fshift_presets_list = [323 os.path.join(dirpath, filename)324 for dirpath, _, filenames in os.walk(fshift_root)325 for filename in filenames326 if filename.endswith(".txt")327 ]328 329 return fshift_presets_list if fshift_presets_list else ''330 331import soundfile as sf332 333def generate_output_path(output_folder, base_name, extension):334 # Generar un nombre único para el archivo de salida335 index = 1336 while True:337 output_path = os.path.join(output_folder, f"{base_name}_{index}.{extension}")338 if not os.path.exists(output_path):339 return output_path340 index += 1341 342def combine_and_save_audios(audio1_path, audio2_path, output_path, volume_factor_audio1, volume_factor_audio2):343 audio1, sr1 = librosa.load(audio1_path, sr=None)344 audio2, sr2 = librosa.load(audio2_path, sr=None)345 346 # Alinear las tasas de muestreo347 if sr1 != sr2:348 if sr1 > sr2:349 audio2 = librosa.resample(audio2, orig_sr=sr2, target_sr=sr1)350 else:351 audio1 = librosa.resample(audio1, orig_sr=sr1, target_sr=sr2)352 353 # Ajustar los audios para que tengan la misma longitud354 target_length = min(len(audio1), len(audio2))355 audio1 = librosa.util.fix_length(audio1, target_length)356 audio2 = librosa.util.fix_length(audio2, target_length)357 358 # Ajustar el volumen de los audios multiplicando por el factor de ganancia359 if volume_factor_audio1 != 1.0:360 audio1 *= volume_factor_audio1361 if volume_factor_audio2 != 1.0:362 audio2 *= volume_factor_audio2363 364 # Combinar los audios365 combined_audio = audio1 + audio2366 367 sf.write(output_path, combined_audio, sr1)368 369# Resto de tu código...370 371# Define función de conversión llamada por el botón372def audio_combined(audio1_path, audio2_path, volume_factor_audio1=1.0, volume_factor_audio2=1.0, reverb_enabled=False, compressor_enabled=False, noise_gate_enabled=False):373 output_folder = os.path.join(now_dir, "audio-outputs")374 os.makedirs(output_folder, exist_ok=True)375 376 # Generar nombres únicos para los archivos de salida377 base_name = "combined_audio"378 extension = "wav"379 output_path = generate_output_path(output_folder, base_name, extension)380 print(reverb_enabled)381 print(compressor_enabled)382 print(noise_gate_enabled)383 384 if reverb_enabled or compressor_enabled or noise_gate_enabled:385 # Procesa el primer audio con los efectos habilitados386 base_name = "effect_audio"387 output_path = generate_output_path(output_folder, base_name, extension)388 processed_audio_path = audioEffects.process_audio(audio2_path, output_path, reverb_enabled, compressor_enabled, noise_gate_enabled)389 base_name = "combined_audio"390 output_path = generate_output_path(output_folder, base_name, extension)391 # Combina el audio procesado con el segundo audio usando audio_combined392 combine_and_save_audios(audio1_path, processed_audio_path, output_path, volume_factor_audio1, volume_factor_audio2)393 394 return i18n("Conversion complete!"), output_path395 else:396 base_name = "combined_audio"397 output_path = generate_output_path(output_folder, base_name, extension)398 # No hay efectos habilitados, combina directamente los audios sin procesar399 combine_and_save_audios(audio1_path, audio2_path, output_path, volume_factor_audio1, volume_factor_audio2)400 401 return i18n("Conversion complete!"), output_path402 403 404 405 406def uvr(model_name, inp_root, save_root_vocal, paths, save_root_ins, agg, format0,architecture):407 infos = []408 if architecture == "VR":409 try:410 inp_root, save_root_vocal, save_root_ins = [x.strip(" ").strip('"').strip("\n").strip('"').strip(" ") for x in [inp_root, save_root_vocal, save_root_ins]]411 usable_files = [os.path.join(inp_root, file) 412 for file in os.listdir(inp_root) 413 if file.endswith(tuple(sup_audioext))] 414 415 416 pre_fun = MDXNetDereverb(15) if model_name == "onnx_dereverb_By_FoxJoy" else (_audio_pre_ if "DeEcho" not in model_name else _audio_pre_new)(417 agg=int(agg),418 model_path=os.path.join(weight_uvr5_root, model_name + ".pth"),419 device=config.device,420 is_half=config.is_half,421 )422 423 try:424 if paths != None:425 paths = [path.name for path in paths]426 else:427 paths = usable_files428 429 except:430 traceback.print_exc()431 paths = usable_files432 print(paths) 433 for path in paths:434 inp_path = os.path.join(inp_root, path)435 need_reformat, done = 1, 0436 437 try:438 info = ffmpeg.probe(inp_path, cmd="ffprobe")439 if info["streams"][0]["channels"] == 2 and info["streams"][0]["sample_rate"] == "44100":440 need_reformat = 0441 pre_fun._path_audio_(inp_path, save_root_ins, save_root_vocal, format0)442 done = 1443 except:444 traceback.print_exc()445 446 if need_reformat:447 tmp_path = f"{tmp}/{os.path.basename(RQuote(inp_path))}.reformatted.wav"448 os.system(f"ffmpeg -i {RQuote(inp_path)} -vn -acodec pcm_s16le -ac 2 -ar 44100 {RQuote(tmp_path)} -y")449 inp_path = tmp_path450 451 try:452 if not done:453 pre_fun._path_audio_(inp_path, save_root_ins, save_root_vocal, format0)454 infos.append(f"{os.path.basename(inp_path)}->Success")455 yield "\n".join(infos)456 except:457 infos.append(f"{os.path.basename(inp_path)}->{traceback.format_exc()}")458 yield "\n".join(infos)459 except:460 infos.append(traceback.format_exc())461 yield "\n".join(infos)462 finally:463 try:464 if model_name == "onnx_dereverb_By_FoxJoy":465 del pre_fun.pred.model466 del pre_fun.pred.model_467 else:468 del pre_fun.model469 470 del pre_fun471 except: traceback.print_exc()472 473 print("clean_empty_cache")474 475 if torch.cuda.is_available(): torch.cuda.empty_cache()476 477 yield "\n".join(infos)478 elif architecture == "MDX":479 try:480 infos.append(i18n("Starting audio conversion... (This might take a moment)"))481 yield "\n".join(infos)482 inp_root, save_root_vocal, save_root_ins = [x.strip(" ").strip('"').strip("\n").strip('"').strip(" ") for x in [inp_root, save_root_vocal, save_root_ins]]483 484 usable_files = [os.path.join(inp_root, file) 485 for file in os.listdir(inp_root) 486 if file.endswith(tuple(sup_audioext))] 487 try:488 if paths != None:489 paths = [path.name for path in paths]490 else:491 paths = usable_files492 493 except:494 traceback.print_exc()495 paths = usable_files496 print(paths) 497 invert=True498 denoise=True499 use_custom_parameter=True500 dim_f=3072501 dim_t=256502 n_fft=7680503 use_custom_compensation=True504 compensation=1.025505 suffix = "Vocals_custom" #@param ["Vocals", "Drums", "Bass", "Other"]{allow-input: true}506 suffix_invert = "Instrumental_custom" #@param ["Instrumental", "Drumless", "Bassless", "Instruments"]{allow-input: true}507 print_settings = True # @param{type:"boolean"}508 onnx = id_to_ptm(model_name)509 compensation = compensation if use_custom_compensation or use_custom_parameter else None510 mdx_model = prepare_mdx(onnx,use_custom_parameter, dim_f, dim_t, n_fft, compensation=compensation)511 512 513 for path in paths:514 #inp_path = os.path.join(inp_root, path)515 suffix_naming = suffix if use_custom_parameter else None516 diff_suffix_naming = suffix_invert if use_custom_parameter else None517 run_mdx(onnx, mdx_model, path, format0, diff=invert,suffix=suffix_naming,diff_suffix=diff_suffix_naming,denoise=denoise)518 519 if print_settings:520 print()521 print('[MDX-Net_Colab settings used]')522 print(f'Model used: {onnx}')523 print(f'Model MD5: {mdx.MDX.get_hash(onnx)}')524 print(f'Model parameters:')525 print(f' -dim_f: {mdx_model.dim_f}')526 print(f' -dim_t: {mdx_model.dim_t}')527 print(f' -n_fft: {mdx_model.n_fft}')528 print(f' -compensation: {mdx_model.compensation}')529 print()530 print('[Input file]')531 print('filename(s): ')532 for filename in paths:533 print(f' -{filename}')534 infos.append(f"{os.path.basename(filename)}->Success")535 yield "\n".join(infos)536 except:537 infos.append(traceback.format_exc())538 yield "\n".join(infos)539 finally:540 try:541 del mdx_model542 except: traceback.print_exc()543 544 print("clean_empty_cache")545 546 if torch.cuda.is_available(): torch.cuda.empty_cache()547 548 549 550 551 552def change_choices():553 names = [os.path.join(root, file)554 for root, _, files in os.walk(weight_root)555 for file in files556 if file.endswith((".pth", ".onnx"))]557 indexes_list = [os.path.join(root, name) for root, _, files in os.walk(index_root, topdown=False) for name in files if name.endswith(".index") and "trained" not in name]558 audio_paths = [os.path.join(audio_root, file) for file in os.listdir(os.path.join(now_dir, "audios"))]559 560 561 return (562 {"choices": sorted(names), "__type__": "update"}, 563 {"choices": sorted(indexes_list), "__type__": "update"}, 564 {"choices": sorted(audio_paths), "__type__": "update"}565 )566def change_choices2():567 names = [os.path.join(root, file)568 for root, _, files in os.walk(weight_root)569 for file in files570 if file.endswith((".pth", ".onnx"))]571 indexes_list = [os.path.join(root, name) for root, _, files in os.walk(index_root, topdown=False) for name in files if name.endswith(".index") and "trained" not in name]572 573 574 return (575 {"choices": sorted(names), "__type__": "update"}, 576 {"choices": sorted(indexes_list), "__type__": "update"}, 577 )578def change_choices3():579 580 audio_paths = [os.path.join(audio_root, file) for file in os.listdir(os.path.join(now_dir, "audios"))]581 audio_others_paths = [os.path.join(audio_others_root, file) for file in os.listdir(os.path.join(now_dir, "audio-others"))]582 583 584 return (585 {"choices": sorted(audio_others_paths), "__type__": "update"},586 {"choices": sorted(audio_paths), "__type__": "update"}587 )588 589def clean():590 return {"value": "", "__type__": "update"}591def export_onnx():592 from infer.modules.onnx.export import export_onnx as eo593 594 eo()595 596sr_dict = {597 "32k": 32000,598 "40k": 40000,599 "48k": 48000,600}601 602 603def if_done(done, p):604 while 1:605 if p.poll() is None:606 sleep(0.5)607 else:608 break609 done[0] = True610 611 612def if_done_multi(done, ps):613 while 1:614 # poll==None代表进程未结束615 # 只要有一个进程未结束都不停616 flag = 1617 for p in ps:618 if p.poll() is None:619 flag = 0620 sleep(0.5)621 break622 if flag == 1:623 break624 done[0] = True625 626def formant_enabled(627 cbox, qfrency, tmbre, frmntapply, formantpreset, formant_refresh_button628):629 if cbox:630 DoFormant = True631 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, qfrency, tmbre)632 633 # print(f"is checked? - {cbox}\ngot {DoFormant}")634 635 return (636 {"value": True, "__type__": "update"},637 {"visible": True, "__type__": "update"},638 {"visible": True, "__type__": "update"},639 {"visible": True, "__type__": "update"},640 {"visible": True, "__type__": "update"},641 {"visible": True, "__type__": "update"},642 )643 644 else:645 DoFormant = False646 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, qfrency, tmbre)647 648 # print(f"is checked? - {cbox}\ngot {DoFormant}")649 return (650 {"value": False, "__type__": "update"},651 {"visible": False, "__type__": "update"},652 {"visible": False, "__type__": "update"},653 {"visible": False, "__type__": "update"},654 {"visible": False, "__type__": "update"},655 {"visible": False, "__type__": "update"},656 {"visible": False, "__type__": "update"},657 )658 659 660def formant_apply(qfrency, tmbre):661 Quefrency = qfrency662 Timbre = tmbre663 DoFormant = True664 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, qfrency, tmbre)665 666 return (667 {"value": Quefrency, "__type__": "update"},668 {"value": Timbre, "__type__": "update"},669 )670 671def update_fshift_presets(preset, qfrency, tmbre):672 673 if preset: 674 with open(preset, 'r') as p:675 content = p.readlines()676 qfrency, tmbre = content[0].strip(), content[1]677 678 formant_apply(qfrency, tmbre)679 else:680 qfrency, tmbre = preset_apply(preset, qfrency, tmbre)681 682 return (683 {"choices": get_fshift_presets(), "__type__": "update"},684 {"value": qfrency, "__type__": "update"},685 {"value": tmbre, "__type__": "update"},686 )687 688def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):689 sr = sr_dict[sr]690 os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)691 f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")692 f.close()693 per = 3.0 if config.is_half else 3.7694 cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (695 config.python_cmd,696 trainset_dir,697 sr,698 n_p,699 now_dir,700 exp_dir,701 config.noparallel,702 per,703 )704 logger.info(cmd)705 p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir706 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读707 done = [False]708 threading.Thread(709 target=if_done,710 args=(711 done,712 p,713 ),714 ).start()715 while 1:716 with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:717 yield (f.read())718 sleep(1)719 if done[0]:720 break721 with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:722 log = f.read()723 logger.info(log)724 yield log725 726 727def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, echl, gpus_rmvpe):728 gpus = gpus.split("-")729 os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)730 f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")731 f.close()732 if if_f0:733 if f0method != "rmvpe_gpu":734 cmd = (735 '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'736 % (737 config.python_cmd,738 now_dir,739 exp_dir,740 n_p,741 f0method,742 echl,743 )744 )745 logger.info(cmd)746 p = Popen(747 cmd, shell=True, cwd=now_dir748 ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE749 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读750 done = [False]751 threading.Thread(752 target=if_done,753 args=(754 done,755 p,756 ),757 ).start()758 else:759 if gpus_rmvpe != "-":760 gpus_rmvpe = gpus_rmvpe.split("-")761 leng = len(gpus_rmvpe)762 ps = []763 for idx, n_g in enumerate(gpus_rmvpe):764 cmd = (765 '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '766 % (767 config.python_cmd,768 leng,769 idx,770 n_g,771 now_dir,772 exp_dir,773 config.is_half,774 )775 )776 logger.info(cmd)777 p = Popen(778 cmd, shell=True, cwd=now_dir779 ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir780 ps.append(p)781 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读782 done = [False]783 threading.Thread(784 target=if_done_multi, #785 args=(786 done,787 ps,788 ),789 ).start()790 else:791 cmd = (792 config.python_cmd793 + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '794 % (795 now_dir,796 exp_dir,797 )798 )799 logger.info(cmd)800 p = Popen(801 cmd, shell=True, cwd=now_dir802 ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir803 p.wait()804 done = [True]805 while 1:806 with open(807 "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"808 ) as f:809 yield (f.read())810 sleep(1)811 if done[0]:812 break813 with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:814 log = f.read()815 logger.info(log)816 yield log817 ####对不同part分别开多进程818 """819 n_part=int(sys.argv[1])820 i_part=int(sys.argv[2])821 i_gpu=sys.argv[3]822 exp_dir=sys.argv[4]823 os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)824 """825 leng = len(gpus)826 ps = []827 for idx, n_g in enumerate(gpus):828 cmd = (829 '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'830 % (831 config.python_cmd,832 config.device,833 leng,834 idx,835 n_g,836 now_dir,837 exp_dir,838 version19,839 )840 )841 logger.info(cmd)842 p = Popen(843 cmd, shell=True, cwd=now_dir844 ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir845 ps.append(p)846 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读847 done = [False]848 threading.Thread(849 target=if_done_multi,850 args=(851 done,852 ps,853 ),854 ).start()855 while 1:856 with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:857 yield (f.read())858 sleep(1)859 if done[0]:860 break861 with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:862 log = f.read()863 logger.info(log)864 yield log865 866def get_pretrained_models(path_str, f0_str, sr2):867 if_pretrained_generator_exist = os.access(868 "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK869 )870 if_pretrained_discriminator_exist = os.access(871 "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK872 )873 if not if_pretrained_generator_exist:874 logger.warn(875 "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",876 path_str,877 f0_str,878 sr2,879 )880 if not if_pretrained_discriminator_exist:881 logger.warn(882 "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",883 path_str,884 f0_str,885 sr2,886 )887 return (888 "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)889 if if_pretrained_generator_exist890 else "",891 "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)892 if if_pretrained_discriminator_exist893 else "",894 )895 896def change_sr2(sr2, if_f0_3, version19):897 path_str = "" if version19 == "v1" else "_v2"898 f0_str = "f0" if if_f0_3 else ""899 return get_pretrained_models(path_str, f0_str, sr2)900 901 902def change_version19(sr2, if_f0_3, version19):903 path_str = "" if version19 == "v1" else "_v2"904 if sr2 == "32k" and version19 == "v1":905 sr2 = "40k"906 to_return_sr2 = (907 {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}908 if version19 == "v1"909 else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}910 )911 f0_str = "f0" if if_f0_3 else ""912 return (913 *get_pretrained_models(path_str, f0_str, sr2),914 to_return_sr2,915 )916 917 918def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15919 path_str = "" if version19 == "v1" else "_v2"920 return (921 {"visible": if_f0_3, "__type__": "update"},922 *get_pretrained_models(path_str, "f0", sr2),923 )924 925 926global log_interval927 928def set_log_interval(exp_dir, batch_size12):929 log_interval = 1930 folder_path = os.path.join(exp_dir, "1_16k_wavs")931 932 if os.path.isdir(folder_path):933 wav_files_num = len(glob1(folder_path,"*.wav"))934 935 if wav_files_num > 0:936 log_interval = math.ceil(wav_files_num / batch_size12)937 if log_interval > 1:938 log_interval += 1939 940 return log_interval941 942global PID, PROCESS943 944def click_train(945 exp_dir1,946 sr2,947 if_f0_3,948 spk_id5,949 save_epoch10,950 total_epoch11,951 batch_size12,952 if_save_latest13,953 pretrained_G14,954 pretrained_D15,955 gpus16,956 if_cache_gpu17,957 if_save_every_weights18,958 version19,959):960 CSVutil("csvdb/stop.csv", "w+", "formanting", False)961 # 生成filelist962 exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)963 os.makedirs(exp_dir, exist_ok=True)964 gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)965 feature_dir = (966 "%s/3_feature256" % (exp_dir)967 if version19 == "v1"968 else "%s/3_feature768" % (exp_dir)969 )970 if if_f0_3:971 f0_dir = "%s/2a_f0" % (exp_dir)972 f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)973 names = (974 set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])975 & set([name.split(".")[0] for name in os.listdir(feature_dir)])976 & set([name.split(".")[0] for name in os.listdir(f0_dir)])977 & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])978 )979 else:980 names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(981 [name.split(".")[0] for name in os.listdir(feature_dir)]982 )983 opt = []984 for name in names:985 if if_f0_3:986 opt.append(987 "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"988 % (989 gt_wavs_dir.replace("\\", "\\\\"),990 name,991 feature_dir.replace("\\", "\\\\"),992 name,993 f0_dir.replace("\\", "\\\\"),994 name,995 f0nsf_dir.replace("\\", "\\\\"),996 name,997 spk_id5,998 )999 )1000 else:1001 opt.append(1002 "%s/%s.wav|%s/%s.npy|%s"1003 % (1004 gt_wavs_dir.replace("\\", "\\\\"),1005 name,1006 feature_dir.replace("\\", "\\\\"),1007 name,1008 spk_id5,1009 )1010 )1011 fea_dim = 256 if version19 == "v1" else 7681012 if if_f0_3:1013 for _ in range(2):1014 opt.append(1015 "%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"1016 % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)1017 )1018 else:1019 for _ in range(2):1020 opt.append(1021 "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"1022 % (now_dir, sr2, now_dir, fea_dim, spk_id5)1023 )1024 shuffle(opt)1025 with open("%s/filelist.txt" % exp_dir, "w") as f:1026 f.write("\n".join(opt))1027 logger.debug("Write filelist done")1028 # 生成config#无需生成config1029 # 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"1030 logger.info("Use gpus: %s", str(gpus16))1031 if pretrained_G14 == "":1032 logger.info("No pretrained Generator")1033 if pretrained_D15 == "":1034 logger.info("No pretrained Discriminator")1035 if version19 == "v1" or sr2 == "40k":1036 config_path = "v1/%s.json" % sr21037 else:1038 config_path = "v2/%s.json" % sr21039 config_save_path = os.path.join(exp_dir, "config.json")1040 if not pathlib.Path(config_save_path).exists():1041 with open(config_save_path, "w", encoding="utf-8") as f:1042 json.dump(1043 config.json_config[config_path],1044 f,1045 ensure_ascii=False,1046 indent=4,1047 sort_keys=True,1048 )1049 f.write("\n")1050 if gpus16:1051 cmd = (1052 '"%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'1053 % (1054 config.python_cmd,1055 exp_dir1,1056 sr2,1057 1 if if_f0_3 else 0,1058 batch_size12,1059 gpus16,1060 total_epoch11,1061 save_epoch10,1062 "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",1063 "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",1064 1 if if_save_latest13 == True else 0,1065 1 if if_cache_gpu17 == True else 0,1066 1 if if_save_every_weights18 == True else 0,1067 version19,1068 )1069 )1070 else:1071 cmd = (1072 '"%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'1073 % (1074 config.python_cmd,1075 exp_dir1,1076 sr2,1077 1 if if_f0_3 else 0,1078 batch_size12,1079 total_epoch11,1080 save_epoch10,1081 "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",1082 "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",1083 1 if if_save_latest13 == True else 0,1084 1 if if_cache_gpu17 == True else 0,1085 1 if if_save_every_weights18 == True else 0,1086 version19,1087 )1088 )1089 logger.info(cmd)1090 global p1091 p = Popen(cmd, shell=True, cwd=now_dir)1092 global PID1093 PID = p.pid1094 1095 p.wait()1096 1097 return i18n("Training is done, check train.log"), {"visible": False, "__type__": "update"}, {"visible": True, "__type__": "update"}1098 1099 1100def train_index(exp_dir1, version19):1101 # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)1102 exp_dir = "logs/%s" % (exp_dir1)1103 os.makedirs(exp_dir, exist_ok=True)1104 feature_dir = (1105 "%s/3_feature256" % (exp_dir)1106 if version19 == "v1"1107 else "%s/3_feature768" % (exp_dir)1108 )1109 if not os.path.exists(feature_dir):1110 return "请先进行特征提取!"1111 listdir_res = list(os.listdir(feature_dir))1112 if len(listdir_res) == 0:1113 return "请先进行特征提取!"1114 infos = []1115 npys = []1116 for name in sorted(listdir_res):1117 phone = np.load("%s/%s" % (feature_dir, name))1118 npys.append(phone)1119 big_npy = np.concatenate(npys, 0)1120 big_npy_idx = np.arange(big_npy.shape[0])1121 np.random.shuffle(big_npy_idx)1122 big_npy = big_npy[big_npy_idx]1123 if big_npy.shape[0] > 2e5:1124 infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])1125 yield "\n".join(infos)1126 try:1127 big_npy = (1128 MiniBatchKMeans(1129 n_clusters=10000,1130 verbose=True,1131 batch_size=256 * config.n_cpu,1132 compute_labels=False,1133 init="random",1134 )1135 .fit(big_npy)1136 .cluster_centers_1137 )1138 except:1139 info = traceback.format_exc()1140 logger.info(info)1141 infos.append(info)1142 yield "\n".join(infos)1143 1144 np.save("%s/total_fea.npy" % exp_dir, big_npy)1145 n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)1146 infos.append("%s,%s" % (big_npy.shape, n_ivf))1147 yield "\n".join(infos)1148 index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)1149 # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)1150 infos.append("training")1151 yield "\n".join(infos)1152 index_ivf = faiss.extract_index_ivf(index) #1153 index_ivf.nprobe = 11154 index.train(big_npy)1155 faiss.write_index(1156 index,1157 "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"1158 % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),1159 )1160 1161 infos.append("adding")1162 yield "\n".join(infos)1163 batch_size_add = 81921164 for i in range(0, big_npy.shape[0], batch_size_add):1165 index.add(big_npy[i : i + batch_size_add])1166 faiss.write_index(1167 index,1168 "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"1169 % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),1170 )1171 infos.append(1172 "Successful Index Construction,added_IVF%s_Flat_nprobe_%s_%s_%s.index"1173 % (n_ivf, index_ivf.nprobe, exp_dir1, version19)1174 )1175 # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))1176 # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))1177 yield "\n".join(infos)1178 1179def change_info_(ckpt_path):1180 if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):1181 return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}1182 try:1183 with open(1184 ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"1185 ) as f:1186 info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])1187 sr, f0 = info["sample_rate"], info["if_f0"]1188 version = "v2" if ("version" in info and info["version"] == "v2") else "v1"1189 return sr, str(f0), version1190 except:1191 traceback.print_exc()1192 return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}1193 1194F0GPUVisible = config.dml == False1195 1196 1197def change_f0_method(f0method8):1198 if f0method8 == "rmvpe_gpu":1199 visible = F0GPUVisible1200 else: