diff --git a/GPT_SoVITS/export_torch_script.py b/GPT_SoVITS/export_torch_script.py index 69817a3..b68dd38 100644 --- a/GPT_SoVITS/export_torch_script.py +++ b/GPT_SoVITS/export_torch_script.py @@ -331,7 +331,7 @@ class VitsModel(nn.Module): def __init__(self, vits_path): super().__init__() # dict_s2 = torch.load(vits_path,map_location="cpu") - dict_s2 = torch.load(vits_path) + dict_s2 = torch.load(vits_path, weights_only=False) self.hps = dict_s2["config"] if dict_s2["weight"]["enc_p.text_embedding.weight"].shape[0] == 322: self.hps["model"]["version"] = "v1" @@ -645,7 +645,7 @@ def export(gpt_path, vits_path, ref_audio_path, ref_text, output_path, export_be # gpt_path = "GPT_weights_v2/xw-e15.ckpt" # dict_s1 = torch.load(gpt_path, map_location=device) - dict_s1 = torch.load(gpt_path) + dict_s1 = torch.load(gpt_path, weights_only=False) raw_t2s = get_raw_t2s_model(dict_s1).to(device) print("#### get_raw_t2s_model ####") print(raw_t2s.config) diff --git a/GPT_SoVITS/inference_webui.py b/GPT_SoVITS/inference_webui.py index c507b09..21f5f34 100644 --- a/GPT_SoVITS/inference_webui.py +++ b/GPT_SoVITS/inference_webui.py @@ -30,32 +30,14 @@ logging.getLogger("multipart.multipart").setLevel(logging.ERROR) warnings.simplefilter(action="ignore", category=FutureWarning) version = model_version = os.environ.get("version", "v2") -path_sovits_v3 = "GPT_SoVITS/pretrained_models/s2Gv3.pth" -path_sovits_v4 = "GPT_SoVITS/pretrained_models/gsv-v4-pretrained/s2Gv4.pth" + +from config import name2sovits_path,name2gpt_path,change_choices,get_weights_names +SoVITS_names, GPT_names = get_weights_names() +from config import pretrained_sovits_name +path_sovits_v3 = pretrained_sovits_name["v3"] +path_sovits_v4 = pretrained_sovits_name["v4"] is_exist_s2gv3 = os.path.exists(path_sovits_v3) is_exist_s2gv4 = os.path.exists(path_sovits_v4) -pretrained_sovits_name = [ - "GPT_SoVITS/pretrained_models/s2G488k.pth", - "GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s2G2333k.pth", - "GPT_SoVITS/pretrained_models/s2Gv3.pth", - "GPT_SoVITS/pretrained_models/gsv-v4-pretrained/s2Gv4.pth", -] -pretrained_gpt_name = [ - "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt", - "GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt", - "GPT_SoVITS/pretrained_models/s1v3.ckpt", - "GPT_SoVITS/pretrained_models/s1v3.ckpt", -] - - -_ = [[], []] -for i in range(4): - if os.path.exists(pretrained_gpt_name[i]): - _[0].append(pretrained_gpt_name[i]) - if os.path.exists(pretrained_sovits_name[i]): - _[-1].append(pretrained_sovits_name[i]) -pretrained_gpt_name, pretrained_sovits_name = _ - if os.path.exists("./weight.json"): pass @@ -66,28 +48,24 @@ else: with open("./weight.json", "r", encoding="utf-8") as file: weight_data = file.read() weight_data = json.loads(weight_data) - gpt_path = os.environ.get( - "gpt_path", weight_data.get("GPT", {}).get(version, pretrained_gpt_name) - ) - sovits_path = os.environ.get( - "sovits_path", - weight_data.get("SoVITS", {}).get(version, pretrained_sovits_name), - ) + gpt_path = os.environ.get("gpt_path", weight_data.get("GPT", {}).get(version, GPT_names[-1])) + sovits_path = os.environ.get("sovits_path", weight_data.get("SoVITS", {}).get(version, SoVITS_names[0])) if isinstance(gpt_path, list): gpt_path = gpt_path[0] if isinstance(sovits_path, list): sovits_path = sovits_path[0] -# gpt_path = os.environ.get( -# "gpt_path", pretrained_gpt_name -# ) -# sovits_path = os.environ.get("sovits_path", pretrained_sovits_name) -cnhubert_base_path = os.environ.get( - "cnhubert_base_path", "GPT_SoVITS/pretrained_models/chinese-hubert-base" -) -bert_path = os.environ.get( - "bert_path", "GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large" -) +# print(2333333) +# print(os.environ["gpt_path"]) +# print(gpt_path) +# print(GPT_names) +# print(weight_data) +# print(weight_data.get("GPT", {})) +# print(version)###GPT version里没有s2的v2pro +# print(weight_data.get("GPT", {}).get(version, GPT_names[-1])) + +cnhubert_base_path = os.environ.get("cnhubert_base_path", "GPT_SoVITS/pretrained_models/chinese-hubert-base") +bert_path = os.environ.get("bert_path", "GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large") infer_ttswebui = os.environ.get("infer_ttswebui", 9872) infer_ttswebui = int(infer_ttswebui) is_share = os.environ.get("is_share", "False") @@ -231,9 +209,7 @@ def resample(audio_tensor, sr0, sr1): global resample_transform_dict key = "%s-%s" % (sr0, sr1) if key not in resample_transform_dict: - resample_transform_dict[key] = torchaudio.transforms.Resample(sr0, sr1).to( - device - ) + resample_transform_dict[key] = torchaudio.transforms.Resample(sr0, sr1).to(device) return resample_transform_dict[key](audio_tensor) @@ -242,20 +218,15 @@ def resample(audio_tensor, sr0, sr1): from process_ckpt import get_sovits_version_from_path_fast, load_sovits_new v3v4set = {"v3", "v4"} - - def change_sovits_weights(sovits_path, prompt_language=None, text_language=None): + if "!"in sovits_path:sovits_path=name2sovits_path[sovits_path] global vq_model, hps, version, model_version, dict_language, if_lora_v3 version, model_version, if_lora_v3 = get_sovits_version_from_path_fast(sovits_path) print(sovits_path, version, model_version, if_lora_v3) is_exist = is_exist_s2gv3 if model_version == "v3" else is_exist_s2gv4 + path_sovits = path_sovits_v3 if model_version == "v3" else path_sovits_v4 if if_lora_v3 == True and is_exist == False: - info = ( - "GPT_SoVITS/pretrained_models/s2Gv3.pth" - + f"SoVITS {model_version}" - + " : " - + i18n("底模缺失,无法加载相应 LoRA 权重") - ) + info = path_sovits + i18n("SoVITS %s 底模缺失,无法加载相应 LoRA 权重" % model_version) gr.Warning(info) raise FileExistsError(info) dict_language = dict_language_v1 if version == "v1" else dict_language_v2 @@ -269,10 +240,7 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) prompt_text_update = {"__type__": "update", "value": ""} prompt_language_update = {"__type__": "update", "value": i18n("中文")} if text_language in list(dict_language.keys()): - text_update, text_language_update = {"__type__": "update"}, { - "__type__": "update", - "value": text_language, - } + text_update, text_language_update = {"__type__": "update"}, {"__type__": "update", "value": text_language} else: text_update = {"__type__": "update", "value": ""} text_language_update = {"__type__": "update", "value": i18n("中文")} @@ -293,22 +261,12 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) "__type__": "update", "visible": visible_sample_steps, "value": 32 if model_version == "v3" else 8, - "choices": ( - [4, 8, 16, 32, 64, 128] if model_version == "v3" else [4, 8, 16, 32] - ), + "choices": [4, 8, 16, 32, 64, 128] if model_version == "v3" else [4, 8, 16, 32], }, {"__type__": "update", "visible": visible_inp_refs}, - { - "__type__": "update", - "value": False, - "interactive": True if model_version not in v3v4set else False, - }, + {"__type__": "update", "value": False, "interactive": True if model_version not in v3v4set else False}, {"__type__": "update", "visible": True if model_version == "v3" else False}, - { - "__type__": "update", - "value": i18n("模型加载中,请等待"), - "interactive": False, - }, + {"__type__": "update", "value": i18n("模型加载中,请等待"), "interactive": False}, ) dict_s2 = load_sovits_new(sovits_path) @@ -324,13 +282,16 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) version = hps.model.version # print("sovits版本:",hps.model.version) if model_version not in v3v4set: + if "Pro"not in model_version: + model_version = version + else: + hps.model.version = model_version vq_model = SynthesizerTrn( hps.data.filter_length // 2 + 1, hps.train.segment_size // hps.data.hop_length, n_speakers=hps.data.n_speakers, **hps.model, ) - model_version = version else: hps.model.version = model_version vq_model = SynthesizerTrnV3( @@ -350,17 +311,12 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) vq_model = vq_model.to(device) vq_model.eval() if if_lora_v3 == False: - print( - "loading sovits_%s" % model_version, - vq_model.load_state_dict(dict_s2["weight"], strict=False), - ) + print("loading sovits_%s" % model_version, vq_model.load_state_dict(dict_s2["weight"], strict=False)) else: path_sovits = path_sovits_v3 if model_version == "v3" else path_sovits_v4 print( "loading sovits_%spretrained_G" % model_version, - vq_model.load_state_dict( - load_sovits_new(path_sovits)["weight"], strict=False - ), + vq_model.load_state_dict(load_sovits_new(path_sovits)["weight"], strict=False), ) lora_rank = dict_s2["lora_rank"] lora_config = LoraConfig( @@ -387,16 +343,10 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) "__type__": "update", "visible": visible_sample_steps, "value": 32 if model_version == "v3" else 8, - "choices": ( - [4, 8, 16, 32, 64, 128] if model_version == "v3" else [4, 8, 16, 32] - ), + "choices": [4, 8, 16, 32, 64, 128] if model_version == "v3" else [4, 8, 16, 32], }, {"__type__": "update", "visible": visible_inp_refs}, - { - "__type__": "update", - "value": False, - "interactive": True if model_version not in v3v4set else False, - }, + {"__type__": "update", "value": False, "interactive": True if model_version not in v3v4set else False}, {"__type__": "update", "visible": True if model_version == "v3" else False}, {"__type__": "update", "value": i18n("合成语音"), "interactive": True}, ) @@ -415,9 +365,10 @@ except: def change_gpt_weights(gpt_path): + if "!"in gpt_path:gpt_path=name2gpt_path[gpt_path] global hz, max_sec, t2s_model, config hz = 50 - dict_s1 = torch.load(gpt_path, map_location="cpu") + dict_s1 = torch.load(gpt_path, map_location="cpu", weights_only=False) config = dict_s1["config"] max_sec = config["data"]["max_sec"] t2s_model = Text2SemanticLightningModule(config, "****", is_train=False) @@ -442,19 +393,8 @@ import torch now_dir = os.getcwd() - -def init_bigvgan(): - global bigvgan_model, hifigan_model - from BigVGAN import bigvgan - - bigvgan_model = bigvgan.BigVGAN.from_pretrained( - "%s/GPT_SoVITS/pretrained_models/models--nvidia--bigvgan_v2_24khz_100band_256x" - % (now_dir,), - use_cuda_kernel=False, - ) # if True, RuntimeError: Ninja is required to load C++ extensions - # remove weight norm in the model and set to eval mode - bigvgan_model.remove_weight_norm() - bigvgan_model = bigvgan_model.eval() +def clean_hifigan_model(): + global hifigan_model if hifigan_model: hifigan_model = hifigan_model.cpu() hifigan_model = None @@ -462,14 +402,45 @@ def init_bigvgan(): torch.cuda.empty_cache() except: pass +def clean_bigvgan_model(): + global bigvgan_model + if bigvgan_model: + bigvgan_model = bigvgan_model.cpu() + bigvgan_model = None + try: + torch.cuda.empty_cache() + except: + pass +def clean_sv_cn_model(): + global sv_cn_model + if sv_cn_model: + sv_cn_model.embedding_model = sv_cn_model.embedding_model.cpu() + sv_cn_model = None + try: + torch.cuda.empty_cache() + except: + pass + +def init_bigvgan(): + global bigvgan_model, hifigan_model,sv_cn_model + from BigVGAN import bigvgan + + bigvgan_model = bigvgan.BigVGAN.from_pretrained( + "%s/GPT_SoVITS/pretrained_models/models--nvidia--bigvgan_v2_24khz_100band_256x" % (now_dir,), + use_cuda_kernel=False, + ) # if True, RuntimeError: Ninja is required to load C++ extensions + # remove weight norm in the model and set to eval mode + bigvgan_model.remove_weight_norm() + bigvgan_model = bigvgan_model.eval() + clean_hifigan_model() + clean_sv_cn_model() if is_half == True: bigvgan_model = bigvgan_model.half().to(device) else: bigvgan_model = bigvgan_model.to(device) - def init_hifigan(): - global hifigan_model, bigvgan_model + global hifigan_model, bigvgan_model,sv_cn_model hifigan_model = Generator( initial_channel=100, resblock="1", @@ -484,48 +455,73 @@ def init_hifigan(): hifigan_model.eval() hifigan_model.remove_weight_norm() state_dict_g = torch.load( - "%s/GPT_SoVITS/pretrained_models/gsv-v4-pretrained/vocoder.pth" % (now_dir,), - map_location="cpu", + "%s/GPT_SoVITS/pretrained_models/gsv-v4-pretrained/vocoder.pth" % (now_dir,), map_location="cpu", weights_only=False ) print("loading vocoder", hifigan_model.load_state_dict(state_dict_g)) - if bigvgan_model: - bigvgan_model = bigvgan_model.cpu() - bigvgan_model = None - try: - torch.cuda.empty_cache() - except: - pass + clean_bigvgan_model() + clean_sv_cn_model() if is_half == True: hifigan_model = hifigan_model.half().to(device) else: hifigan_model = hifigan_model.to(device) +from sv import SV +def init_sv_cn(): + global hifigan_model, bigvgan_model,sv_cn_model + sv_cn_model = SV(device, is_half) + clean_bigvgan_model() + clean_hifigan_model() -bigvgan_model = hifigan_model = None + +bigvgan_model = hifigan_model = sv_cn_model = None if model_version == "v3": init_bigvgan() if model_version == "v4": init_hifigan() +if model_version in {"v2Pro","v2ProPlus"}: + init_sv_cn() +resample_transform_dict={} +def resample(audio_tensor, sr0,sr1,device): + global resample_transform_dict + key="%s-%s-%s"%(sr0,sr1,str(device)) + if key not in resample_transform_dict: + resample_transform_dict[key] = torchaudio.transforms.Resample( + sr0, sr1 + ).to(device) + return resample_transform_dict[key](audio_tensor) -def get_spepc(hps, filename): +def get_spepc(hps, filename,dtype,device,is_v2pro=False): # audio = load_audio(filename, int(hps.data.sampling_rate)) - audio, sampling_rate = librosa.load(filename, sr=int(hps.data.sampling_rate)) - audio = torch.FloatTensor(audio) + + # audio, sampling_rate = librosa.load(filename, sr=int(hps.data.sampling_rate)) + # audio = torch.FloatTensor(audio) + + sr1=int(hps.data.sampling_rate) + audio, sr0=torchaudio.load(filename) + if sr0!=sr1: + audio=audio.to(device) + if(audio.shape[0]==2):audio=audio.mean(0).unsqueeze(0) + audio=resample(audio,sr0,sr1,device) + else: + audio=audio.to(device) + if(audio.shape[0]==2):audio=audio.mean(0).unsqueeze(0) + maxx = audio.abs().max() if maxx > 1: audio /= min(2, maxx) - audio_norm = audio - audio_norm = audio_norm.unsqueeze(0) spec = spectrogram_torch( - audio_norm, + audio, hps.data.filter_length, hps.data.sampling_rate, hps.data.hop_length, hps.data.win_length, center=False, ) - return spec + spec=spec.to(dtype) + if is_v2pro==True: + audio=resample(audio,sr1,16000,device).to(dtype) + return spec,audio def clean_text_inf(text, language, version): @@ -588,9 +584,7 @@ def get_phones_and_bert(text, language, version, final=False): formattext = chinese.mix_text_normalize(formattext) return get_phones_and_bert(formattext, "zh", version) else: - phones, word2ph, norm_text = clean_text_inf( - formattext, language, version - ) + phones, word2ph, norm_text = clean_text_inf(formattext, language, version) bert = get_bert_feature(norm_text, word2ph).to(device) elif language == "all_yue" and re.search(r"[A-Za-z]", formattext): formattext = re.sub(r"[a-z]", lambda x: x.group(0).upper(), formattext) @@ -716,11 +710,7 @@ def audio_sr(audio, sr): try: sr_model = AP_BWE(device, DictToAttrRecursive) except FileNotFoundError: - gr.Warning( - i18n( - "你没有下载超分模型的参数,因此不进行超分。如想超分请先参照教程把文件下载好" - ) - ) + gr.Warning(i18n("你没有下载超分模型的参数,因此不进行超分。如想超分请先参照教程把文件下载好")) return audio.cpu().detach().numpy(), sr return sr_model(audio, sr) @@ -764,6 +754,10 @@ def get_tts_wav( ref_free = False # s2v3暂不支持ref_free else: if_sr = False + if model_version not in {"v3","v4","v2Pro","v2ProPlus"}: + clean_bigvgan_model() + clean_hifigan_model() + clean_sv_cn_model() t0 = ttime() prompt_language = dict_language[prompt_language] text_language = dict_language[text_language] @@ -798,11 +792,7 @@ def get_tts_wav( else: wav16k = wav16k.to(device) wav16k = torch.cat([wav16k, zero_wav_torch]) - ssl_content = ssl_model.model(wav16k.unsqueeze(0))[ - "last_hidden_state" - ].transpose( - 1, 2 - ) # .float() + ssl_content = ssl_model.model(wav16k.unsqueeze(0))["last_hidden_state"].transpose(1, 2) # .float() codes = vq_model.extract_latent(ssl_content) prompt_semantic = codes[0, 0] prompt = prompt_semantic.unsqueeze(0).to(device) @@ -829,9 +819,7 @@ def get_tts_wav( audio_opt = [] ###s2v3暂不支持ref_free if not ref_free: - phones1, bert1, norm_text1 = get_phones_and_bert( - prompt_text, prompt_language, version - ) + phones1, bert1, norm_text1 = get_phones_and_bert(prompt_text, prompt_language, version) for i_text, text in enumerate(texts): # 解决输入目标文本的空行导致报错的问题 @@ -844,9 +832,7 @@ def get_tts_wav( print(i18n("前端处理后的文本(每句):"), norm_text2) if not ref_free: bert = torch.cat([bert1, bert2], 1) - all_phoneme_ids = ( - torch.LongTensor(phones1 + phones2).to(device).unsqueeze(0) - ) + all_phoneme_ids = torch.LongTensor(phones1 + phones2).to(device).unsqueeze(0) else: bert = bert2 all_phoneme_ids = torch.LongTensor(phones2).to(device).unsqueeze(0) @@ -875,31 +861,37 @@ def get_tts_wav( pred_semantic = pred_semantic[:, -idx:].unsqueeze(0) cache[i_text] = pred_semantic t3 = ttime() + is_v2pro=model_version in {"v2Pro","v2ProPlus"} + # print(23333,is_v2pro,model_version) ###v3不存在以下逻辑和inp_refs if model_version not in v3v4set: refers = [] + if is_v2pro: + sv_emb=[] + if sv_cn_model == None: + init_sv_cn() if inp_refs: for path in inp_refs: - try: - refer = get_spepc(hps, path.name).to(dtype).to(device) + try:#####这里加上提取sv的逻辑,要么一堆sv一堆refer,要么单个sv单个refer + refer,audio_tensor = get_spepc(hps, path.name,dtype,device,is_v2pro) refers.append(refer) + if is_v2pro: + sv_emb.append(sv_cn_model.compute_embedding3(audio_tensor)) except: traceback.print_exc() if len(refers) == 0: - refers = [get_spepc(hps, ref_wav_path).to(dtype).to(device)] - audio = vq_model.decode( - pred_semantic, - torch.LongTensor(phones2).to(device).unsqueeze(0), - refers, - speed=speed, - )[0][ - 0 - ] # .cpu().detach().numpy() + refers,audio_tensor = get_spepc(hps, ref_wav_path,dtype,device,is_v2pro) + refers=[refers] + if is_v2pro: + sv_emb=[sv_cn_model.compute_embedding3(audio_tensor)] + if is_v2pro: + audio = vq_model.decode(pred_semantic, torch.LongTensor(phones2).to(device).unsqueeze(0), refers, speed=speed,sv_emb=sv_emb)[0][0] + else: + audio = vq_model.decode(pred_semantic, torch.LongTensor(phones2).to(device).unsqueeze(0), refers, speed=speed)[0][0] else: - refer = get_spepc(hps, ref_wav_path).to(device).to(dtype) + refer,audio_tensor = get_spepc(hps, ref_wav_path,dtype,device) phoneme_ids0 = torch.LongTensor(phones1).to(device).unsqueeze(0) phoneme_ids1 = torch.LongTensor(phones2).to(device).unsqueeze(0) - # print(11111111, phoneme_ids0, phoneme_ids1) fea_ref, ge = vq_model.decode_encp(prompt.unsqueeze(0), phoneme_ids0, refer) ref_audio, sr = torchaudio.load(ref_wav_path) ref_audio = ref_audio.to(device).float() @@ -922,9 +914,7 @@ def get_tts_wav( T_min = Tref chunk_len = Tchunk - T_min mel2 = mel2.to(dtype) - fea_todo, ge = vq_model.decode_encp( - pred_semantic, phoneme_ids1, refer, ge, speed - ) + fea_todo, ge = vq_model.decode_encp(pred_semantic, phoneme_ids1, refer, ge, speed) cfm_resss = [] idx = 0 while 1: @@ -934,11 +924,7 @@ def get_tts_wav( idx += chunk_len fea = torch.cat([fea_ref, fea_todo_chunk], 2).transpose(2, 1) cfm_res = vq_model.cfm.inference( - fea, - torch.LongTensor([fea.size(1)]).to(fea.device), - mel2, - sample_steps, - inference_cfg_rate=0, + fea, torch.LongTensor([fea.size(1)]).to(fea.device), mel2, sample_steps, inference_cfg_rate=0 ) cfm_res = cfm_res[:, :, mel2.shape[2] :] mel2 = cfm_res[:, :, -T_min:] @@ -966,7 +952,7 @@ def get_tts_wav( t1 = ttime() print("%.3f\t%.3f\t%.3f\t%.3f" % (t[0], sum(t[1::3]), sum(t[2::3]), sum(t[3::3]))) audio_opt = torch.cat(audio_opt, 0) # np.concatenate - if model_version in {"v1", "v2"}: + if model_version in {"v1", "v2", "v2Pro", "v2ProPlus"}: opt_sr = 32000 elif model_version == "v3": opt_sr = 24000 @@ -1065,13 +1051,7 @@ def cut5(inp): for i, char in enumerate(inp): if char in punds: - if ( - char == "." - and i > 0 - and i < len(inp) - 1 - and inp[i - 1].isdigit() - and inp[i + 1].isdigit() - ): + if char == "." and i > 0 and i < len(inp) - 1 and inp[i - 1].isdigit() and inp[i + 1].isdigit(): items.append(char) else: items.append(char) @@ -1106,46 +1086,6 @@ def process_text(texts): _text.append(text) return _text - -def change_choices(): - SoVITS_names, GPT_names = get_weights_names(GPT_weight_root, SoVITS_weight_root) - return { - "choices": sorted(SoVITS_names, key=custom_sort_key), - "__type__": "update", - }, { - "choices": sorted(GPT_names, key=custom_sort_key), - "__type__": "update", - } - - -SoVITS_weight_root = [ - "SoVITS_weights", - "SoVITS_weights_v2", - "SoVITS_weights_v3", - "SoVITS_weights_v4", -] -GPT_weight_root = ["GPT_weights", "GPT_weights_v2", "GPT_weights_v3", "GPT_weights_v4"] -for path in SoVITS_weight_root + GPT_weight_root: - os.makedirs(path, exist_ok=True) - - -def get_weights_names(GPT_weight_root, SoVITS_weight_root): - SoVITS_names = [i for i in pretrained_sovits_name] - for path in SoVITS_weight_root: - for name in os.listdir(path): - if name.endswith(".pth"): - SoVITS_names.append("%s/%s" % (path, name)) - GPT_names = [i for i in pretrained_gpt_name] - for path in GPT_weight_root: - for name in os.listdir(path): - if name.endswith(".ckpt"): - GPT_names.append("%s/%s" % (path, name)) - return SoVITS_names, GPT_names - - -SoVITS_names, GPT_names = get_weights_names(GPT_weight_root, SoVITS_weight_root) - - def html_center(text, label="p"): return f"""
<{label} style="margin: 0; padding: 0;">{text} @@ -1160,13 +1100,9 @@ def html_left(text, label="p"): with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: gr.Markdown( - value=i18n( - "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责." - ) + value=i18n("本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责.") + "
" - + i18n( - "如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录LICENSE." - ) + + i18n("如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录LICENSE.") ) with gr.Group(): gr.Markdown(html_center(i18n("模型切换"), "h3")) @@ -1185,19 +1121,11 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: interactive=True, scale=14, ) - refresh_button = gr.Button( - i18n("刷新模型路径"), variant="primary", scale=14 - ) - refresh_button.click( - fn=change_choices, inputs=[], outputs=[SoVITS_dropdown, GPT_dropdown] - ) + refresh_button = gr.Button(i18n("刷新模型路径"), variant="primary", scale=14) + refresh_button.click(fn=change_choices, inputs=[], outputs=[SoVITS_dropdown, GPT_dropdown]) gr.Markdown(html_center(i18n("*请上传并填写参考信息"), "h3")) with gr.Row(): - inp_ref = gr.Audio( - label=i18n("请上传3~10秒内参考音频,超过会报错!"), - type="filepath", - scale=13, - ) + inp_ref = gr.Audio(label=i18n("请上传3~10秒内参考音频,超过会报错!"), type="filepath", scale=13) with gr.Column(scale=13): ref_text_free = gr.Checkbox( label=i18n("开启无参考文本模式。不填参考文本亦相当于开启。") @@ -1211,18 +1139,10 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: html_left( i18n("使用无参考文本模式时建议使用微调的GPT") + "
" - + i18n( - "听不清参考音频说的啥(不晓得写啥)可以开。开启后无视填写的参考文本。" - ) + + i18n("听不清参考音频说的啥(不晓得写啥)可以开。开启后无视填写的参考文本。") ) ) - prompt_text = gr.Textbox( - label=i18n("参考音频的文本"), - value="", - lines=5, - max_lines=5, - scale=1, - ) + prompt_text = gr.Textbox(label=i18n("参考音频的文本"), value="", lines=5, max_lines=5, scale=1) with gr.Column(scale=14): prompt_language = gr.Dropdown( label=i18n("参考音频的语种"), @@ -1249,21 +1169,13 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: gr.Radio( label=i18n("采样步数,如果觉得电,提高试试,如果觉得慢,降低试试"), value=32 if model_version == "v3" else 8, - choices=( - [4, 8, 16, 32, 64, 128] - if model_version == "v3" - else [4, 8, 16, 32] - ), + choices=[4, 8, 16, 32, 64, 128] if model_version == "v3" else [4, 8, 16, 32], visible=True, ) if model_version in v3v4set else gr.Radio( label=i18n("采样步数,如果觉得电,提高试试,如果觉得慢,降低试试"), - choices=( - [4, 8, 16, 32, 64, 128] - if model_version == "v3" - else [4, 8, 16, 32] - ), + choices=[4, 8, 16, 32, 64, 128] if model_version == "v3" else [4, 8, 16, 32], visible=False, value=32 if model_version == "v3" else 8, ) @@ -1278,9 +1190,7 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: gr.Markdown(html_center(i18n("*请填写需要合成的目标文本和语种模式"), "h3")) with gr.Row(): with gr.Column(scale=13): - text = gr.Textbox( - label=i18n("需要合成的文本"), value="", lines=26, max_lines=26 - ) + text = gr.Textbox(label=i18n("需要合成的文本"), value="", lines=26, max_lines=26) with gr.Column(scale=7): text_language = gr.Dropdown( label=i18n("需要合成的语种") + i18n(".限制范围越小判别效果越好。"), @@ -1312,13 +1222,7 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: ) with gr.Row(): speed = gr.Slider( - minimum=0.6, - maximum=1.65, - step=0.05, - label=i18n("语速"), - value=1, - interactive=True, - scale=1, + minimum=0.6, maximum=1.65, step=0.05, label=i18n("语速"), value=1, interactive=True, scale=1 ) pause_second_slider = gr.Slider( minimum=0.1, @@ -1329,46 +1233,22 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: interactive=True, scale=1, ) - gr.Markdown( - html_center( - i18n("GPT采样参数(无参考文本时不要太低。不懂就用默认):") - ) - ) + gr.Markdown(html_center(i18n("GPT采样参数(无参考文本时不要太低。不懂就用默认):"))) top_k = gr.Slider( - minimum=1, - maximum=100, - step=1, - label=i18n("top_k"), - value=15, - interactive=True, - scale=1, + minimum=1, maximum=100, step=1, label=i18n("top_k"), value=15, interactive=True, scale=1 ) top_p = gr.Slider( - minimum=0, - maximum=1, - step=0.05, - label=i18n("top_p"), - value=1, - interactive=True, - scale=1, + minimum=0, maximum=1, step=0.05, label=i18n("top_p"), value=1, interactive=True, scale=1 ) temperature = gr.Slider( - minimum=0, - maximum=1, - step=0.05, - label=i18n("temperature"), - value=1, - interactive=True, - scale=1, + minimum=0, maximum=1, step=0.05, label=i18n("temperature"), value=1, interactive=True, scale=1 ) # with gr.Column(): # gr.Markdown(value=i18n("手工调整音素。当音素框不为空时使用手工音素输入推理,无视目标文本框。")) # phoneme=gr.Textbox(label=i18n("音素框"), value="") # get_phoneme_button = gr.Button(i18n("目标文本转音素"), variant="primary") with gr.Row(): - inference_button = gr.Button( - value=i18n("合成语音"), variant="primary", size="lg", scale=25 - ) + inference_button = gr.Button(value=i18n("合成语音"), variant="primary", size="lg", scale=25) output = gr.Audio(label=i18n("输出的语音"), scale=14) inference_button.click( diff --git a/GPT_SoVITS/inference_webui_fast.py b/GPT_SoVITS/inference_webui_fast.py index 6bc4be8..342e7ee 100644 --- a/GPT_SoVITS/inference_webui_fast.py +++ b/GPT_SoVITS/inference_webui_fast.py @@ -98,13 +98,23 @@ cut_method = { i18n("按标点符号切"): "cut5", } +from config import name2sovits_path,name2gpt_path,change_choices,get_weights_names +SoVITS_names, GPT_names = get_weights_names() +from config import pretrained_sovits_name +path_sovits_v3 = pretrained_sovits_name["v3"] +path_sovits_v4 = pretrained_sovits_name["v4"] +is_exist_s2gv3 = os.path.exists(path_sovits_v3) +is_exist_s2gv4 = os.path.exists(path_sovits_v4) + tts_config = TTS_Config("GPT_SoVITS/configs/tts_infer.yaml") tts_config.device = device tts_config.is_half = is_half tts_config.version = version if gpt_path is not None: + if "!"in gpt_path:gpt_path=name2gpt_path[gpt_path] tts_config.t2s_weights_path = gpt_path if sovits_path is not None: + if "!"in sovits_path:sovits_path=name2sovits_path[sovits_path] tts_config.vits_weights_path = sovits_path if cnhubert_base_path is not None: tts_config.cnhuhbert_base_path = cnhubert_base_path @@ -147,11 +157,7 @@ def inference( "text": text, "text_lang": dict_language[text_lang], "ref_audio_path": ref_audio_path, - "aux_ref_audio_paths": ( - [item.name for item in aux_ref_audio_paths] - if aux_ref_audio_paths is not None - else [] - ), + "aux_ref_audio_paths": [item.name for item in aux_ref_audio_paths] if aux_ref_audio_paths is not None else [], "prompt_text": prompt_text if not ref_text_free else "", "prompt_lang": dict_language[prompt_lang], "top_k": top_k, @@ -183,44 +189,6 @@ def custom_sort_key(s): parts = [int(part) if part.isdigit() else part for part in parts] return parts - -def change_choices(): - SoVITS_names, GPT_names = get_weights_names(GPT_weight_root, SoVITS_weight_root) - return { - "choices": sorted(SoVITS_names, key=custom_sort_key), - "__type__": "update", - }, { - "choices": sorted(GPT_names, key=custom_sort_key), - "__type__": "update", - } - - -path_sovits_v3 = "GPT_SoVITS/pretrained_models/s2Gv3.pth" -path_sovits_v4 = "GPT_SoVITS/pretrained_models/gsv-v4-pretrained/s2Gv4.pth" -is_exist_s2gv3 = os.path.exists(path_sovits_v3) -is_exist_s2gv4 = os.path.exists(path_sovits_v4) -pretrained_sovits_name = [ - "GPT_SoVITS/pretrained_models/s2G488k.pth", - "GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s2G2333k.pth", - "GPT_SoVITS/pretrained_models/s2Gv3.pth", - "GPT_SoVITS/pretrained_models/gsv-v4-pretrained/s2Gv4.pth", -] -pretrained_gpt_name = [ - "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt", - "GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt", - "GPT_SoVITS/pretrained_models/s1v3.ckpt", - "GPT_SoVITS/pretrained_models/s1v3.ckpt", -] - - -_ = [[], []] -for i in range(4): - if os.path.exists(pretrained_gpt_name[i]): - _[0].append(pretrained_gpt_name[i]) - if os.path.exists(pretrained_sovits_name[i]): - _[-1].append(pretrained_sovits_name[i]) -pretrained_gpt_name, pretrained_sovits_name = _ - if os.path.exists("./weight.json"): pass else: @@ -230,65 +198,24 @@ else: with open("./weight.json", "r", encoding="utf-8") as file: weight_data = file.read() weight_data = json.loads(weight_data) - gpt_path = os.environ.get( - "gpt_path", weight_data.get("GPT", {}).get(version, pretrained_gpt_name) - ) - sovits_path = os.environ.get( - "sovits_path", - weight_data.get("SoVITS", {}).get(version, pretrained_sovits_name), - ) + gpt_path = os.environ.get("gpt_path", weight_data.get("GPT", {}).get(version, GPT_names[-1])) + sovits_path = os.environ.get("sovits_path", weight_data.get("SoVITS", {}).get(version, SoVITS_names[0])) if isinstance(gpt_path, list): gpt_path = gpt_path[0] if isinstance(sovits_path, list): sovits_path = sovits_path[0] - -SoVITS_weight_root = [ - "SoVITS_weights", - "SoVITS_weights_v2", - "SoVITS_weights_v3", - "SoVITS_weights_v4", -] -GPT_weight_root = ["GPT_weights", "GPT_weights_v2", "GPT_weights_v3", "GPT_weights_v4"] -for path in SoVITS_weight_root + GPT_weight_root: - os.makedirs(path, exist_ok=True) - - -def get_weights_names(GPT_weight_root, SoVITS_weight_root): - SoVITS_names = [i for i in pretrained_sovits_name] - for path in SoVITS_weight_root: - for name in os.listdir(path): - if name.endswith(".pth"): - SoVITS_names.append("%s/%s" % (path, name)) - GPT_names = [i for i in pretrained_gpt_name] - for path in GPT_weight_root: - for name in os.listdir(path): - if name.endswith(".ckpt"): - GPT_names.append("%s/%s" % (path, name)) - return SoVITS_names, GPT_names - - -SoVITS_names, GPT_names = get_weights_names(GPT_weight_root, SoVITS_weight_root) - - from process_ckpt import get_sovits_version_from_path_fast - v3v4set = {"v3", "v4"} - - def change_sovits_weights(sovits_path, prompt_language=None, text_language=None): + if "!"in sovits_path:sovits_path=name2sovits_path[sovits_path] global version, model_version, dict_language, if_lora_v3 version, model_version, if_lora_v3 = get_sovits_version_from_path_fast(sovits_path) # print(sovits_path,version, model_version, if_lora_v3) is_exist = is_exist_s2gv3 if model_version == "v3" else is_exist_s2gv4 path_sovits = path_sovits_v3 if model_version == "v3" else path_sovits_v4 if if_lora_v3 == True and is_exist == False: - info = ( - path_sovits - + f"SoVITS {model_version}" - + " : " - + i18n("底模缺失,无法加载相应 LoRA 权重") - ) + info = path_sovits + i18n("SoVITS %s 底模缺失,无法加载相应 LoRA 权重" % model_version) gr.Warning(info) raise FileExistsError(info) dict_language = dict_language_v1 if version == "v1" else dict_language_v2 @@ -302,10 +229,7 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) prompt_text_update = {"__type__": "update", "value": ""} prompt_language_update = {"__type__": "update", "value": i18n("中文")} if text_language in list(dict_language.keys()): - text_update, text_language_update = {"__type__": "update"}, { - "__type__": "update", - "value": text_language, - } + text_update, text_language_update = {"__type__": "update"}, {"__type__": "update", "value": text_language} else: text_update = {"__type__": "update", "value": ""} text_language_update = {"__type__": "update", "value": i18n("中文")} @@ -324,15 +248,8 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) text_language_update, {"__type__": "update", "interactive": visible_sample_steps, "value": 32}, {"__type__": "update", "visible": visible_inp_refs}, - { - "__type__": "update", - "interactive": True if model_version not in v3v4set else False, - }, - { - "__type__": "update", - "value": i18n("模型加载中,请等待"), - "interactive": False, - }, + {"__type__": "update", "interactive": True if model_version not in v3v4set else False}, + {"__type__": "update", "value": i18n("模型加载中,请等待"), "interactive": False}, ) tts_pipeline.init_vits_weights(sovits_path) @@ -345,10 +262,7 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) text_language_update, {"__type__": "update", "interactive": visible_sample_steps, "value": 32}, {"__type__": "update", "visible": visible_inp_refs}, - { - "__type__": "update", - "interactive": True if model_version not in v3v4set else False, - }, + {"__type__": "update", "interactive": True if model_version not in v3v4set else False}, {"__type__": "update", "value": i18n("合成语音"), "interactive": True}, ) with open("./weight.json") as f: @@ -361,13 +275,9 @@ def change_sovits_weights(sovits_path, prompt_language=None, text_language=None) with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: gr.Markdown( - value=i18n( - "本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责." - ) + value=i18n("本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责.") + "
" - + i18n( - "如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录LICENSE." - ) + + i18n("如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录LICENSE.") ) with gr.Column(): @@ -387,18 +297,13 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: interactive=True, ) refresh_button = gr.Button(i18n("刷新模型路径"), variant="primary") - refresh_button.click( - fn=change_choices, inputs=[], outputs=[SoVITS_dropdown, GPT_dropdown] - ) + refresh_button.click(fn=change_choices, inputs=[], outputs=[SoVITS_dropdown, GPT_dropdown]) with gr.Row(): with gr.Column(): gr.Markdown(value=i18n("*请上传并填写参考信息")) with gr.Row(): - inp_ref = gr.Audio( - label=i18n("主参考音频(请上传3~10秒内参考音频,超过会报错!)"), - type="filepath", - ) + inp_ref = gr.Audio(label=i18n("主参考音频(请上传3~10秒内参考音频,超过会报错!)"), type="filepath") inp_refs = gr.File( label=i18n("辅参考音频(可选多个,或不选)"), file_count="multiple", @@ -407,9 +312,7 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: prompt_text = gr.Textbox(label=i18n("主参考音频的文本"), value="", lines=2) with gr.Row(): prompt_language = gr.Dropdown( - label=i18n("主参考音频的语种"), - choices=list(dict_language.keys()), - value=i18n("中文"), + label=i18n("主参考音频的语种"), choices=list(dict_language.keys()), value=i18n("中文") ) with gr.Column(): ref_text_free = gr.Checkbox( @@ -421,20 +324,14 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: gr.Markdown( i18n("使用无参考文本模式时建议使用微调的GPT") + "
" - + i18n( - "听不清参考音频说的啥(不晓得写啥)可以开。开启后无视填写的参考文本。" - ) + + i18n("听不清参考音频说的啥(不晓得写啥)可以开。开启后无视填写的参考文本。") ) with gr.Column(): gr.Markdown(value=i18n("*请填写需要合成的目标文本和语种模式")) - text = gr.Textbox( - label=i18n("需要合成的文本"), value="", lines=20, max_lines=20 - ) + text = gr.Textbox(label=i18n("需要合成的文本"), value="", lines=20, max_lines=20) text_language = gr.Dropdown( - label=i18n("需要合成的文本的语种"), - choices=list(dict_language.keys()), - value=i18n("中文"), + label=i18n("需要合成的文本的语种"), choices=list(dict_language.keys()), value=i18n("中文") ) with gr.Group(): @@ -443,69 +340,27 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: with gr.Column(): with gr.Row(): batch_size = gr.Slider( - minimum=1, - maximum=200, - step=1, - label=i18n("batch_size"), - value=20, - interactive=True, + minimum=1, maximum=200, step=1, label=i18n("batch_size"), value=20, interactive=True ) sample_steps = gr.Radio( - label=i18n("采样步数(仅对V3/4生效)"), - value=32, - choices=[4, 8, 16, 32, 64, 128], - visible=True, + label=i18n("采样步数(仅对V3/4生效)"), value=32, choices=[4, 8, 16, 32, 64, 128], visible=True ) with gr.Row(): fragment_interval = gr.Slider( - minimum=0.01, - maximum=1, - step=0.01, - label=i18n("分段间隔(秒)"), - value=0.3, - interactive=True, + minimum=0.01, maximum=1, step=0.01, label=i18n("分段间隔(秒)"), value=0.3, interactive=True ) speed_factor = gr.Slider( - minimum=0.6, - maximum=1.65, - step=0.05, - label="语速", - value=1.0, - interactive=True, + minimum=0.6, maximum=1.65, step=0.05, label="语速", value=1.0, interactive=True ) with gr.Row(): - top_k = gr.Slider( - minimum=1, - maximum=100, - step=1, - label=i18n("top_k"), - value=5, - interactive=True, - ) - top_p = gr.Slider( - minimum=0, - maximum=1, - step=0.05, - label=i18n("top_p"), - value=1, - interactive=True, - ) + top_k = gr.Slider(minimum=1, maximum=100, step=1, label=i18n("top_k"), value=5, interactive=True) + top_p = gr.Slider(minimum=0, maximum=1, step=0.05, label=i18n("top_p"), value=1, interactive=True) with gr.Row(): temperature = gr.Slider( - minimum=0, - maximum=1, - step=0.05, - label=i18n("temperature"), - value=1, - interactive=True, + minimum=0, maximum=1, step=0.05, label=i18n("temperature"), value=1, interactive=True ) repetition_penalty = gr.Slider( - minimum=0, - maximum=2, - step=0.05, - label=i18n("重复惩罚"), - value=1.35, - interactive=True, + minimum=0, maximum=2, step=0.05, label=i18n("重复惩罚"), value=1.35, interactive=True ) with gr.Column(): @@ -525,19 +380,11 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: scale=1, ) super_sampling = gr.Checkbox( - label=i18n("音频超采样(仅对V3生效))"), - value=False, - interactive=True, - show_label=True, + label=i18n("音频超采样(仅对V3生效))"), value=False, interactive=True, show_label=True ) with gr.Row(): - parallel_infer = gr.Checkbox( - label=i18n("并行推理"), - value=True, - interactive=True, - show_label=True, - ) + parallel_infer = gr.Checkbox(label=i18n("并行推理"), value=True, interactive=True, show_label=True) split_bucket = gr.Checkbox( label=i18n("数据分桶(并行推理时会降低一点计算量)"), value=True, @@ -547,12 +394,7 @@ with gr.Blocks(title="GPT-SoVITS WebUI", analytics_enabled=False) as app: with gr.Row(): seed = gr.Number(label=i18n("随机种子"), value=-1) - keep_random = gr.Checkbox( - label=i18n("保持随机"), - value=True, - interactive=True, - show_label=True, - ) + keep_random = gr.Checkbox(label=i18n("保持随机"), value=True, interactive=True, show_label=True) output = gr.Audio(label=i18n("输出的语音")) with gr.Row(): diff --git a/GPT_SoVITS/process_ckpt.py b/GPT_SoVITS/process_ckpt.py index 1c458a4..1e5471b 100644 --- a/GPT_SoVITS/process_ckpt.py +++ b/GPT_SoVITS/process_ckpt.py @@ -17,29 +17,27 @@ def my_save(fea, path): #####fix issue: torch.save doesn't support chinese path shutil.move(tmp_path, "%s/%s" % (dir, name)) -""" -00:v1 -01:v2 -02:v3 -03:v3lora -04:v4lora -""" from io import BytesIO - -def my_save2(fea, path, cfm_version): +model_version2byte={ + "v3":b"03", + "v4":b"04", + "v2Pro":b"05", + "v2ProPlus":b"06", +} +def my_save2(fea, path, model_version): bio = BytesIO() torch.save(fea, bio) bio.seek(0) data = bio.getvalue() - byte = b"03" if cfm_version == "v3" else b"04" + byte = model_version2byte[model_version] data = byte + data[2:] with open(path, "wb") as f: f.write(data) -def savee(ckpt, name, epoch, steps, hps, cfm_version=None, lora_rank=None): +def savee(ckpt, name, epoch, steps, hps, model_version=None, lora_rank=None): try: opt = OrderedDict() opt["weight"] = {} @@ -51,26 +49,40 @@ def savee(ckpt, name, epoch, steps, hps, cfm_version=None, lora_rank=None): opt["info"] = "%sepoch_%siteration" % (epoch, steps) if lora_rank: opt["lora_rank"] = lora_rank - my_save2(opt, "%s/%s.pth" % (hps.save_weight_dir, name), cfm_version) + my_save2(opt, "%s/%s.pth" % (hps.save_weight_dir, name), model_version) + elif (model_version!=None and "Pro"in model_version): + my_save2(opt, "%s/%s.pth" % (hps.save_weight_dir, name), model_version) else: my_save(opt, "%s/%s.pth" % (hps.save_weight_dir, name)) return "Success." except: return traceback.format_exc() - +""" +00:v1 +01:v2 +02:v3 +03:v3lora +04:v4lora +05:v2Pro +06:v2ProPlus +""" head2version = { b"00": ["v1", "v1", False], b"01": ["v2", "v2", False], b"02": ["v2", "v3", False], b"03": ["v2", "v3", True], b"04": ["v2", "v4", True], + b"05": ["v2", "v2Pro", False], + b"06": ["v2", "v2ProPlus", False], } hash_pretrained_dict = { "dc3c97e17592963677a4a1681f30c653": ["v2", "v2", False], # s2G488k.pth#sovits_v1_pretrained "43797be674a37c1c83ee81081941ed0f": ["v2", "v3", False], # s2Gv3.pth#sovits_v3_pretrained "6642b37f3dbb1f76882b69937c95a5f3": ["v2", "v2", False], # s2G2333K.pth#sovits_v2_pretrained "4f26b9476d0c5033e04162c486074374": ["v2", "v4", False], # s2Gv4.pth#sovits_v4_pretrained + "1dbcf2d280aff5dc4713c7b56b5c9463": ["v2", "v2Pro", False], # s2Gv2Pro_pre1.pth#sovits_v2Pro_pretrained + "2581b83257dbb1c91d1278e40c6b7a2f": ["v2", "v2ProPlus", False], # s2Gv2ProPlus_pre1.pth#sovits_v2ProPlus_pretrained } import hashlib diff --git a/GPT_SoVITS/s2_train.py b/GPT_SoVITS/s2_train.py index ab46118..0a04604 100644 --- a/GPT_SoVITS/s2_train.py +++ b/GPT_SoVITS/s2_train.py @@ -36,7 +36,7 @@ from module.models import ( MultiPeriodDiscriminator, SynthesizerTrn, ) -from process_ckpt import savee +from process_ckpt import savee,my_save2 torch.backends.cudnn.benchmark = False torch.backends.cudnn.deterministic = False @@ -87,38 +87,19 @@ def run(rank, n_gpus, hps): if torch.cuda.is_available(): torch.cuda.set_device(rank) - train_dataset = TextAudioSpeakerLoader(hps.data) ######## + train_dataset = TextAudioSpeakerLoader(hps.data,version=hps.model.version) train_sampler = DistributedBucketSampler( train_dataset, hps.train.batch_size, - [ - 32, - 300, - 400, - 500, - 600, - 700, - 800, - 900, - 1000, - 1100, - 1200, - 1300, - 1400, - 1500, - 1600, - 1700, - 1800, - 1900, - ], + [32,300,400,500,600,700,800,900,1000,1100,1200,1300,1400,1500,1600,1700,1800,1900,], num_replicas=n_gpus, rank=rank, shuffle=True, ) - collate_fn = TextAudioSpeakerCollate() + collate_fn = TextAudioSpeakerCollate(version=hps.model.version) train_loader = DataLoader( train_dataset, - num_workers=6, + num_workers=5, shuffle=False, pin_memory=True, collate_fn=collate_fn, @@ -149,9 +130,9 @@ def run(rank, n_gpus, hps): ) net_d = ( - MultiPeriodDiscriminator(hps.model.use_spectral_norm).cuda(rank) + MultiPeriodDiscriminator(hps.model.use_spectral_norm,version=hps.model.version).cuda(rank) if torch.cuda.is_available() - else MultiPeriodDiscriminator(hps.model.use_spectral_norm).to(device) + else MultiPeriodDiscriminator(hps.model.use_spectral_norm,version=hps.model.version).to(device) ) for name, param in net_g.named_parameters(): if not param.requires_grad: @@ -235,12 +216,12 @@ def run(rank, n_gpus, hps): print( "loaded pretrained %s" % hps.train.pretrained_s2G, net_g.module.load_state_dict( - torch.load(hps.train.pretrained_s2G, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2G, map_location="cpu", weights_only=False)["weight"], strict=False, ) if torch.cuda.is_available() else net_g.load_state_dict( - torch.load(hps.train.pretrained_s2G, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2G, map_location="cpu", weights_only=False)["weight"], strict=False, ), ) ##测试不加载优化器 @@ -254,11 +235,11 @@ def run(rank, n_gpus, hps): print( "loaded pretrained %s" % hps.train.pretrained_s2D, net_d.module.load_state_dict( - torch.load(hps.train.pretrained_s2D, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2D, map_location="cpu", weights_only=False)["weight"],strict=False ) if torch.cuda.is_available() else net_d.load_state_dict( - torch.load(hps.train.pretrained_s2D, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2D, map_location="cpu", weights_only=False)["weight"], ), ) @@ -328,50 +309,20 @@ def train_and_evaluate(rank, epoch, hps, nets, optims, schedulers, scaler, loade net_g.train() net_d.train() - for batch_idx, ( - ssl, - ssl_lengths, - spec, - spec_lengths, - y, - y_lengths, - text, - text_lengths, - ) in enumerate(tqdm(train_loader)): + for batch_idx, data in enumerate(tqdm(train_loader)): + if hps.model.version in {"v2Pro","v2ProPlus"}: + ssl, ssl_lengths, spec, spec_lengths, y, y_lengths, text, text_lengths,sv_emb=data + else: + ssl, ssl_lengths, spec, spec_lengths, y, y_lengths, text, text_lengths=data if torch.cuda.is_available(): - spec, spec_lengths = ( - spec.cuda( - rank, - non_blocking=True, - ), - spec_lengths.cuda( - rank, - non_blocking=True, - ), - ) - y, y_lengths = ( - y.cuda( - rank, - non_blocking=True, - ), - y_lengths.cuda( - rank, - non_blocking=True, - ), - ) + spec, spec_lengths = (spec.cuda(rank,non_blocking=True,),spec_lengths.cuda(rank,non_blocking=True,),) + y, y_lengths = (y.cuda(rank,non_blocking=True,),y_lengths.cuda(rank,non_blocking=True,),) ssl = ssl.cuda(rank, non_blocking=True) ssl.requires_grad = False # ssl_lengths = ssl_lengths.cuda(rank, non_blocking=True) - text, text_lengths = ( - text.cuda( - rank, - non_blocking=True, - ), - text_lengths.cuda( - rank, - non_blocking=True, - ), - ) + text, text_lengths = (text.cuda(rank,non_blocking=True,),text_lengths.cuda(rank,non_blocking=True,),) + if hps.model.version in {"v2Pro", "v2ProPlus"}: + sv_emb = sv_emb.cuda(rank, non_blocking=True) else: spec, spec_lengths = spec.to(device), spec_lengths.to(device) y, y_lengths = y.to(device), y_lengths.to(device) @@ -379,17 +330,13 @@ def train_and_evaluate(rank, epoch, hps, nets, optims, schedulers, scaler, loade ssl.requires_grad = False # ssl_lengths = ssl_lengths.cuda(rank, non_blocking=True) text, text_lengths = text.to(device), text_lengths.to(device) - + if hps.model.version in {"v2Pro", "v2ProPlus"}: + sv_emb = sv_emb.to(device) with autocast(enabled=hps.train.fp16_run): - ( - y_hat, - kl_ssl, - ids_slice, - x_mask, - z_mask, - (z, z_p, m_p, logs_p, m_q, logs_q), - stats_ssl, - ) = net_g(ssl, spec, spec_lengths, text, text_lengths) + if hps.model.version in {"v2Pro", "v2ProPlus"}: + (y_hat,kl_ssl,ids_slice,x_mask,z_mask,(z, z_p, m_p, logs_p, m_q, logs_q),stats_ssl) = net_g(ssl, spec, spec_lengths, text, text_lengths,sv_emb) + else: + (y_hat,kl_ssl,ids_slice,x_mask,z_mask,(z, z_p, m_p, logs_p, m_q, logs_q),stats_ssl,) = net_g(ssl, spec, spec_lengths, text, text_lengths) mel = spec_to_mel_torch( spec, @@ -561,13 +508,7 @@ def train_and_evaluate(rank, epoch, hps, nets, optims, schedulers, scaler, loade % ( hps.name, epoch, - savee( - ckpt, - hps.name + "_e%s_s%s" % (epoch, global_step), - epoch, - global_step, - hps, - ), + savee(ckpt,hps.name + "_e%s_s%s" % (epoch, global_step),epoch,global_step,hps,model_version=None if hps.model.version not in {"v2Pro","v2ProPlus"}else hps.model.version), ) ) diff --git a/GPT_SoVITS/s2_train_v3.py b/GPT_SoVITS/s2_train_v3.py index 71d2196..aa8dae7 100644 --- a/GPT_SoVITS/s2_train_v3.py +++ b/GPT_SoVITS/s2_train_v3.py @@ -204,12 +204,12 @@ def run(rank, n_gpus, hps): print( "loaded pretrained %s" % hps.train.pretrained_s2G, net_g.module.load_state_dict( - torch.load(hps.train.pretrained_s2G, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2G, map_location="cpu", weights_only=False)["weight"], strict=False, ) if torch.cuda.is_available() else net_g.load_state_dict( - torch.load(hps.train.pretrained_s2G, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2G, map_location="cpu", weights_only=False)["weight"], strict=False, ), ) ##测试不加载优化器 diff --git a/GPT_SoVITS/s2_train_v3_lora.py b/GPT_SoVITS/s2_train_v3_lora.py index 4d8d23d..ba9e4ed 100644 --- a/GPT_SoVITS/s2_train_v3_lora.py +++ b/GPT_SoVITS/s2_train_v3_lora.py @@ -189,7 +189,7 @@ def run(rank, n_gpus, hps): print( "loaded pretrained %s" % hps.train.pretrained_s2G, net_g.load_state_dict( - torch.load(hps.train.pretrained_s2G, map_location="cpu")["weight"], + torch.load(hps.train.pretrained_s2G, map_location="cpu", weights_only=False)["weight"], strict=False, ), ) @@ -365,7 +365,7 @@ def train_and_evaluate(rank, epoch, hps, nets, optims, schedulers, scaler, loade epoch, global_step, hps, - cfm_version=hps.model.version, + model_version=hps.model.version, lora_rank=lora_rank, ), ) diff --git a/GPT_SoVITS/sv.py b/GPT_SoVITS/sv.py new file mode 100644 index 0000000..00f0cff --- /dev/null +++ b/GPT_SoVITS/sv.py @@ -0,0 +1,24 @@ +import sys,os,torch +sys.path.append(f"{os.getcwd()}/GPT_SoVITS/eres2net") +sv_path = "GPT_SoVITS\pretrained_models\sv\pretrained_eres2netv2w24s4ep4.ckpt" +from ERes2NetV2 import ERes2NetV2 +import kaldi as Kaldi +class SV: + def __init__(self,device,is_half): + pretrained_state = torch.load(sv_path, map_location='cpu', weights_only=False) + embedding_model = ERes2NetV2(baseWidth=24,scale=4,expansion=4) + embedding_model.load_state_dict(pretrained_state) + embedding_model.eval() + self.embedding_model=embedding_model + if is_half == False: + self.embedding_model=self.embedding_model.to(device) + else: + self.embedding_model=self.embedding_model.half().to(device) + self.is_half=is_half + + def compute_embedding3(self,wav):#(1,x)#-1~1 + with torch.no_grad(): + if self.is_half==True:wav=wav.half() + feat = torch.stack([Kaldi.fbank(wav0.unsqueeze(0), num_mel_bins=80, sample_frequency=16000, dither=0) for wav0 in wav]) + sv_emb = self.embedding_model.forward3(feat) + return sv_emb \ No newline at end of file diff --git a/GPT_SoVITS/utils.py b/GPT_SoVITS/utils.py index 0ec4251..14955fd 100644 --- a/GPT_SoVITS/utils.py +++ b/GPT_SoVITS/utils.py @@ -22,7 +22,7 @@ logger = logging def load_checkpoint(checkpoint_path, model, optimizer=None, skip_optimizer=False): assert os.path.isfile(checkpoint_path) - checkpoint_dict = torch.load(checkpoint_path, map_location="cpu") + checkpoint_dict = torch.load(checkpoint_path, map_location="cpu", weights_only=False) iteration = checkpoint_dict["iteration"] learning_rate = checkpoint_dict["learning_rate"] if optimizer is not None and not skip_optimizer and checkpoint_dict["optimizer"] is not None: