Krish778/AI_singer
0
1import gpu_check2import os, sys3os.system("pip install pyworld") # ==0.3.34 5now_dir = os.getcwd()6sys.path.append(now_dir)7os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'8os.environ["OPENBLAS_NUM_THREADS"] = "1"9os.environ["no_proxy"] = "localhost, 127.0.0.1, ::1"10 11# Download models12shell_script = './tools/dlmodels.sh'13os.system(f'chmod +x {shell_script}')14os.system('apt install git-lfs')15os.system('git lfs install')16os.system('apt-get -y install aria2')17os.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')18try:19 return_code = os.system(shell_script)20 if return_code == 0:21 print("Shell script executed successfully.")22 else:23 print(f"Shell script failed with return code {return_code}")24except Exception as e:25 print(f"An error occurred: {e}")26 27 28import logging29import shutil30import threading31import lib.globals.globals as rvc_globals32from LazyImport import lazyload33import mdx34from mdx_processing_script import get_model_list,id_to_ptm,prepare_mdx,run_mdx35math = lazyload('math')36import traceback37import warnings38tensorlowest = lazyload('tensorlowest')39from random import shuffle40from subprocess import Popen41from time import sleep42import json43import pathlib44 45import fairseq46logging.getLogger("faiss").setLevel(logging.WARNING)47import faiss48gr = lazyload("gradio")49np = lazyload("numpy")50torch = lazyload('torch')51re = lazyload('regex')52SF = lazyload("soundfile")53SFWrite = SF.write54from dotenv import load_dotenv55from sklearn.cluster import MiniBatchKMeans56import datetime57 58 59from glob import glob160import signal61from signal import SIGTERM62import librosa63 64from configs.config import Config65from i18n import I18nAuto66from infer.lib.train.process_ckpt import (67 change_info,68 extract_small_model,69 merge,70 show_info,71)72#from infer.modules.uvr5.modules import uvr73from infer.modules.vc.modules import VC74from infer.modules.vc.utils import *75from infer.modules.vc.pipeline import Pipeline76import lib.globals.globals as rvc_globals77math = lazyload('math')78ffmpeg = lazyload('ffmpeg')79import nltk80nltk.download('punkt', quiet=True)81from nltk.tokenize import sent_tokenize82from bark import SAMPLE_RATE83 84import easy_infer85import audioEffects86from infer.lib.csvutil import CSVutil87 88from lib.infer_pack.models import (89 SynthesizerTrnMs256NSFsid,90 SynthesizerTrnMs256NSFsid_nono,91 SynthesizerTrnMs768NSFsid,92 SynthesizerTrnMs768NSFsid_nono,93)94from lib.infer_pack.models_onnx import SynthesizerTrnMsNSFsidM95from infer_uvr5 import _audio_pre_, _audio_pre_new96from MDXNet import MDXNetDereverb97from infer.lib.audio import load_audio98 99 100from sklearn.cluster import MiniBatchKMeans101 102import time103import csv104 105from shlex import quote as SQuote106 107 108 109 110RQuote = lambda val: SQuote(str(val))111 112tmp = os.path.join(now_dir, "TEMP")113runtime_dir = os.path.join(now_dir, "runtime/Lib/site-packages")114directories = ['logs', 'audios', 'datasets', 'weights', 'audio-others' , 'audio-outputs']115 116shutil.rmtree(tmp, ignore_errors=True)117shutil.rmtree("%s/runtime/Lib/site-packages/infer_pack" % (now_dir), ignore_errors=True)118shutil.rmtree("%s/runtime/Lib/site-packages/uvr5_pack" % (now_dir), ignore_errors=True)119 120os.makedirs(tmp, exist_ok=True)121for folder in directories:122 os.makedirs(os.path.join(now_dir, folder), exist_ok=True)123 124 125os.makedirs(tmp, exist_ok=True)126os.makedirs(os.path.join(now_dir, "logs"), exist_ok=True)127os.makedirs(os.path.join(now_dir, "assets/weights"), exist_ok=True)128os.environ["TEMP"] = tmp129warnings.filterwarnings("ignore")130torch.manual_seed(114514)131logging.getLogger("numba").setLevel(logging.WARNING)132 133logger = logging.getLogger(__name__)134 135 136if not os.path.isdir("csvdb/"):137 os.makedirs("csvdb")138 frmnt, stp = open("csvdb/formanting.csv", "w"), open("csvdb/stop.csv", "w")139 frmnt.close()140 stp.close()141 142global DoFormant, Quefrency, Timbre143 144try:145 DoFormant, Quefrency, Timbre = CSVutil("csvdb/formanting.csv", "r", "formanting")146 DoFormant = (147 lambda DoFormant: True148 if DoFormant.lower() == "true"149 else (False if DoFormant.lower() == "false" else DoFormant)150 )(DoFormant)151except (ValueError, TypeError, IndexError):152 DoFormant, Quefrency, Timbre = False, 1.0, 1.0153 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, Quefrency, Timbre)154 155load_dotenv()156config = Config()157vc = VC(config)158 159if config.dml == True:160 161 def forward_dml(ctx, x, scale):162 ctx.scale = scale163 res = x.clone().detach()164 return res165 166 fairseq.modules.grad_multiply.GradMultiply.forward = forward_dml167 168i18n = I18nAuto()169i18n.print()170# 判断是否有能用来训练和加速推理的N卡171ngpu = torch.cuda.device_count()172gpu_infos = []173mem = []174if_gpu_ok = False175 176isinterrupted = 0177 178 179if torch.cuda.is_available() or ngpu != 0:180 for i in range(ngpu):181 gpu_name = torch.cuda.get_device_name(i)182 if any(183 value in gpu_name.upper()184 for value in [185 "10",186 "16",187 "20",188 "30",189 "40",190 "A2",191 "A3",192 "A4",193 "P4",194 "A50",195 "500",196 "A60",197 "70",198 "80",199 "90",200 "M4",201 "T4",202 "TITAN",203 ]204 ):205 # A10#A100#V100#A40#P40#M40#K80#A4500206 if_gpu_ok = True # 至少有一张能用的N卡207 gpu_infos.append("%s\t%s" % (i, gpu_name))208 mem.append(209 int(210 torch.cuda.get_device_properties(i).total_memory211 / 1024212 / 1024213 / 1024214 + 0.4215 )216 )217if if_gpu_ok and len(gpu_infos) > 0:218 gpu_info = "\n".join(gpu_infos)219 default_batch_size = min(mem) // 2220else:221 gpu_info = "Unfortunately, there is no compatible GPU available to support your training."222 default_batch_size = 1223gpus = "-".join([i[0] for i in gpu_infos])224 225class ToolButton(gr.Button, gr.components.FormComponent):226 """Small button with single emoji as text, fits inside gradio forms"""227 228 def __init__(self, **kwargs):229 super().__init__(variant="tool", **kwargs)230 231 def get_block_name(self):232 return "button"233 234 235hubert_model = None236weight_root = os.getenv("weight_root")237weight_uvr5_root = os.getenv("weight_uvr5_root")238index_root = os.getenv("index_root")239datasets_root = "datasets"240fshift_root = "formantshiftcfg"241audio_root = "audios"242audio_others_root = "audio-others"243 244sup_audioext = {'wav', 'mp3', 'flac', 'ogg', 'opus',245 'm4a', 'mp4', 'aac', 'alac', 'wma',246 'aiff', 'webm', 'ac3'}247 248names = [os.path.join(root, file)249 for root, _, files in os.walk(weight_root)250 for file in files251 if file.endswith((".pth", ".onnx"))]252 253indexes_list = [os.path.join(root, name)254 for root, _, files in os.walk(index_root, topdown=False) 255 for name in files 256 if name.endswith(".index") and "trained" not in name]257 258audio_paths = [os.path.join(root, name)259 for root, _, files in os.walk(audio_root, topdown=False) 260 for name in files261 if name.endswith(tuple(sup_audioext))]262 263audio_others_paths = [os.path.join(root, name)264 for root, _, files in os.walk(audio_others_root, topdown=False) 265 for name in files266 if name.endswith(tuple(sup_audioext))]267 268uvr5_names = [name.replace(".pth", "") 269 for name in os.listdir(weight_uvr5_root) 270 if name.endswith(".pth") or "onnx" in name]271 272 273check_for_name = lambda: sorted(names)[0] if names else ''274 275datasets=[]276for foldername in os.listdir(os.path.join(now_dir, datasets_root)):277 if "." not in foldername:278 datasets.append(os.path.join(easy_infer.find_folder_parent(".","pretrained"),"datasets",foldername))279 280def get_dataset():281 if len(datasets) > 0:282 return sorted(datasets)[0]283 else:284 return ''285 286def update_model_choices(select_value):287 model_ids = get_model_list()288 model_ids_list = list(model_ids)289 if select_value == "VR":290 return {"choices": uvr5_names, "__type__": "update"}291 elif select_value == "MDX":292 return {"choices": model_ids_list, "__type__": "update"}293 294set_bark_voice = easy_infer.get_bark_voice()295set_edge_voice = easy_infer.get_edge_voice()296 297def update_tts_methods_voice(select_value):298 #["Edge-tts", "RVG-tts", "Bark-tts"]299 if select_value == "Edge-tts":300 return {"choices": set_edge_voice, "value": "", "__type__": "update"}301 elif select_value == "Bark-tts":302 return {"choices": set_bark_voice, "value": "", "__type__": "update"}303 304 305def update_dataset_list(name):306 new_datasets = []307 for foldername in os.listdir(os.path.join(now_dir, datasets_root)):308 if "." not in foldername:309 new_datasets.append(os.path.join(easy_infer.find_folder_parent(".","pretrained"),"datasets",foldername))310 return gr.Dropdown.update(choices=new_datasets)311 312def get_indexes():313 indexes_list = [314 os.path.join(dirpath, filename)315 for dirpath, _, filenames in os.walk(index_root)316 for filename in filenames317 if filename.endswith(".index") and "trained" not in filename318 ]319 320 return indexes_list if indexes_list else ''321 322def get_fshift_presets():323 fshift_presets_list = [324 os.path.join(dirpath, filename)325 for dirpath, _, filenames in os.walk(fshift_root)326 for filename in filenames327 if filename.endswith(".txt")328 ]329 330 return fshift_presets_list if fshift_presets_list else ''331 332import soundfile as sf333 334def generate_output_path(output_folder, base_name, extension):335 # Generar un nombre único para el archivo de salida336 index = 1337 while True:338 output_path = os.path.join(output_folder, f"{base_name}_{index}.{extension}")339 if not os.path.exists(output_path):340 return output_path341 index += 1342 343def combine_and_save_audios(audio1_path, audio2_path, output_path, volume_factor_audio1, volume_factor_audio2):344 audio1, sr1 = librosa.load(audio1_path, sr=None)345 audio2, sr2 = librosa.load(audio2_path, sr=None)346 347 # Alinear las tasas de muestreo348 if sr1 != sr2:349 if sr1 > sr2:350 audio2 = librosa.resample(audio2, orig_sr=sr2, target_sr=sr1)351 else:352 audio1 = librosa.resample(audio1, orig_sr=sr1, target_sr=sr2)353 354 # Ajustar los audios para que tengan la misma longitud355 target_length = min(len(audio1), len(audio2))356 audio1 = librosa.util.fix_length(audio1, target_length)357 audio2 = librosa.util.fix_length(audio2, target_length)358 359 # Ajustar el volumen de los audios multiplicando por el factor de ganancia360 if volume_factor_audio1 != 1.0:361 audio1 *= volume_factor_audio1362 if volume_factor_audio2 != 1.0:363 audio2 *= volume_factor_audio2364 365 # Combinar los audios366 combined_audio = audio1 + audio2367 368 sf.write(output_path, combined_audio, sr1)369 370# Resto de tu código...371 372# Define función de conversión llamada por el botón373def 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):374 output_folder = os.path.join(now_dir, "audio-outputs")375 os.makedirs(output_folder, exist_ok=True)376 377 # Generar nombres únicos para los archivos de salida378 base_name = "combined_audio"379 extension = "wav"380 output_path = generate_output_path(output_folder, base_name, extension)381 print(reverb_enabled)382 print(compressor_enabled)383 print(noise_gate_enabled)384 385 if reverb_enabled or compressor_enabled or noise_gate_enabled:386 # Procesa el primer audio con los efectos habilitados387 base_name = "effect_audio"388 output_path = generate_output_path(output_folder, base_name, extension)389 processed_audio_path = audioEffects.process_audio(audio2_path, output_path, reverb_enabled, compressor_enabled, noise_gate_enabled)390 base_name = "combined_audio"391 output_path = generate_output_path(output_folder, base_name, extension)392 # Combina el audio procesado con el segundo audio usando audio_combined393 combine_and_save_audios(audio1_path, processed_audio_path, output_path, volume_factor_audio1, volume_factor_audio2)394 395 return i18n("Conversion complete!"), output_path396 else:397 base_name = "combined_audio"398 output_path = generate_output_path(output_folder, base_name, extension)399 # No hay efectos habilitados, combina directamente los audios sin procesar400 combine_and_save_audios(audio1_path, audio2_path, output_path, volume_factor_audio1, volume_factor_audio2)401 402 return i18n("Conversion complete!"), output_path403 404 405 406 407def uvr(model_name, inp_root, save_root_vocal, paths, save_root_ins, agg, format0,architecture):408 infos = []409 if architecture == "VR":410 try:411 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]]412 usable_files = [os.path.join(inp_root, file) 413 for file in os.listdir(inp_root) 414 if file.endswith(tuple(sup_audioext))] 415 416 417 pre_fun = MDXNetDereverb(15) if model_name == "onnx_dereverb_By_FoxJoy" else (_audio_pre_ if "DeEcho" not in model_name else _audio_pre_new)(418 agg=int(agg),419 model_path=os.path.join(weight_uvr5_root, model_name + ".pth"),420 device=config.device,421 is_half=config.is_half,422 )423 424 try:425 if paths != None:426 paths = [path.name for path in paths]427 else:428 paths = usable_files429 430 except:431 traceback.print_exc()432 paths = usable_files433 print(paths) 434 for path in paths:435 inp_path = os.path.join(inp_root, path)436 need_reformat, done = 1, 0437 438 try:439 info = ffmpeg.probe(inp_path, cmd="ffprobe")440 if info["streams"][0]["channels"] == 2 and info["streams"][0]["sample_rate"] == "44100":441 need_reformat = 0442 pre_fun._path_audio_(inp_path, save_root_ins, save_root_vocal, format0)443 done = 1444 except:445 traceback.print_exc()446 447 if need_reformat:448 tmp_path = f"{tmp}/{os.path.basename(RQuote(inp_path))}.reformatted.wav"449 os.system(f"ffmpeg -i {RQuote(inp_path)} -vn -acodec pcm_s16le -ac 2 -ar 44100 {RQuote(tmp_path)} -y")450 inp_path = tmp_path451 452 try:453 if not done:454 pre_fun._path_audio_(inp_path, save_root_ins, save_root_vocal, format0)455 infos.append(f"{os.path.basename(inp_path)}->Success")456 yield "\n".join(infos)457 except:458 infos.append(f"{os.path.basename(inp_path)}->{traceback.format_exc()}")459 yield "\n".join(infos)460 except:461 infos.append(traceback.format_exc())462 yield "\n".join(infos)463 finally:464 try:465 if model_name == "onnx_dereverb_By_FoxJoy":466 del pre_fun.pred.model467 del pre_fun.pred.model_468 else:469 del pre_fun.model470 471 del pre_fun472 except: traceback.print_exc()473 474 print("clean_empty_cache")475 476 if torch.cuda.is_available(): torch.cuda.empty_cache()477 478 yield "\n".join(infos)479 elif architecture == "MDX":480 try:481 infos.append(i18n("Starting audio conversion... (This might take a moment)"))482 yield "\n".join(infos)483 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]]484 485 usable_files = [os.path.join(inp_root, file) 486 for file in os.listdir(inp_root) 487 if file.endswith(tuple(sup_audioext))] 488 try:489 if paths != None:490 paths = [path.name for path in paths]491 else:492 paths = usable_files493 494 except:495 traceback.print_exc()496 paths = usable_files497 print(paths) 498 invert=True499 denoise=True500 use_custom_parameter=True501 dim_f=3072502 dim_t=256503 n_fft=7680504 use_custom_compensation=True505 compensation=1.025506 suffix = "Vocals_custom" #@param ["Vocals", "Drums", "Bass", "Other"]{allow-input: true}507 suffix_invert = "Instrumental_custom" #@param ["Instrumental", "Drumless", "Bassless", "Instruments"]{allow-input: true}508 print_settings = True # @param{type:"boolean"}509 onnx = id_to_ptm(model_name)510 compensation = compensation if use_custom_compensation or use_custom_parameter else None511 mdx_model = prepare_mdx(onnx,use_custom_parameter, dim_f, dim_t, n_fft, compensation=compensation)512 513 514 for path in paths:515 #inp_path = os.path.join(inp_root, path)516 suffix_naming = suffix if use_custom_parameter else None517 diff_suffix_naming = suffix_invert if use_custom_parameter else None518 run_mdx(onnx, mdx_model, path, format0, diff=invert,suffix=suffix_naming,diff_suffix=diff_suffix_naming,denoise=denoise)519 520 if print_settings:521 print()522 print('[MDX-Net_Colab settings used]')523 print(f'Model used: {onnx}')524 print(f'Model MD5: {mdx.MDX.get_hash(onnx)}')525 print(f'Model parameters:')526 print(f' -dim_f: {mdx_model.dim_f}')527 print(f' -dim_t: {mdx_model.dim_t}')528 print(f' -n_fft: {mdx_model.n_fft}')529 print(f' -compensation: {mdx_model.compensation}')530 print()531 print('[Input file]')532 print('filename(s): ')533 for filename in paths:534 print(f' -{filename}')535 infos.append(f"{os.path.basename(filename)}->Success")536 yield "\n".join(infos)537 except:538 infos.append(traceback.format_exc())539 yield "\n".join(infos)540 finally:541 try:542 del mdx_model543 except: traceback.print_exc()544 545 print("clean_empty_cache")546 547 if torch.cuda.is_available(): torch.cuda.empty_cache()548 549 550 551 552 553def change_choices():554 names = [os.path.join(root, file)555 for root, _, files in os.walk(weight_root)556 for file in files557 if file.endswith((".pth", ".onnx"))]558 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]559 audio_paths = [os.path.join(audio_root, file) for file in os.listdir(os.path.join(now_dir, "audios"))]560 561 562 return (563 {"choices": sorted(names), "__type__": "update"}, 564 {"choices": sorted(indexes_list), "__type__": "update"}, 565 {"choices": sorted(audio_paths), "__type__": "update"}566 )567def change_choices2():568 names = [os.path.join(root, file)569 for root, _, files in os.walk(weight_root)570 for file in files571 if file.endswith((".pth", ".onnx"))]572 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]573 574 575 return (576 {"choices": sorted(names), "__type__": "update"}, 577 {"choices": sorted(indexes_list), "__type__": "update"}, 578 )579def change_choices3():580 581 audio_paths = [os.path.join(audio_root, file) for file in os.listdir(os.path.join(now_dir, "audios"))]582 audio_others_paths = [os.path.join(audio_others_root, file) for file in os.listdir(os.path.join(now_dir, "audio-others"))]583 584 585 return (586 {"choices": sorted(audio_others_paths), "__type__": "update"},587 {"choices": sorted(audio_paths), "__type__": "update"}588 )589 590def clean():591 return {"value": "", "__type__": "update"}592def export_onnx():593 from infer.modules.onnx.export import export_onnx as eo594 595 eo()596 597sr_dict = {598 "32k": 32000,599 "40k": 40000,600 "48k": 48000,601}602 603 604def if_done(done, p):605 while 1:606 if p.poll() is None:607 sleep(0.5)608 else:609 break610 done[0] = True611 612 613def if_done_multi(done, ps):614 while 1:615 # poll==None代表进程未结束616 # 只要有一个进程未结束都不停617 flag = 1618 for p in ps:619 if p.poll() is None:620 flag = 0621 sleep(0.5)622 break623 if flag == 1:624 break625 done[0] = True626 627def formant_enabled(628 cbox, qfrency, tmbre, frmntapply, formantpreset, formant_refresh_button629):630 if cbox:631 DoFormant = True632 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, qfrency, tmbre)633 634 # print(f"is checked? - {cbox}\ngot {DoFormant}")635 636 return (637 {"value": True, "__type__": "update"},638 {"visible": True, "__type__": "update"},639 {"visible": True, "__type__": "update"},640 {"visible": True, "__type__": "update"},641 {"visible": True, "__type__": "update"},642 {"visible": True, "__type__": "update"},643 )644 645 else:646 DoFormant = False647 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, qfrency, tmbre)648 649 # print(f"is checked? - {cbox}\ngot {DoFormant}")650 return (651 {"value": 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 {"visible": False, "__type__": "update"},658 )659 660 661def formant_apply(qfrency, tmbre):662 Quefrency = qfrency663 Timbre = tmbre664 DoFormant = True665 CSVutil("csvdb/formanting.csv", "w+", "formanting", DoFormant, qfrency, tmbre)666 667 return (668 {"value": Quefrency, "__type__": "update"},669 {"value": Timbre, "__type__": "update"},670 )671 672def update_fshift_presets(preset, qfrency, tmbre):673 674 if preset: 675 with open(preset, 'r') as p:676 content = p.readlines()677 qfrency, tmbre = content[0].strip(), content[1]678 679 formant_apply(qfrency, tmbre)680 else:681 qfrency, tmbre = preset_apply(preset, qfrency, tmbre)682 683 return (684 {"choices": get_fshift_presets(), "__type__": "update"},685 {"value": qfrency, "__type__": "update"},686 {"value": tmbre, "__type__": "update"},687 )688 689def preprocess_dataset(trainset_dir, exp_dir, sr, n_p):690 sr = sr_dict[sr]691 os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)692 f = open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "w")693 f.close()694 per = 3.0 if config.is_half else 3.7695 cmd = '"%s" infer/modules/train/preprocess.py "%s" %s %s "%s/logs/%s" %s %.1f' % (696 config.python_cmd,697 trainset_dir,698 sr,699 n_p,700 now_dir,701 exp_dir,702 config.noparallel,703 per,704 )705 logger.info(cmd)706 p = Popen(cmd, shell=True) # , stdin=PIPE, stdout=PIPE,stderr=PIPE,cwd=now_dir707 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读708 done = [False]709 threading.Thread(710 target=if_done,711 args=(712 done,713 p,714 ),715 ).start()716 while 1:717 with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:718 yield (f.read())719 sleep(1)720 if done[0]:721 break722 with open("%s/logs/%s/preprocess.log" % (now_dir, exp_dir), "r") as f:723 log = f.read()724 logger.info(log)725 yield log726 727 728def extract_f0_feature(gpus, n_p, f0method, if_f0, exp_dir, version19, echl, gpus_rmvpe):729 gpus = gpus.split("-")730 os.makedirs("%s/logs/%s" % (now_dir, exp_dir), exist_ok=True)731 f = open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "w")732 f.close()733 if if_f0:734 if f0method != "rmvpe_gpu":735 cmd = (736 '"%s" infer/modules/train/extract/extract_f0_print.py "%s/logs/%s" %s %s'737 % (738 config.python_cmd,739 now_dir,740 exp_dir,741 n_p,742 f0method,743 echl,744 )745 )746 logger.info(cmd)747 p = Popen(748 cmd, shell=True, cwd=now_dir749 ) # , stdin=PIPE, stdout=PIPE,stderr=PIPE750 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读751 done = [False]752 threading.Thread(753 target=if_done,754 args=(755 done,756 p,757 ),758 ).start()759 else:760 if gpus_rmvpe != "-":761 gpus_rmvpe = gpus_rmvpe.split("-")762 leng = len(gpus_rmvpe)763 ps = []764 for idx, n_g in enumerate(gpus_rmvpe):765 cmd = (766 '"%s" infer/modules/train/extract/extract_f0_rmvpe.py %s %s %s "%s/logs/%s" %s '767 % (768 config.python_cmd,769 leng,770 idx,771 n_g,772 now_dir,773 exp_dir,774 config.is_half,775 )776 )777 logger.info(cmd)778 p = Popen(779 cmd, shell=True, cwd=now_dir780 ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir781 ps.append(p)782 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读783 done = [False]784 threading.Thread(785 target=if_done_multi, #786 args=(787 done,788 ps,789 ),790 ).start()791 else:792 cmd = (793 config.python_cmd794 + ' infer/modules/train/extract/extract_f0_rmvpe_dml.py "%s/logs/%s" '795 % (796 now_dir,797 exp_dir,798 )799 )800 logger.info(cmd)801 p = Popen(802 cmd, shell=True, cwd=now_dir803 ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir804 p.wait()805 done = [True]806 while 1:807 with open(808 "%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r"809 ) as f:810 yield (f.read())811 sleep(1)812 if done[0]:813 break814 with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:815 log = f.read()816 logger.info(log)817 yield log818 ####对不同part分别开多进程819 """820 n_part=int(sys.argv[1])821 i_part=int(sys.argv[2])822 i_gpu=sys.argv[3]823 exp_dir=sys.argv[4]824 os.environ["CUDA_VISIBLE_DEVICES"]=str(i_gpu)825 """826 leng = len(gpus)827 ps = []828 for idx, n_g in enumerate(gpus):829 cmd = (830 '"%s" infer/modules/train/extract_feature_print.py %s %s %s %s "%s/logs/%s" %s'831 % (832 config.python_cmd,833 config.device,834 leng,835 idx,836 n_g,837 now_dir,838 exp_dir,839 version19,840 )841 )842 logger.info(cmd)843 p = Popen(844 cmd, shell=True, cwd=now_dir845 ) # , shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, cwd=now_dir846 ps.append(p)847 ###煞笔gr, popen read都非得全跑完了再一次性读取, 不用gr就正常读一句输出一句;只能额外弄出一个文本流定时读848 done = [False]849 threading.Thread(850 target=if_done_multi,851 args=(852 done,853 ps,854 ),855 ).start()856 while 1:857 with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:858 yield (f.read())859 sleep(1)860 if done[0]:861 break862 with open("%s/logs/%s/extract_f0_feature.log" % (now_dir, exp_dir), "r") as f:863 log = f.read()864 logger.info(log)865 yield log866 867def get_pretrained_models(path_str, f0_str, sr2):868 if_pretrained_generator_exist = os.access(869 "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2), os.F_OK870 )871 if_pretrained_discriminator_exist = os.access(872 "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2), os.F_OK873 )874 if not if_pretrained_generator_exist:875 logger.warn(876 "assets/pretrained%s/%sG%s.pth not exist, will not use pretrained model",877 path_str,878 f0_str,879 sr2,880 )881 if not if_pretrained_discriminator_exist:882 logger.warn(883 "assets/pretrained%s/%sD%s.pth not exist, will not use pretrained model",884 path_str,885 f0_str,886 sr2,887 )888 return (889 "assets/pretrained%s/%sG%s.pth" % (path_str, f0_str, sr2)890 if if_pretrained_generator_exist891 else "",892 "assets/pretrained%s/%sD%s.pth" % (path_str, f0_str, sr2)893 if if_pretrained_discriminator_exist894 else "",895 )896 897def change_sr2(sr2, if_f0_3, version19):898 path_str = "" if version19 == "v1" else "_v2"899 f0_str = "f0" if if_f0_3 else ""900 return get_pretrained_models(path_str, f0_str, sr2)901 902 903def change_version19(sr2, if_f0_3, version19):904 path_str = "" if version19 == "v1" else "_v2"905 if sr2 == "32k" and version19 == "v1":906 sr2 = "40k"907 to_return_sr2 = (908 {"choices": ["40k", "48k"], "__type__": "update", "value": sr2}909 if version19 == "v1"910 else {"choices": ["40k", "48k", "32k"], "__type__": "update", "value": sr2}911 )912 f0_str = "f0" if if_f0_3 else ""913 return (914 *get_pretrained_models(path_str, f0_str, sr2),915 to_return_sr2,916 )917 918 919def change_f0(if_f0_3, sr2, version19): # f0method8,pretrained_G14,pretrained_D15920 path_str = "" if version19 == "v1" else "_v2"921 return (922 {"visible": if_f0_3, "__type__": "update"},923 *get_pretrained_models(path_str, "f0", sr2),924 )925 926 927global log_interval928 929def set_log_interval(exp_dir, batch_size12):930 log_interval = 1931 folder_path = os.path.join(exp_dir, "1_16k_wavs")932 933 if os.path.isdir(folder_path):934 wav_files_num = len(glob1(folder_path,"*.wav"))935 936 if wav_files_num > 0:937 log_interval = math.ceil(wav_files_num / batch_size12)938 if log_interval > 1:939 log_interval += 1940 941 return log_interval942 943global PID, PROCESS944 945def click_train(946 exp_dir1,947 sr2,948 if_f0_3,949 spk_id5,950 save_epoch10,951 total_epoch11,952 batch_size12,953 if_save_latest13,954 pretrained_G14,955 pretrained_D15,956 gpus16,957 if_cache_gpu17,958 if_save_every_weights18,959 version19,960):961 CSVutil("csvdb/stop.csv", "w+", "formanting", False)962 # 生成filelist963 exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)964 os.makedirs(exp_dir, exist_ok=True)965 gt_wavs_dir = "%s/0_gt_wavs" % (exp_dir)966 feature_dir = (967 "%s/3_feature256" % (exp_dir)968 if version19 == "v1"969 else "%s/3_feature768" % (exp_dir)970 )971 if if_f0_3:972 f0_dir = "%s/2a_f0" % (exp_dir)973 f0nsf_dir = "%s/2b-f0nsf" % (exp_dir)974 names = (975 set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)])976 & set([name.split(".")[0] for name in os.listdir(feature_dir)])977 & set([name.split(".")[0] for name in os.listdir(f0_dir)])978 & set([name.split(".")[0] for name in os.listdir(f0nsf_dir)])979 )980 else:981 names = set([name.split(".")[0] for name in os.listdir(gt_wavs_dir)]) & set(982 [name.split(".")[0] for name in os.listdir(feature_dir)]983 )984 opt = []985 for name in names:986 if if_f0_3:987 opt.append(988 "%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s"989 % (990 gt_wavs_dir.replace("\\", "\\\\"),991 name,992 feature_dir.replace("\\", "\\\\"),993 name,994 f0_dir.replace("\\", "\\\\"),995 name,996 f0nsf_dir.replace("\\", "\\\\"),997 name,998 spk_id5,999 )1000 )1001 else:1002 opt.append(1003 "%s/%s.wav|%s/%s.npy|%s"1004 % (1005 gt_wavs_dir.replace("\\", "\\\\"),1006 name,1007 feature_dir.replace("\\", "\\\\"),1008 name,1009 spk_id5,1010 )1011 )1012 fea_dim = 256 if version19 == "v1" else 7681013 if if_f0_3:1014 for _ in range(2):1015 opt.append(1016 "%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"1017 % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)1018 )1019 else:1020 for _ in range(2):1021 opt.append(1022 "%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s"1023 % (now_dir, sr2, now_dir, fea_dim, spk_id5)1024 )1025 shuffle(opt)1026 with open("%s/filelist.txt" % exp_dir, "w") as f:1027 f.write("\n".join(opt))1028 logger.debug("Write filelist done")1029 # 生成config#无需生成config1030 # 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"1031 logger.info("Use gpus: %s", str(gpus16))1032 if pretrained_G14 == "":1033 logger.info("No pretrained Generator")1034 if pretrained_D15 == "":1035 logger.info("No pretrained Discriminator")1036 if version19 == "v1" or sr2 == "40k":1037 config_path = "v1/%s.json" % sr21038 else:1039 config_path = "v2/%s.json" % sr21040 config_save_path = os.path.join(exp_dir, "config.json")1041 if not pathlib.Path(config_save_path).exists():1042 with open(config_save_path, "w", encoding="utf-8") as f:1043 json.dump(1044 config.json_config[config_path],1045 f,1046 ensure_ascii=False,1047 indent=4,1048 sort_keys=True,1049 )1050 f.write("\n")1051 if gpus16:1052 cmd = (1053 '"%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'1054 % (1055 config.python_cmd,1056 exp_dir1,1057 sr2,1058 1 if if_f0_3 else 0,1059 batch_size12,1060 gpus16,1061 total_epoch11,1062 save_epoch10,1063 "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",1064 "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",1065 1 if if_save_latest13 == True else 0,1066 1 if if_cache_gpu17 == True else 0,1067 1 if if_save_every_weights18 == True else 0,1068 version19,1069 )1070 )1071 else:1072 cmd = (1073 '"%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'1074 % (1075 config.python_cmd,1076 exp_dir1,1077 sr2,1078 1 if if_f0_3 else 0,1079 batch_size12,1080 total_epoch11,1081 save_epoch10,1082 "-pg %s" % pretrained_G14 if pretrained_G14 != "" else "",1083 "-pd %s" % pretrained_D15 if pretrained_D15 != "" else "",1084 1 if if_save_latest13 == True else 0,1085 1 if if_cache_gpu17 == True else 0,1086 1 if if_save_every_weights18 == True else 0,1087 version19,1088 )1089 )1090 logger.info(cmd)1091 global p1092 p = Popen(cmd, shell=True, cwd=now_dir)1093 global PID1094 PID = p.pid1095 1096 p.wait()1097 1098 return i18n("Training is done, check train.log"), {"visible": False, "__type__": "update"}, {"visible": True, "__type__": "update"}1099 1100 1101def train_index(exp_dir1, version19):1102 # exp_dir = "%s/logs/%s" % (now_dir, exp_dir1)1103 exp_dir = "logs/%s" % (exp_dir1)1104 os.makedirs(exp_dir, exist_ok=True)1105 feature_dir = (1106 "%s/3_feature256" % (exp_dir)1107 if version19 == "v1"1108 else "%s/3_feature768" % (exp_dir)1109 )1110 if not os.path.exists(feature_dir):1111 return "请先进行特征提取!"1112 listdir_res = list(os.listdir(feature_dir))1113 if len(listdir_res) == 0:1114 return "请先进行特征提取!"1115 infos = []1116 npys = []1117 for name in sorted(listdir_res):1118 phone = np.load("%s/%s" % (feature_dir, name))1119 npys.append(phone)1120 big_npy = np.concatenate(npys, 0)1121 big_npy_idx = np.arange(big_npy.shape[0])1122 np.random.shuffle(big_npy_idx)1123 big_npy = big_npy[big_npy_idx]1124 if big_npy.shape[0] > 2e5:1125 infos.append("Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0])1126 yield "\n".join(infos)1127 try:1128 big_npy = (1129 MiniBatchKMeans(1130 n_clusters=10000,1131 verbose=True,1132 batch_size=256 * config.n_cpu,1133 compute_labels=False,1134 init="random",1135 )1136 .fit(big_npy)1137 .cluster_centers_1138 )1139 except:1140 info = traceback.format_exc()1141 logger.info(info)1142 infos.append(info)1143 yield "\n".join(infos)1144 1145 np.save("%s/total_fea.npy" % exp_dir, big_npy)1146 n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)1147 infos.append("%s,%s" % (big_npy.shape, n_ivf))1148 yield "\n".join(infos)1149 index = faiss.index_factory(256 if version19 == "v1" else 768, "IVF%s,Flat" % n_ivf)1150 # index = faiss.index_factory(256if version19=="v1"else 768, "IVF%s,PQ128x4fs,RFlat"%n_ivf)1151 infos.append("training")1152 yield "\n".join(infos)1153 index_ivf = faiss.extract_index_ivf(index) #1154 index_ivf.nprobe = 11155 index.train(big_npy)1156 faiss.write_index(1157 index,1158 "%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index"1159 % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),1160 )1161 1162 infos.append("adding")1163 yield "\n".join(infos)1164 batch_size_add = 81921165 for i in range(0, big_npy.shape[0], batch_size_add):1166 index.add(big_npy[i : i + batch_size_add])1167 faiss.write_index(1168 index,1169 "%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index"1170 % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),1171 )1172 infos.append(1173 "Successful Index Construction,added_IVF%s_Flat_nprobe_%s_%s_%s.index"1174 % (n_ivf, index_ivf.nprobe, exp_dir1, version19)1175 )1176 # faiss.write_index(index, '%s/added_IVF%s_Flat_FastScan_%s.index'%(exp_dir,n_ivf,version19))1177 # infos.append("成功构建索引,added_IVF%s_Flat_FastScan_%s.index"%(n_ivf,version19))1178 yield "\n".join(infos)1179 1180def change_info_(ckpt_path):1181 if not os.path.exists(ckpt_path.replace(os.path.basename(ckpt_path), "train.log")):1182 return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}1183 try:1184 with open(1185 ckpt_path.replace(os.path.basename(ckpt_path), "train.log"), "r"1186 ) as f:1187 info = eval(f.read().strip("\n").split("\n")[0].split("\t")[-1])1188 sr, f0 = info["sample_rate"], info["if_f0"]1189 version = "v2" if ("version" in info and info["version"] == "v2") else "v1"1190 return sr, str(f0), version1191 except:1192 traceback.print_exc()1193 return {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}1194 1195F0GPUVisible = config.dml == False1196 1197 1198def change_f0_method(f0method8):1199 if f0method8 == "rmvpe_gpu":1200 visible = F0GPUVisible