Update the base code

This commit is contained in:
Justin John
2024-08-08 09:59:00 +05:30
parent f1456ec6fb
commit 9aebadf790
67 changed files with 48594 additions and 587 deletions
+3 -1
View File
@@ -15,6 +15,8 @@ from torch.utils.data import DataLoader
from torch.utils.data import Dataset
from transformers import AutoTokenizer
version = os.environ.get('version',None)
from text import cleaned_text_to_sequence
# from config import exp_dir
@@ -149,7 +151,7 @@ class Text2SemanticDataset(Dataset):
phoneme = phoneme.split(" ")
try:
phoneme_ids = cleaned_text_to_sequence(phoneme)
phoneme_ids = cleaned_text_to_sequence(phoneme, version)
except:
traceback.print_exc()
# print(f"{item_name} not in self.phoneme_data !")
@@ -0,0 +1,31 @@
train:
seed: 1234
epochs: 20
batch_size: 8
save_every_n_epoch: 1
precision: 16-mixed
gradient_clip: 1.0
optimizer:
lr: 0.01
lr_init: 0.00001
lr_end: 0.0001
warmup_steps: 2000
decay_steps: 40000
data:
max_eval_sample: 8
max_sec: 54
num_workers: 4
pad_val: 1024 # same with EOS in model
model:
vocab_size: 1025
phoneme_vocab_size: 732
embedding_dim: 512
hidden_dim: 512
head: 16
linear_units: 2048
n_layer: 24
dropout: 0
EOS: 1024
random_bert: 0
inference:
top_k: 15
+5
View File
@@ -0,0 +1,5 @@
import os, sys
now_dir = os.getcwd()
sys.path.insert(0, now_dir)
from .text.g2pw import G2PWPinyin
g2pw = G2PWPinyin(model_dir="GPT_SoVITS/text/G2PWModel",model_source="GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large",v_to_u=False, neutral_tone_with_five=True)
@@ -4,8 +4,11 @@ import librosa
import torch
import torch.nn.functional as F
import soundfile as sf
import logging
import os
from transformers import logging as tf_logging
tf_logging.set_verbosity_error()
import logging
logging.getLogger("numba").setLevel(logging.WARNING)
from transformers import (
@@ -22,9 +25,11 @@ cnhubert_base_path = None
class CNHubert(nn.Module):
def __init__(self):
super().__init__()
self.model = HubertModel.from_pretrained(cnhubert_base_path)
if os.path.exists(cnhubert_base_path):...
else:raise FileNotFoundError(cnhubert_base_path)
self.model = HubertModel.from_pretrained(cnhubert_base_path, local_files_only=True)
self.feature_extractor = Wav2Vec2FeatureExtractor.from_pretrained(
cnhubert_base_path
cnhubert_base_path, local_files_only=True
)
def forward(self, x):
+227 -131
View File
@@ -6,8 +6,9 @@
全部按英文识别
全部按日文识别
'''
import os, re, logging
import LangSegment
import logging
import traceback
logging.getLogger("markdown_it").setLevel(logging.ERROR)
logging.getLogger("urllib3").setLevel(logging.ERROR)
logging.getLogger("httpcore").setLevel(logging.ERROR)
@@ -15,28 +16,46 @@ logging.getLogger("httpx").setLevel(logging.ERROR)
logging.getLogger("asyncio").setLevel(logging.ERROR)
logging.getLogger("charset_normalizer").setLevel(logging.ERROR)
logging.getLogger("torchaudio._extension").setLevel(logging.ERROR)
logging.getLogger("multipart.multipart").setLevel(logging.ERROR)
import LangSegment, os, re, sys, json
import pdb
import torch
if os.path.exists("./gweight.txt"):
with open("./gweight.txt", 'r', encoding="utf-8") as file:
gweight_data = file.read()
gpt_path = os.environ.get(
"gpt_path", gweight_data)
else:
gpt_path = os.environ.get(
"gpt_path", "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt")
version=os.environ.get("version","v2")
pretrained_sovits_name=["GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s2G2333k.pth", "GPT_SoVITS/pretrained_models/s2G488k.pth"]
pretrained_gpt_name=["GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt", "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt"]
if os.path.exists("./sweight.txt"):
with open("./sweight.txt", 'r', encoding="utf-8") as file:
sweight_data = file.read()
sovits_path = os.environ.get("sovits_path", sweight_data)
_ =[[],[]]
for i in range(2):
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(f"./weight.json"):
pass
else:
sovits_path = os.environ.get("sovits_path", "GPT_SoVITS/pretrained_models/s2G488k.pth")
with open(f"./weight.json", 'w', encoding="utf-8") as file:json.dump({'GPT':{},'SoVITS':{}},file)
with open(f"./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))
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_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt"
# "gpt_path", pretrained_gpt_name
# )
# sovits_path = os.environ.get("sovits_path", "pretrained_models/s2G488k.pth")
# 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"
)
@@ -66,9 +85,11 @@ from text.cleaner import clean_text
from time import time as ttime
from module.mel_processing import spectrogram_torch
from tools.my_utils import load_audio
from tools.i18n.i18n import I18nAuto
from tools.i18n.i18n import I18nAuto, scan_language_list
i18n = I18nAuto()
language=os.environ.get("language","Auto")
language=sys.argv[-1] if sys.argv[-1] in scan_language_list() else language
i18n = I18nAuto(language=language)
# os.environ['PYTORCH_ENABLE_MPS_FALLBACK'] = '1' # 确保直接启动推理UI时也能够设置。
@@ -77,6 +98,29 @@ if torch.cuda.is_available():
else:
device = "cpu"
dict_language_v1 = {
i18n("中文"): "all_zh",#全部按中文识别
i18n("英文"): "en",#全部按英文识别#######不变
i18n("日文"): "all_ja",#全部按日文识别
i18n("中英混合"): "zh",#按中英混合识别####不变
i18n("日英混合"): "ja",#按日英混合识别####不变
i18n("多语种混合"): "auto",#多语种启动切分识别语种
}
dict_language_v2 = {
i18n("中文"): "all_zh",#全部按中文识别
i18n("英文"): "en",#全部按英文识别#######不变
i18n("日文"): "all_ja",#全部按日文识别
i18n("粤语"): "all_yue",#全部按中文识别
i18n("韩文"): "all_ko",#全部按韩文识别
i18n("中英混合"): "zh",#按中英混合识别####不变
i18n("日英混合"): "ja",#按日英混合识别####不变
i18n("粤英混合"): "yue",#按粤英混合识别####不变
i18n("韩英混合"): "ko",#按韩英混合识别####不变
i18n("多语种混合"): "auto",#多语种启动切分识别语种
i18n("多语种混合(粤语)"): "auto_yue",#多语种启动切分识别语种
}
dict_language = dict_language_v1 if version =='v1' else dict_language_v2
tokenizer = AutoTokenizer.from_pretrained(bert_path)
bert_model = AutoModelForMaskedLM.from_pretrained(bert_path)
if is_half == True:
@@ -136,12 +180,18 @@ else:
ssl_model = ssl_model.to(device)
def change_sovits_weights(sovits_path):
global vq_model, hps
def change_sovits_weights(sovits_path,prompt_language=None,text_language=None):
global vq_model, hps, version, dict_language
dict_s2 = torch.load(sovits_path, map_location="cpu")
hps = dict_s2["config"]
hps = DictToAttrRecursive(hps)
hps.model.semantic_frame_rate = "25hz"
if dict_s2['weight']['enc_p.text_embedding.weight'].shape[0] == 322:
hps.model.version = "v1"
else:
hps.model.version = "v2"
version = hps.model.version
# print("sovits版本:",hps.model.version)
vq_model = SynthesizerTrn(
hps.data.filter_length // 2 + 1,
hps.train.segment_size // hps.data.hop_length,
@@ -156,8 +206,25 @@ def change_sovits_weights(sovits_path):
vq_model = vq_model.to(device)
vq_model.eval()
print(vq_model.load_state_dict(dict_s2["weight"], strict=False))
with open("./sweight.txt", "w", encoding="utf-8") as f:
f.write(sovits_path)
dict_language = dict_language_v1 if version =='v1' else dict_language_v2
with open("./weight.json")as f:
data=f.read()
data=json.loads(data)
data["SoVITS"][version]=sovits_path
with open("./weight.json","w")as f:f.write(json.dumps(data))
if prompt_language is not None and text_language is not None:
if prompt_language in list(dict_language.keys()):
prompt_text_update, prompt_language_update = {'__type__':'update'}, {'__type__':'update', 'value':prompt_language}
else:
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}
else:
text_update = {'__type__':'update', 'value':''}
text_language_update = {'__type__':'update', 'value':i18n("中文")}
return {'__type__':'update', 'choices':list(dict_language.keys())}, {'__type__':'update', 'choices':list(dict_language.keys())}, prompt_text_update, prompt_language_update, text_update, text_language_update
change_sovits_weights(sovits_path)
@@ -177,7 +244,11 @@ def change_gpt_weights(gpt_path):
t2s_model.eval()
total = sum([param.nelement() for param in t2s_model.parameters()])
print("Number of parameter: %.2fM" % (total / 1e6))
with open("./gweight.txt", "w", encoding="utf-8") as f: f.write(gpt_path)
with open("./weight.json")as f:
data=f.read()
data=json.loads(data)
data["GPT"][version]=gpt_path
with open("./weight.json","w")as f:f.write(json.dumps(data))
change_gpt_weights(gpt_path)
@@ -186,6 +257,8 @@ change_gpt_weights(gpt_path)
def get_spepc(hps, filename):
audio = load_audio(filename, int(hps.data.sampling_rate))
audio = torch.FloatTensor(audio)
maxx=audio.abs().max()
if(maxx>1):audio/=min(2,maxx)
audio_norm = audio
audio_norm = audio_norm.unsqueeze(0)
spec = spectrogram_torch(
@@ -198,20 +271,9 @@ def get_spepc(hps, filename):
)
return spec
dict_language = {
i18n("中文"): "all_zh",#全部按中文识别
i18n("英文"): "en",#全部按英文识别#######不变
i18n("日文"): "all_ja",#全部按日文识别
i18n("中英混合"): "zh",#按中英混合识别####不变
i18n("日英混合"): "ja",#按日英混合识别####不变
i18n("多语种混合"): "auto",#多语种启动切分识别语种
}
def clean_text_inf(text, language):
phones, word2ph, norm_text = clean_text(text, language)
phones = cleaned_text_to_sequence(phones)
def clean_text_inf(text, language, version):
phones, word2ph, norm_text = clean_text(text, language, version)
phones = cleaned_text_to_sequence(phones, version)
return phones, word2ph, norm_text
dtype=torch.float16 if is_half == True else torch.float32
@@ -237,50 +299,55 @@ def get_first(text):
return text
from text import chinese
def get_phones_and_bert(text,language):
if language in {"en","all_zh","all_ja"}:
def get_phones_and_bert(text,language,version):
if language in {"en", "all_zh", "all_ja", "all_ko", "all_yue"}:
language = language.replace("all_","")
if language == "en":
LangSegment.setfilters(["en"])
formattext = " ".join(tmp["text"] for tmp in LangSegment.getTexts(text))
else:
# 因无法区别中日文汉字,以用户输入为准
# 因无法区别中日韩文汉字,以用户输入为准
formattext = text
while " " in formattext:
formattext = formattext.replace(" ", " ")
if language == "zh":
if re.search(r'[A-Za-z]', formattext):
formattext = re.sub(r'[a-z]', lambda x: x.group(0).upper(), formattext)
formattext = chinese.text_normalize(formattext)
return get_phones_and_bert(formattext,"zh")
formattext = chinese.mix_text_normalize(formattext)
return get_phones_and_bert(formattext,"zh",version)
else:
phones, word2ph, norm_text = clean_text_inf(formattext, language)
bert = get_bert_feature(norm_text, word2ph).to(device)
phones, word2ph, norm_text = clean_text_inf(formattext, language, version)
bert = get_bert_feature(norm_text, word2ph).to(device)
elif language == "yue" and re.search(r'[A-Za-z]', formattext):
formattext = re.sub(r'[a-z]', lambda x: x.group(0).upper(), formattext)
formattext = chinese.mix_text_normalize(formattext)
return get_phones_and_bert(formattext,"yue",version)
else:
phones, word2ph, norm_text = clean_text_inf(formattext, language)
phones, word2ph, norm_text = clean_text_inf(formattext, language, version)
bert = torch.zeros(
(1024, len(phones)),
dtype=torch.float16 if is_half == True else torch.float32,
).to(device)
elif language in {"zh", "ja","auto"}:
elif language in {"zh", "ja", "ko", "yue", "auto", "auto_yue"}:
textlist=[]
langlist=[]
LangSegment.setfilters(["zh","ja","en","ko"])
if language == "auto":
for tmp in LangSegment.getTexts(text):
if tmp["lang"] == "ko":
langlist.append("zh")
textlist.append(tmp["text"])
else:
langlist.append(tmp["lang"])
textlist.append(tmp["text"])
langlist.append(tmp["lang"])
textlist.append(tmp["text"])
elif language == "auto_yue":
for tmp in LangSegment.getTexts(text):
if tmp["lang"] == "zh":
tmp["lang"] = "yue"
langlist.append(tmp["lang"])
textlist.append(tmp["text"])
else:
for tmp in LangSegment.getTexts(text):
if tmp["lang"] == "en":
langlist.append(tmp["lang"])
else:
# 因无法区别中日文汉字,以用户输入为准
# 因无法区别中日韩文汉字,以用户输入为准
langlist.append(language)
textlist.append(tmp["text"])
print(textlist)
@@ -290,7 +357,7 @@ def get_phones_and_bert(text,language):
norm_text_list = []
for i in range(len(textlist)):
lang = langlist[i]
phones, word2ph, norm_text = clean_text_inf(textlist[i], lang)
phones, word2ph, norm_text = clean_text_inf(textlist[i], lang, version)
bert = get_bert_inf(phones, word2ph, norm_text, lang)
phones_list.append(phones)
norm_text_list.append(norm_text)
@@ -322,13 +389,20 @@ def merge_short_text_in_array(texts, threshold):
##ref_wav_path+prompt_text+prompt_language+text(单个)+text_language+top_k+top_p+temperature
# cache_tokens={}#暂未实现清理机制
cache= {}
def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut=i18n("不切"), top_k=20, top_p=0.6, temperature=0.6, ref_free = False,speed=1,if_freeze=False):
def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut=i18n("不切"), top_k=20, top_p=0.6, temperature=0.6, ref_free = False,speed=1,if_freeze=False,inp_refs=123):
global cache
if ref_wav_path:pass
else:gr.Warning(i18n('请上传参考音频'))
if text:pass
else:gr.Warning(i18n('请填入推理文本'))
t = []
if prompt_text is None or len(prompt_text) == 0:
ref_free = True
t0 = ttime()
prompt_language = dict_language[prompt_language]
text_language = dict_language[text_language]
if not ref_free:
prompt_text = prompt_text.strip("\n")
if (prompt_text[-1] not in splits): prompt_text += "。" if prompt_language != "en" else "."
@@ -345,6 +419,7 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
with torch.no_grad():
wav16k, sr = librosa.load(ref_wav_path, sr=16000)
if (wav16k.shape[0] > 160000 or wav16k.shape[0] < 48000):
gr.Warning(i18n("参考音频在3~10秒范围外,请更换!"))
raise OSError(i18n("参考音频在3~10秒范围外,请更换!"))
wav16k = torch.from_numpy(wav16k)
zero_wav_torch = torch.from_numpy(zero_wav)
@@ -365,6 +440,7 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
prompt = prompt_semantic.unsqueeze(0).to(device)
t1 = ttime()
t.append(t1-t0)
if (how_to_cut == i18n("凑四句一切")):
text = cut1(text)
@@ -384,7 +460,7 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
texts = merge_short_text_in_array(texts, 5)
audio_opt = []
if not ref_free:
phones1,bert1,norm_text1=get_phones_and_bert(prompt_text, prompt_language)
phones1,bert1,norm_text1=get_phones_and_bert(prompt_text, prompt_language, version)
for i_text,text in enumerate(texts):
# 解决输入目标文本的空行导致报错的问题
@@ -392,7 +468,7 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
continue
if (text[-1] not in splits): text += "。" if text_language != "en" else "."
print(i18n("实际输入的目标文本(每句):"), text)
phones2,bert2,norm_text2=get_phones_and_bert(text, text_language)
phones2,bert2,norm_text2=get_phones_and_bert(text, text_language, version)
print(i18n("前端处理后的文本(每句):"), norm_text2)
if not ref_free:
bert = torch.cat([bert1, bert2], 1)
@@ -424,18 +500,26 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
pred_semantic = pred_semantic[:, -idx:].unsqueeze(0)
cache[i_text]=pred_semantic
t3 = ttime()
refer = get_spepc(hps, ref_wav_path) # .to(device)
if is_half == True:
refer = refer.half().to(device)
else:
refer = refer.to(device)
audio = (vq_model.decode(pred_semantic, torch.LongTensor(phones2).to(device).unsqueeze(0), refer,speed=speed).detach().cpu().numpy()[0, 0])
refers=[]
if(inp_refs):
for path in inp_refs:
try:
refer = get_spepc(hps, path.name).to(dtype).to(device)
refers.append(refer)
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).detach().cpu().numpy()[0, 0])
max_audio=np.abs(audio).max()#简单防止16bit爆音
if max_audio>1:audio/=max_audio
audio_opt.append(audio)
audio_opt.append(zero_wav)
t4 = ttime()
print("%.3f\t%.3f\t%.3f\t%.3f" % (t1 - t0, t2 - t1, t3 - t2, t4 - t3))
t.extend([t2 - t1,t3 - t2, t4 - t3])
t1 = ttime()
print("%.3f\t%.3f\t%.3f\t%.3f" %
(t[0], sum(t[1::3]), sum(t[2::3]), sum(t[3::3]))
)
yield hps.data.sampling_rate, (np.concatenate(audio_opt, 0) * 32768).astype(
np.int16
)
@@ -558,103 +642,115 @@ def process_text(texts):
def change_choices():
SoVITS_names, GPT_names = get_weights_names()
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"}
pretrained_sovits_name = "GPT_SoVITS/pretrained_models/s2G488k.pth"
pretrained_gpt_name = "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt"
SoVITS_weight_root = "SoVITS_weights"
GPT_weight_root = "GPT_weights"
os.makedirs(SoVITS_weight_root, exist_ok=True)
os.makedirs(GPT_weight_root, exist_ok=True)
SoVITS_weight_root=["SoVITS_weights_v2","SoVITS_weights"]
GPT_weight_root=["GPT_weights_v2","GPT_weights"]
for path in SoVITS_weight_root+GPT_weight_root:
os.makedirs(path,exist_ok=True)
def get_weights_names():
SoVITS_names = [pretrained_sovits_name]
for name in os.listdir(SoVITS_weight_root):
if name.endswith(".pth"): SoVITS_names.append("%s/%s" % (SoVITS_weight_root, name))
GPT_names = [pretrained_gpt_name]
for name in os.listdir(GPT_weight_root):
if name.endswith(".ckpt"): GPT_names.append("%s/%s" % (GPT_weight_root, name))
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()
SoVITS_names, GPT_names = get_weights_names(GPT_weight_root, SoVITS_weight_root)
def html_center(text, label='p'):
return f"""<div style="text-align: center; margin: 100; padding: 50;">
<{label} style="margin: 0; padding: 0;">{text}</{label}>
</div>"""
def html_left(text, label='p'):
return f"""<div style="text-align: left; margin: 0; padding: 0;">
<{label} style="margin: 0; padding: 0;">{text}</{label}>
</div>"""
with gr.Blocks(title="GPT-SoVITS WebUI") as app:
gr.Markdown(
value=i18n("本软件以MIT协议开源, 作者不对软件具备任何控制力, 使用软件者、传播软件导出的声音者自负全责. <br>如不认可该条款, 则不能使用或引用软件包内任何代码和文件. 详见根目录<b>LICENSE</b>.")
)
with gr.Group():
gr.Markdown(value=i18n("模型切换"))
gr.Markdown(html_center(i18n("模型切换"),'h3'))
with gr.Row():
GPT_dropdown = gr.Dropdown(label=i18n("GPT模型列表"), choices=sorted(GPT_names, key=custom_sort_key), value=gpt_path, interactive=True)
SoVITS_dropdown = gr.Dropdown(label=i18n("SoVITS模型列表"), choices=sorted(SoVITS_names, key=custom_sort_key), value=sovits_path, interactive=True)
refresh_button = gr.Button(i18n("刷新模型路径"), variant="primary")
GPT_dropdown = gr.Dropdown(label=i18n("GPT模型列表"), choices=sorted(GPT_names, key=custom_sort_key), value=gpt_path, interactive=True, scale=14)
SoVITS_dropdown = gr.Dropdown(label=i18n("SoVITS模型列表"), choices=sorted(SoVITS_names, key=custom_sort_key), value=sovits_path, 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])
SoVITS_dropdown.change(change_sovits_weights, [SoVITS_dropdown], [])
GPT_dropdown.change(change_gpt_weights, [GPT_dropdown], [])
gr.Markdown(value=i18n("*请上传并填写参考信息"))
gr.Markdown(html_center(i18n("*请上传并填写参考信息"),'h3'))
with gr.Row():
inp_ref = gr.Audio(label=i18n("请上传3~10秒内参考音频,超过会报错!"), type="filepath")
with gr.Column():
inp_ref = gr.Audio(label=i18n("请上传3~10秒内参考音频,超过会报错!"), type="filepath", scale=13)
with gr.Column(scale=13):
ref_text_free = gr.Checkbox(label=i18n("开启无参考文本模式。不填参考文本亦相当于开启。"), value=False, interactive=True, show_label=True)
gr.Markdown(i18n("使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。"))
prompt_text = gr.Textbox(label=i18n("参考音频的文本"), value="")
gr.Markdown(html_left(i18n("使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。")))
prompt_text = gr.Textbox(label=i18n("参考音频的文本"), value="", lines=3, max_lines=3)
prompt_language = gr.Dropdown(
label=i18n("参考音频的语种"), choices=[i18n("中文"), i18n("英文"), i18n("日文"), i18n("中英混合"), i18n("日英混合"), i18n("多语种混合")], value=i18n("中文")
label=i18n("参考音频的语种"), choices=list(dict_language.keys()), value=i18n("中文"), scale=14
)
gr.Markdown(value=i18n("*请填写需要合成的目标文本和语种模式"))
inp_refs = gr.File(label=i18n("可选项:通过拖拽多个文件上传多个参考音频(建议同性),平均融合他们的音色。如不填写此项,音色由左侧单个参考音频控制。如是微调模型,建议参考音频全部在微调训练集音色内,底模不用管。"),file_count="file_count",scale=13)
gr.Markdown(html_center(i18n("*请填写需要合成的目标文本和语种模式"),'h3'))
with gr.Row():
with gr.Column():
text = gr.Textbox(label=i18n("需要合成的文本"), value="")
with gr.Column(scale=13):
text = gr.Textbox(label=i18n("需要合成的文本"), value="", lines=26, max_lines=26)
with gr.Column(scale=7):
text_language = gr.Dropdown(
label=i18n("需要合成的语种"), choices=[i18n("中文"), i18n("英文"), i18n("日文"), i18n("中英混合"), i18n("日英混合"), i18n("多语种混合")], value=i18n("中文")
)
how_to_cut = gr.Radio(
label=i18n("怎么切"),
choices=[i18n("不切"), i18n("凑四句一切"), i18n("凑50字一切"), i18n("按中文句号。切"), i18n("按英文句号.切"), i18n("按标点符号切"), ],
value=i18n("凑四句一切"),
interactive=True,
)
with gr.Column():
gr.Markdown(value=i18n("gpt采样参数(无参考文本时不要太低。不懂就用默认):"))
top_k = gr.Slider(minimum=1,maximum=100,step=1,label=i18n("top_k"),value=10,interactive=True)
top_p = gr.Slider(minimum=0,maximum=1,step=0.05,label=i18n("top_p"),value=1,interactive=True)
temperature = gr.Slider(minimum=0,maximum=1,step=0.05,label=i18n("temperature"),value=1,interactive=True)
with gr.Column():
gr.Markdown(value=i18n("语速调整,高为更快"))
if_freeze=gr.Checkbox(label=i18n("是否直接对上次合成结果调整语速。防止随机性。"), value=False, interactive=True, show_label=True)
speed = gr.Slider(minimum=0.6,maximum=1.65,step=0.05,label=i18n("语速"),value=1,interactive=True)
label=i18n("需要合成的语种")+i18n(".限制范围越小判别效果越好。"), choices=list(dict_language.keys()), value=i18n("中文"), scale=1
)
how_to_cut = gr.Dropdown(
label=i18n("怎么切"),
choices=[i18n("不切"), i18n("凑四句一切"), i18n("凑50字一切"), i18n("按中文句号。切"), i18n("按英文句号.切"), i18n("按标点符号切"), ],
value=i18n("凑四句一切"),
interactive=True, scale=1
)
gr.Markdown(value=html_center(i18n("语速调整,高为更快")))
if_freeze=gr.Checkbox(label=i18n("是否直接对上次合成结果调整语速和音色。防止随机性。"), value=False, interactive=True,show_label=True, scale=1)
speed = gr.Slider(minimum=0.6,maximum=1.65,step=0.05,label=i18n("语速"),value=1,interactive=True, scale=1)
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)
top_p = gr.Slider(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)
# with gr.Column():
# gr.Markdown(value=i18n("手工调整音素。当音素框不为空时使用手工音素输入推理,无视目标文本框。"))
# phoneme=gr.Textbox(label=i18n("音素框"), value="")
# get_phoneme_button = gr.Button(i18n("目标文本转音素"), variant="primary")
inference_button = gr.Button(i18n("合成语音"), variant="primary")
output = gr.Audio(label=i18n("输出的语音"))
with gr.Row():
inference_button = gr.Button(i18n("合成语音"), variant="primary", size='lg', scale=25)
output = gr.Audio(label=i18n("输出的语音"), scale=14)
inference_button.click(
get_tts_wav,
[inp_ref, prompt_text, prompt_language, text, text_language, how_to_cut, top_k, top_p, temperature, ref_text_free,speed,if_freeze],
[inp_ref, prompt_text, prompt_language, text, text_language, how_to_cut, top_k, top_p, temperature, ref_text_free,speed,if_freeze,inp_refs],
[output],
)
SoVITS_dropdown.change(change_sovits_weights, [SoVITS_dropdown,prompt_language,text_language], [prompt_language,text_language,prompt_text,prompt_language,text,text_language])
GPT_dropdown.change(change_gpt_weights, [GPT_dropdown], [])
gr.Markdown(value=i18n("文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。"))
with gr.Row():
text_inp = gr.Textbox(label=i18n("需要合成的切分前文本"), value="")
button1 = gr.Button(i18n("凑四句一切"), variant="primary")
button2 = gr.Button(i18n("凑50字一切"), variant="primary")
button3 = gr.Button(i18n("按中文句号。切"), variant="primary")
button4 = gr.Button(i18n("按英文句号.切"), variant="primary")
button5 = gr.Button(i18n("按标点符号切"), variant="primary")
text_opt = gr.Textbox(label=i18n("切分后文本"), value="")
button1.click(cut1, [text_inp], [text_opt])
button2.click(cut2, [text_inp], [text_opt])
button3.click(cut3, [text_inp], [text_opt])
button4.click(cut4, [text_inp], [text_opt])
button5.click(cut5, [text_inp], [text_opt])
gr.Markdown(value=i18n("后续将支持转音素、手工修改音素、语音合成分步执行。"))
# gr.Markdown(value=i18n("文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。"))
# with gr.Row():
# text_inp = gr.Textbox(label=i18n("需要合成的切分前文本"), value="")
# button1 = gr.Button(i18n("凑四句一切"), variant="primary")
# button2 = gr.Button(i18n("凑50字一切"), variant="primary")
# button3 = gr.Button(i18n("按中文句号。切"), variant="primary")
# button4 = gr.Button(i18n("按英文句号.切"), variant="primary")
# button5 = gr.Button(i18n("按标点符号切"), variant="primary")
# text_opt = gr.Textbox(label=i18n("切分后文本"), value="")
# button1.click(cut1, [text_inp], [text_opt])
# button2.click(cut2, [text_inp], [text_opt])
# button3.click(cut3, [text_inp], [text_opt])
# button4.click(cut4, [text_inp], [text_opt])
# button5.click(cut5, [text_inp], [text_opt])
# gr.Markdown(html_center(i18n("后续将支持转音素、手工修改音素、语音合成分步执行。")))
if __name__ == '__main__':
app.queue(concurrency_count=511, max_size=1022).launch(
@@ -18,7 +18,7 @@ import requests
from scipy.io import wavfile
from io import BytesIO
from tools.my_utils import load_audio
version = os.environ.get('version',None)
# ZeroDivisionError fixed by Tybost (https://github.com/RVC-Boss/GPT-SoVITS/issues/79)
class TextAudioSpeakerLoader(torch.utils.data.Dataset):
"""
@@ -77,7 +77,7 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
try:
phoneme = self.phoneme_data[audiopath][0]
phoneme = phoneme.split(' ')
phoneme_ids = cleaned_text_to_sequence(phoneme)
phoneme_ids = cleaned_text_to_sequence(phoneme, version)
except Exception:
print(f"{audiopath} not in self.phoneme_data !")
skipped_phone += 1
+51 -21
View File
@@ -1,5 +1,10 @@
import warnings
warnings.filterwarnings("ignore")
import copy
import math
import os
import pdb
import torch
from torch import nn
from torch.nn import functional as F
@@ -13,7 +18,9 @@ from torch.nn.utils import weight_norm, remove_weight_norm, spectral_norm
from module.commons import init_weights, get_padding
from module.mrte_model import MRTE
from module.quantize import ResidualVectorQuantizer
from text import symbols
# from text import symbols
from text import symbols as symbols_v1
from text import symbols2 as symbols_v2
from torch.cuda.amp import autocast
import contextlib
@@ -183,6 +190,7 @@ class TextEncoder(nn.Module):
kernel_size,
p_dropout,
latent_channels=192,
version = "v2",
):
super().__init__()
self.out_channels = out_channels
@@ -193,6 +201,7 @@ class TextEncoder(nn.Module):
self.kernel_size = kernel_size
self.p_dropout = p_dropout
self.latent_channels = latent_channels
self.version = version
self.ssl_proj = nn.Conv1d(768, hidden_channels, 1)
@@ -208,6 +217,11 @@ class TextEncoder(nn.Module):
self.encoder_text = attentions.Encoder(
hidden_channels, filter_channels, n_heads, n_layers, kernel_size, p_dropout
)
if self.version == "v1":
symbols = symbols_v1.symbols
else:
symbols = symbols_v2.symbols
self.text_embedding = nn.Embedding(len(symbols), hidden_channels)
self.mrte = MRTE()
@@ -825,6 +839,7 @@ class SynthesizerTrn(nn.Module):
use_sdp=True,
semantic_frame_rate=None,
freeze_quantizer=None,
version = "v2",
**kwargs
):
super().__init__()
@@ -845,6 +860,7 @@ class SynthesizerTrn(nn.Module):
self.segment_size = segment_size
self.n_speakers = n_speakers
self.gin_channels = gin_channels
self.version = version
self.use_sdp = use_sdp
self.enc_p = TextEncoder(
@@ -855,6 +871,7 @@ class SynthesizerTrn(nn.Module):
n_layers,
kernel_size,
p_dropout,
version = version,
)
self.dec = Generator(
inter_channels,
@@ -879,9 +896,11 @@ class SynthesizerTrn(nn.Module):
inter_channels, hidden_channels, 5, 1, 4, gin_channels=gin_channels
)
self.ref_enc = modules.MelStyleEncoder(
spec_channels, style_vector_dim=gin_channels
)
# self.version=os.environ.get("version","v1")
if(self.version=="v1"):
self.ref_enc = modules.MelStyleEncoder(spec_channels, style_vector_dim=gin_channels)
else:
self.ref_enc = modules.MelStyleEncoder(704, style_vector_dim=gin_channels)
ssl_dim = 768
assert semantic_frame_rate in ["25hz", "50hz"]
@@ -893,20 +912,15 @@ class SynthesizerTrn(nn.Module):
self.quantizer = ResidualVectorQuantizer(dimension=ssl_dim, n_q=1, bins=1024)
self.freeze_quantizer = freeze_quantizer
# if freeze_quantizer:
# self.ssl_proj.requires_grad_(False)
# self.quantizer.requires_grad_(False)
#self.quantizer.eval()
# self.enc_p.text_embedding.requires_grad_(False)
# self.enc_p.encoder_text.requires_grad_(False)
# self.enc_p.mrte.requires_grad_(False)
def forward(self, ssl, y, y_lengths, text, text_lengths):
y_mask = torch.unsqueeze(commons.sequence_mask(y_lengths, y.size(2)), 1).to(
y.dtype
)
ge = self.ref_enc(y * y_mask, y_mask)
if(self.version=="v1"):
ge = self.ref_enc(y * y_mask, y_mask)
else:
ge = self.ref_enc(y[:,:704] * y_mask, y_mask)
with autocast(enabled=False):
maybe_no_grad = torch.no_grad() if self.freeze_quantizer else contextlib.nullcontext()
with maybe_no_grad:
@@ -947,7 +961,10 @@ class SynthesizerTrn(nn.Module):
y_mask = torch.unsqueeze(commons.sequence_mask(y_lengths, y.size(2)), 1).to(
y.dtype
)
ge = self.ref_enc(y * y_mask, y_mask)
if(self.version=="v1"):
ge = self.ref_enc(y * y_mask, y_mask)
else:
ge = self.ref_enc(y[:,:704] * y_mask, y_mask)
ssl = self.ssl_proj(ssl)
quantized, codes, commit_loss, _ = self.quantizer(ssl, layers=[0])
@@ -968,13 +985,26 @@ class SynthesizerTrn(nn.Module):
@torch.no_grad()
def decode(self, codes, text, refer, noise_scale=0.5,speed=1):
ge = None
if refer is not None:
refer_lengths = torch.LongTensor([refer.size(2)]).to(refer.device)
refer_mask = torch.unsqueeze(
commons.sequence_mask(refer_lengths, refer.size(2)), 1
).to(refer.dtype)
ge = self.ref_enc(refer * refer_mask, refer_mask)
def get_ge(refer):
ge = None
if refer is not None:
refer_lengths = torch.LongTensor([refer.size(2)]).to(refer.device)
refer_mask = torch.unsqueeze(
commons.sequence_mask(refer_lengths, refer.size(2)), 1
).to(refer.dtype)
if (self.version == "v1"):
ge = self.ref_enc(refer * refer_mask, refer_mask)
else:
ge = self.ref_enc(refer[:, :704] * refer_mask, refer_mask)
return ge
if(type(refer)==list):
ges=[]
for _refer in refer:
ge=get_ge(_refer)
ges.append(ge)
ge=torch.stack(ges,0).mean(0)
else:
ge=get_ge(refer)
y_lengths = torch.LongTensor([codes.size(2) * 2]).to(codes.device)
text_lengths = torch.LongTensor([text.size(-1)]).to(text.device)
@@ -10,15 +10,17 @@ all_parts = os.environ.get("all_parts")
os.environ["CUDA_VISIBLE_DEVICES"] = os.environ.get("_CUDA_VISIBLE_DEVICES")
opt_dir = os.environ.get("opt_dir")
bert_pretrained_dir = os.environ.get("bert_pretrained_dir")
is_half = eval(os.environ.get("is_half", "True"))
import torch
is_half = eval(os.environ.get("is_half", "True")) and torch.cuda.is_available()
version = os.environ.get('version', None)
import sys, numpy as np, traceback, pdb
import os.path
from glob import glob
from tqdm import tqdm
from text.cleaner import clean_text
import torch
from transformers import AutoModelForMaskedLM, AutoTokenizer
import numpy as np
from tools.my_utils import clean_path
# inp_text=sys.argv[1]
# inp_wav_dir=sys.argv[2]
@@ -53,6 +55,8 @@ if os.path.exists(txt_path) == False:
# device = "mps"
else:
device = "cpu"
if os.path.exists(bert_pretrained_dir):...
else:raise FileNotFoundError(bert_pretrained_dir)
tokenizer = AutoTokenizer.from_pretrained(bert_pretrained_dir)
bert_model = AutoModelForMaskedLM.from_pretrained(bert_pretrained_dir)
if is_half == True:
@@ -81,9 +85,11 @@ if os.path.exists(txt_path) == False:
def process(data, res):
for name, text, lan in data:
try:
name=clean_path(name)
name = os.path.basename(name)
print(name)
phones, word2ph, norm_text = clean_text(
text.replace("%", "-").replace("¥", ","), lan
text.replace("%", "-").replace("¥", ","), lan, version
)
path_bert = "%s/%s.pt" % (bert_dir, name)
if os.path.exists(path_bert) == False and lan == "zh":
@@ -112,6 +118,12 @@ if os.path.exists(txt_path) == False:
"EN": "en",
"en": "en",
"En": "en",
"KO": "ko",
"Ko": "ko",
"ko": "ko",
"yue": "yue",
"YUE": "yue",
"Yue": "yue",
}
for line in lines[int(i_part) :: int(all_parts)]:
try:
@@ -10,14 +10,15 @@ os.environ["CUDA_VISIBLE_DEVICES"]= os.environ.get("_CUDA_VISIBLE_DEVICES")
from feature_extractor import cnhubert
opt_dir= os.environ.get("opt_dir")
cnhubert.cnhubert_base_path= os.environ.get("cnhubert_base_dir")
is_half=eval(os.environ.get("is_half","True"))
import torch
is_half = eval(os.environ.get("is_half", "True")) and torch.cuda.is_available()
import pdb,traceback,numpy as np,logging
from scipy.io import wavfile
import librosa,torch
import librosa
now_dir = os.getcwd()
sys.path.append(now_dir)
from tools.my_utils import load_audio
from tools.my_utils import load_audio,clean_path
# from config import cnhubert_base_path
# cnhubert.cnhubert_base_path=cnhubert_base_path
@@ -99,6 +100,7 @@ for line in lines[int(i_part)::int(all_parts)]:
try:
# wav_name,text=line.split("\t")
wav_name, spk_name, language, text = line.split("|")
wav_name=clean_path(wav_name)
if (inp_wav_dir != "" and inp_wav_dir != None):
wav_name = os.path.basename(wav_name)
wav_path = "%s/%s"%(inp_wav_dir, wav_name)
@@ -8,7 +8,9 @@ os.environ["CUDA_VISIBLE_DEVICES"] = os.environ.get("_CUDA_VISIBLE_DEVICES")
opt_dir = os.environ.get("opt_dir")
pretrained_s2G = os.environ.get("pretrained_s2G")
s2config_path = os.environ.get("s2config_path")
is_half = eval(os.environ.get("is_half", "True"))
version=os.environ.get("version","v2")
import torch
is_half = eval(os.environ.get("is_half", "True")) and torch.cuda.is_available()
import math, traceback
import multiprocessing
import sys, pdb
@@ -19,9 +21,9 @@ from random import shuffle
import torch.multiprocessing as mp
from glob import glob
from tqdm import tqdm
import logging, librosa, utils, torch
import logging, librosa, utils
from module.models import SynthesizerTrn
from tools.my_utils import clean_path
logging.getLogger("numba").setLevel(logging.WARNING)
# from config import pretrained_s2G
@@ -32,6 +34,8 @@ logging.getLogger("numba").setLevel(logging.WARNING)
# os.environ["CUDA_VISIBLE_DEVICES"]=sys.argv[5]
# opt_dir="/data/docker/liujing04/gpt-vits/fine_tune_dataset/%s"%exp_name
if os.path.exists(pretrained_s2G):...
else:raise FileNotFoundError(pretrained_s2G)
hubert_dir = "%s/4-cnhubert" % (opt_dir)
semantic_path = "%s/6-name2semantic-%s.tsv" % (opt_dir, i_part)
@@ -49,6 +53,7 @@ if os.path.exists(semantic_path) == False:
hps.data.filter_length // 2 + 1,
hps.train.segment_size // hps.data.hop_length,
n_speakers=hps.data.n_speakers,
version=version,
**hps.model
)
if is_half == True:
@@ -86,6 +91,7 @@ if os.path.exists(semantic_path) == False:
try:
# wav_name,text=line.split("\t")
wav_name, spk_name, language, text = line.split("|")
wav_name=clean_path(wav_name)
wav_name = os.path.basename(wav_name)
# name2go(name,lines1)
name2go(wav_name, lines1)
+5 -4
View File
@@ -1,5 +1,6 @@
import warnings
warnings.filterwarnings("ignore")
import utils, os
hps = utils.get_hparams(stage=2)
os.environ["CUDA_VISIBLE_DEVICES"] = hps.train.gpu_numbers.replace("-", ",")
import torch
@@ -119,7 +120,7 @@ def run(rank, n_gpus, hps):
collate_fn=collate_fn,
batch_sampler=train_sampler,
persistent_workers=True,
prefetch_factor=16,
prefetch_factor=4,
)
# if rank == 0:
# eval_dataset = TextAudioSpeakerLoader(hps.data.validation_files, hps.data, val=True)
@@ -211,7 +212,7 @@ def run(rank, n_gpus, hps):
# traceback.print_exc()
epoch_str = 1
global_step = 0
if hps.train.pretrained_s2G != "":
if hps.train.pretrained_s2G != ""and hps.train.pretrained_s2G != None and os.path.exists(hps.train.pretrained_s2G):
if rank == 0:
logger.info("loaded pretrained %s" % hps.train.pretrained_s2G)
print(
@@ -223,7 +224,7 @@ def run(rank, n_gpus, hps):
strict=False,
)
) ##测试不加载优化器
if hps.train.pretrained_s2D != "":
if hps.train.pretrained_s2D != ""and hps.train.pretrained_s2D != None and os.path.exists(hps.train.pretrained_s2D):
if rank == 0:
logger.info("loaded pretrained %s" % hps.train.pretrained_s2D)
print(
@@ -0,0 +1,3 @@
G2PWModel
__pycache__
*.zip
+16 -4
View File
@@ -1,15 +1,27 @@
from text.symbols import *
import os
# if os.environ.get("version","v1")=="v1":
# from text.symbols import symbols
# else:
# from text.symbols2 import symbols
from text import symbols as symbols_v1
from text import symbols2 as symbols_v2
_symbol_to_id = {s: i for i, s in enumerate(symbols)}
_symbol_to_id_v1 = {s: i for i, s in enumerate(symbols_v1.symbols)}
_symbol_to_id_v2 = {s: i for i, s in enumerate(symbols_v2.symbols)}
def cleaned_text_to_sequence(cleaned_text):
def cleaned_text_to_sequence(cleaned_text, version=None):
'''Converts a string of text to a sequence of IDs corresponding to the symbols in the text.
Args:
text: string to convert to a sequence
Returns:
List of integers corresponding to the symbols in the text
'''
phones = [_symbol_to_id[symbol] for symbol in cleaned_text]
if version is None:version=os.environ.get('version', 'v2')
if version == "v1":
phones = [_symbol_to_id_v1[symbol] for symbol in cleaned_text]
else:
phones = [_symbol_to_id_v2[symbol] for symbol in cleaned_text]
return phones
+209
View File
@@ -0,0 +1,209 @@
# reference: https://huggingface.co/spaces/Naozumi0512/Bert-VITS2-Cantonese-Yue/blob/main/text/chinese.py
import sys
import re
import cn2an
from pyjyutping import jyutping
from text.symbols import punctuation
from text.zh_normalization.text_normlization import TextNormalizer
normalizer = lambda x: cn2an.transform(x, "an2cn")
INITIALS = [
"aa",
"aai",
"aak",
"aap",
"aat",
"aau",
"ai",
"au",
"ap",
"at",
"ak",
"a",
"p",
"b",
"e",
"ts",
"t",
"dz",
"d",
"kw",
"k",
"gw",
"g",
"f",
"h",
"l",
"m",
"ng",
"n",
"s",
"y",
"w",
"c",
"z",
"j",
"ong",
"on",
"ou",
"oi",
"ok",
"o",
"uk",
"ung",
]
INITIALS += ["sp", "spl", "spn", "sil"]
rep_map = {
":": ",",
";": ",",
",": ",",
"。": ".",
"!": "!",
"?": "?",
"\n": ".",
"·": ",",
"、": ",",
"...": "…",
"$": ".",
"“": "'",
"”": "'",
'"': "'",
"‘": "'",
"’": "'",
"(": "'",
")": "'",
"(": "'",
")": "'",
"《": "'",
"》": "'",
"【": "'",
"】": "'",
"[": "'",
"]": "'",
"—": "-",
"~": "-",
"~": "-",
"「": "'",
"」": "'",
}
def replace_punctuation(text):
# text = text.replace("嗯", "恩").replace("呣", "母")
pattern = re.compile("|".join(re.escape(p) for p in rep_map.keys()))
replaced_text = pattern.sub(lambda x: rep_map[x.group()], text)
replaced_text = re.sub(
r"[^\u4e00-\u9fa5" + "".join(punctuation) + r"]+", "", replaced_text
)
return replaced_text
def text_normalize(text):
tx = TextNormalizer()
sentences = tx.normalize(text)
dest_text = ""
for sentence in sentences:
dest_text += replace_punctuation(sentence)
return dest_text
punctuation_set=set(punctuation)
def jyuping_to_initials_finals_tones(jyuping_syllables):
initials_finals = []
tones = []
word2ph = []
for syllable in jyuping_syllables:
if syllable in punctuation:
initials_finals.append(syllable)
tones.append(0)
word2ph.append(1) # Add 1 for punctuation
elif syllable == "_":
initials_finals.append(syllable)
tones.append(0)
word2ph.append(1) # Add 1 for underscore
else:
try:
tone = int(syllable[-1])
syllable_without_tone = syllable[:-1]
except ValueError:
tone = 0
syllable_without_tone = syllable
for initial in INITIALS:
if syllable_without_tone.startswith(initial):
if syllable_without_tone.startswith("nga"):
initials_finals.extend(
[
syllable_without_tone[:2],
syllable_without_tone[2:] or syllable_without_tone[-1],
]
)
# tones.extend([tone, tone])
tones.extend([-1, tone])
word2ph.append(2)
else:
final = syllable_without_tone[len(initial) :] or initial[-1]
initials_finals.extend([initial, final])
# tones.extend([tone, tone])
tones.extend([-1, tone])
word2ph.append(2)
break
assert len(initials_finals) == len(tones)
###魔改为辅音+带音调的元音
phones=[]
for a,b in zip(initials_finals,tones):
if(b not in [-1,0]):###防止粤语和普通话重合开头加Y,如果是标点,不加。
todo="%s%s"%(a,b)
else:todo=a
if(todo not in punctuation_set):todo="Y%s"%todo
phones.append(todo)
# return initials_finals, tones, word2ph
return phones, word2ph
def get_jyutping(text):
jp = jyutping.convert(text)
# print(1111111,jp)
for symbol in punctuation:
jp = jp.replace(symbol, " " + symbol + " ")
jp_array = jp.split()
return jp_array
def get_bert_feature(text, word2ph):
from text import chinese_bert
return chinese_bert.get_bert_feature(text, word2ph)
def g2p(text):
# word2ph = []
jyuping = get_jyutping(text)
# print(jyuping)
# phones, tones, word2ph = jyuping_to_initials_finals_tones(jyuping)
phones, word2ph = jyuping_to_initials_finals_tones(jyuping)
# phones = ["_"] + phones + ["_"]
# tones = [0] + tones + [0]
# word2ph = [1] + word2ph + [1]
return phones, word2ph
if __name__ == "__main__":
# text = "啊!但是《原神》是由,米哈\游自主, [研发]的一款全.新开放世界.冒险游戏"
text = "佢個鋤頭太短啦。"
text = text_normalize(text)
# phones, tones, word2ph = g2p(text)
phones, word2ph = g2p(text)
# print(phones, tones, word2ph)
print(phones, word2ph)
+27
View File
@@ -47,6 +47,19 @@ def replace_punctuation(text):
replaced_text = pattern.sub(lambda x: rep_map[x.group()], text)
replaced_text = re.sub(
r"[^\u4e00-\u9fa5" + "".join(punctuation) + r"]+", "", replaced_text
)
return replaced_text
def replace_punctuation_with_en(text):
text = text.replace("嗯", "恩").replace("呣", "母")
pattern = re.compile("|".join(re.escape(p) for p in rep_map.keys()))
replaced_text = pattern.sub(lambda x: rep_map[x.group()], text)
replaced_text = re.sub(
r"[^\u4e00-\u9fa5A-Za-z" + "".join(punctuation) + r"]+", "", replaced_text
)
@@ -171,6 +184,20 @@ def text_normalize(text):
return dest_text
# 不排除英文的文本格式化
def mix_text_normalize(text):
# https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/t2s/frontend/zh_normalization
tx = TextNormalizer()
sentences = tx.normalize(text)
dest_text = ""
for sentence in sentences:
dest_text += replace_punctuation_with_en(sentence)
# 避免重复标点引起的参考泄露
dest_text = replace_consecutive_punctuation(dest_text)
return dest_text
if __name__ == "__main__":
text = "啊——但是《原神》是由,米哈\游自主,研发的一款全.新开放世界.冒险游戏"
text = "呣呣呣~就是…大人的鼹鼠党吧?"
+308
View File
@@ -0,0 +1,308 @@
import os
import pdb
import re
import cn2an
from pypinyin import lazy_pinyin, Style
from pypinyin.contrib.tone_convert import to_normal, to_finals_tone3, to_initials, to_finals
from text.symbols import punctuation
from text.tone_sandhi import ToneSandhi
from text.zh_normalization.text_normlization import TextNormalizer
normalizer = lambda x: cn2an.transform(x, "an2cn")
current_file_path = os.path.dirname(__file__)
pinyin_to_symbol_map = {
line.split("\t")[0]: line.strip().split("\t")[1]
for line in open(os.path.join(current_file_path, "opencpop-strict.txt")).readlines()
}
import jieba_fast.posseg as psg
# is_g2pw_str = os.environ.get("is_g2pw", "True")##默认开启
# is_g2pw = False#True if is_g2pw_str.lower() == 'true' else False
is_g2pw = True#True if is_g2pw_str.lower() == 'true' else False
if is_g2pw:
print("当前使用g2pw进行拼音推理")
from text.g2pw import G2PWPinyin, correct_pronunciation
parent_directory = os.path.dirname(current_file_path)
g2pw = G2PWPinyin(model_dir="GPT_SoVITS/text/G2PWModel",model_source="GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large",v_to_u=False, neutral_tone_with_five=True)
rep_map = {
":": ",",
";": ",",
",": ",",
"。": ".",
"!": "!",
"?": "?",
"\n": ".",
"·": ",",
"、": ",",
"...": "…",
"$": ".",
"/": ",",
"—": "-",
"~": "…",
"~":"…",
}
tone_modifier = ToneSandhi()
def replace_punctuation(text):
text = text.replace("嗯", "恩").replace("呣", "母")
pattern = re.compile("|".join(re.escape(p) for p in rep_map.keys()))
replaced_text = pattern.sub(lambda x: rep_map[x.group()], text)
replaced_text = re.sub(
r"[^\u4e00-\u9fa5" + "".join(punctuation) + r"]+", "", replaced_text
)
return replaced_text
def g2p(text):
pattern = r"(?<=[{0}])\s*".format("".join(punctuation))
sentences = [i for i in re.split(pattern, text) if i.strip() != ""]
phones, word2ph = _g2p(sentences)
return phones, word2ph
def _get_initials_finals(word):
initials = []
finals = []
orig_initials = lazy_pinyin(word, neutral_tone_with_five=True, style=Style.INITIALS)
orig_finals = lazy_pinyin(
word, neutral_tone_with_five=True, style=Style.FINALS_TONE3
)
for c, v in zip(orig_initials, orig_finals):
initials.append(c)
finals.append(v)
return initials, finals
must_erhua = {
"小院儿", "胡同儿", "范儿", "老汉儿", "撒欢儿", "寻老礼儿", "妥妥儿", "媳妇儿"
}
not_erhua = {
"虐儿", "为儿", "护儿", "瞒儿", "救儿", "替儿", "有儿", "一儿", "我儿", "俺儿", "妻儿",
"拐儿", "聋儿", "乞儿", "患儿", "幼儿", "孤儿", "婴儿", "婴幼儿", "连体儿", "脑瘫儿",
"流浪儿", "体弱儿", "混血儿", "蜜雪儿", "舫儿", "祖儿", "美儿", "应采儿", "可儿", "侄儿",
"孙儿", "侄孙儿", "女儿", "男儿", "红孩儿", "花儿", "虫儿", "马儿", "鸟儿", "猪儿", "猫儿",
"狗儿", "少儿"
}
def _merge_erhua(initials: list[str],
finals: list[str],
word: str,
pos: str) -> list[list[str]]:
"""
Do erhub.
"""
# fix er1
for i, phn in enumerate(finals):
if i == len(finals) - 1 and word[i] == "儿" and phn == 'er1':
finals[i] = 'er2'
# 发音
if word not in must_erhua and (word in not_erhua or
pos in {"a", "j", "nr"}):
return initials, finals
# "……" 等情况直接返回
if len(finals) != len(word):
return initials, finals
assert len(finals) == len(word)
# 与前一个字发同音
new_initials = []
new_finals = []
for i, phn in enumerate(finals):
if i == len(finals) - 1 and word[i] == "儿" and phn in {
"er2", "er5"
} and word[-2:] not in not_erhua and new_finals:
phn = "er" + new_finals[-1][-1]
new_initials.append(initials[i])
new_finals.append(phn)
return new_initials, new_finals
def _g2p(segments):
phones_list = []
word2ph = []
for seg in segments:
pinyins = []
# Replace all English words in the sentence
seg = re.sub("[a-zA-Z]+", "", seg)
seg_cut = psg.lcut(seg)
seg_cut = tone_modifier.pre_merge_for_modify(seg_cut)
initials = []
finals = []
if not is_g2pw:
for word, pos in seg_cut:
if pos == "eng":
continue
sub_initials, sub_finals = _get_initials_finals(word)
sub_finals = tone_modifier.modified_tone(word, pos, sub_finals)
# 儿化
sub_initials, sub_finals = _merge_erhua(sub_initials, sub_finals, word, pos)
initials.append(sub_initials)
finals.append(sub_finals)
# assert len(sub_initials) == len(sub_finals) == len(word)
initials = sum(initials, [])
finals = sum(finals, [])
print("pypinyin结果",initials,finals)
else:
# g2pw采用整句推理
pinyins = g2pw.lazy_pinyin(seg, neutral_tone_with_five=True, style=Style.TONE3)
pre_word_length = 0
for word, pos in seg_cut:
sub_initials = []
sub_finals = []
now_word_length = pre_word_length + len(word)
if pos == 'eng':
pre_word_length = now_word_length
continue
word_pinyins = pinyins[pre_word_length:now_word_length]
# 多音字消歧
word_pinyins = correct_pronunciation(word,word_pinyins)
for pinyin in word_pinyins:
if pinyin[0].isalpha():
sub_initials.append(to_initials(pinyin))
sub_finals.append(to_finals_tone3(pinyin,neutral_tone_with_five=True))
else:
sub_initials.append(pinyin)
sub_finals.append(pinyin)
pre_word_length = now_word_length
sub_finals = tone_modifier.modified_tone(word, pos, sub_finals)
# 儿化
sub_initials, sub_finals = _merge_erhua(sub_initials, sub_finals, word, pos)
initials.append(sub_initials)
finals.append(sub_finals)
initials = sum(initials, [])
finals = sum(finals, [])
# print("g2pw结果",initials,finals)
for c, v in zip(initials, finals):
raw_pinyin = c + v
# NOTE: post process for pypinyin outputs
# we discriminate i, ii and iii
if c == v:
assert c in punctuation
phone = [c]
word2ph.append(1)
else:
v_without_tone = v[:-1]
tone = v[-1]
pinyin = c + v_without_tone
assert tone in "12345"
if c:
# 多音节
v_rep_map = {
"uei": "ui",
"iou": "iu",
"uen": "un",
}
if v_without_tone in v_rep_map.keys():
pinyin = c + v_rep_map[v_without_tone]
else:
# 单音节
pinyin_rep_map = {
"ing": "ying",
"i": "yi",
"in": "yin",
"u": "wu",
}
if pinyin in pinyin_rep_map.keys():
pinyin = pinyin_rep_map[pinyin]
else:
single_rep_map = {
"v": "yu",
"e": "e",
"i": "y",
"u": "w",
}
if pinyin[0] in single_rep_map.keys():
pinyin = single_rep_map[pinyin[0]] + pinyin[1:]
assert pinyin in pinyin_to_symbol_map.keys(), (pinyin, seg, raw_pinyin)
new_c, new_v = pinyin_to_symbol_map[pinyin].split(" ")
new_v = new_v + tone
phone = [new_c, new_v]
word2ph.append(len(phone))
phones_list += phone
return phones_list, word2ph
def replace_punctuation_with_en(text):
text = text.replace("嗯", "恩").replace("呣", "母")
pattern = re.compile("|".join(re.escape(p) for p in rep_map.keys()))
replaced_text = pattern.sub(lambda x: rep_map[x.group()], text)
replaced_text = re.sub(
r"[^\u4e00-\u9fa5A-Za-z" + "".join(punctuation) + r"]+", "", replaced_text
)
return replaced_text
def replace_consecutive_punctuation(text):
punctuations = ''.join(re.escape(p) for p in punctuation)
pattern = f'([{punctuations}])([{punctuations}])+'
result = re.sub(pattern, r'\1', text)
return result
def text_normalize(text):
# https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/t2s/frontend/zh_normalization
tx = TextNormalizer()
sentences = tx.normalize(text)
dest_text = ""
for sentence in sentences:
dest_text += replace_punctuation(sentence)
# 避免重复标点引起的参考泄露
dest_text = replace_consecutive_punctuation(dest_text)
return dest_text
# 不排除英文的文本格式化
def mix_text_normalize(text):
# https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/t2s/frontend/zh_normalization
tx = TextNormalizer()
sentences = tx.normalize(text)
dest_text = ""
for sentence in sentences:
dest_text += replace_punctuation_with_en(sentence)
# 避免重复标点引起的参考泄露
dest_text = replace_consecutive_punctuation(dest_text)
return dest_text
if __name__ == "__main__":
text = "啊——但是《原神》是由,米哈\游自主,研发的一款全.新开放世界.冒险游戏"
text = "呣呣呣~就是…大人的鼹鼠党吧?"
text = "你好"
text = text_normalize(text)
print(g2p(text))
# # 示例用法
# text = "这是一个示例文本:,你好!这是一个测试..."
# print(g2p_paddle(text)) # 输出: 这是一个示例文本你好这是一个测试
+42 -12
View File
@@ -1,6 +1,15 @@
from text import chinese, japanese, cleaned_text_to_sequence, symbols, english
from text import cleaned_text_to_sequence
import os
# if os.environ.get("version","v1")=="v1":
# from text import chinese
# from text.symbols import symbols
# else:
# from text import chinese2 as chinese
# from text.symbols2 import symbols
from text import symbols as symbols_v1
from text import symbols2 as symbols_v2
language_module_map = {"zh": chinese, "ja": japanese, "en": english}
special = [
# ("%", "zh", "SP"),
("¥", "zh", "SP2"),
@@ -9,16 +18,27 @@ special = [
]
def clean_text(text, language):
def clean_text(text, language, version=None):
if version is None:version=os.environ.get('version', 'v2')
if version == "v1":
symbols = symbols_v1.symbols
language_module_map = {"zh": "chinese", "ja": "japanese", "en": "english"}
else:
symbols = symbols_v2.symbols
language_module_map = {"zh": "chinese2", "ja": "japanese", "en": "english", "ko": "korean","yue":"cantonese"}
if(language not in language_module_map):
language="en"
text=" "
for special_s, special_l, target_symbol in special:
if special_s in text and language == special_l:
return clean_special(text, language, special_s, target_symbol)
language_module = language_module_map[language]
norm_text = language_module.text_normalize(text)
if language == "zh":
return clean_special(text, language, special_s, target_symbol, version)
language_module = __import__("text."+language_module_map[language],fromlist=[language_module_map[language]])
if hasattr(language_module,"text_normalize"):
norm_text = language_module.text_normalize(text)
else:
norm_text=text
if language == "zh" or language=="yue":##########
phones, word2ph = language_module.g2p(norm_text)
assert len(phones) == sum(word2ph)
assert len(norm_text) == len(word2ph)
@@ -32,16 +52,24 @@ def clean_text(text, language):
word2ph = None
for ph in phones:
assert ph in symbols
phones = ['UNK' if ph not in symbols else ph for ph in phones]
return phones, word2ph, norm_text
def clean_special(text, language, special_s, target_symbol):
def clean_special(text, language, special_s, target_symbol, version=None):
if version is None:version=os.environ.get('version', 'v2')
if version == "v1":
symbols = symbols_v1.symbols
language_module_map = {"zh": "chinese", "ja": "japanese", "en": "english"}
else:
symbols = symbols_v2.symbols
language_module_map = {"zh": "chinese2", "ja": "japanese", "en": "english", "ko": "korean","yue":"cantonese"}
"""
特殊静音段sp符号处理
"""
text = text.replace(special_s, ",")
language_module = language_module_map[language]
language_module = __import__("text."+language_module_map[language],fromlist=[language_module_map[language]])
norm_text = language_module.text_normalize(text)
phones = language_module.g2p(norm_text)
new_ph = []
@@ -54,9 +82,11 @@ def clean_special(text, language, special_s, target_symbol):
return new_ph, phones[1], norm_text
def text_to_sequence(text, language):
def text_to_sequence(text, language, version=None):
version = os.environ.get('version',version)
if version is None:version='v2'
phones = clean_text(text)
return cleaned_text_to_sequence(phones)
return cleaned_text_to_sequence(phones, version)
if __name__ == "__main__":
+1 -1
View File
@@ -6,7 +6,7 @@ from g2p_en import G2p
from text.symbols import punctuation
from text import symbols
from text.symbols2 import symbols
import unicodedata
from builtins import str as unicode
@@ -0,0 +1 @@
from text.g2pw.g2pw import *
@@ -0,0 +1,166 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Credits
This code is modified from https://github.com/GitYCC/g2pW
"""
from typing import Dict
from typing import List
from typing import Tuple
import numpy as np
from .utils import tokenize_and_map
ANCHOR_CHAR = '▁'
def prepare_onnx_input(tokenizer,
labels: List[str],
char2phonemes: Dict[str, List[int]],
chars: List[str],
texts: List[str],
query_ids: List[int],
use_mask: bool=False,
window_size: int=None,
max_len: int=512) -> Dict[str, np.array]:
if window_size is not None:
truncated_texts, truncated_query_ids = _truncate_texts(
window_size=window_size, texts=texts, query_ids=query_ids)
input_ids = []
token_type_ids = []
attention_masks = []
phoneme_masks = []
char_ids = []
position_ids = []
for idx in range(len(texts)):
text = (truncated_texts if window_size else texts)[idx].lower()
query_id = (truncated_query_ids if window_size else query_ids)[idx]
try:
tokens, text2token, token2text = tokenize_and_map(
tokenizer=tokenizer, text=text)
except Exception:
print(f'warning: text "{text}" is invalid')
return {}
text, query_id, tokens, text2token, token2text = _truncate(
max_len=max_len,
text=text,
query_id=query_id,
tokens=tokens,
text2token=text2token,
token2text=token2text)
processed_tokens = ['[CLS]'] + tokens + ['[SEP]']
input_id = list(
np.array(tokenizer.convert_tokens_to_ids(processed_tokens)))
token_type_id = list(np.zeros((len(processed_tokens), ), dtype=int))
attention_mask = list(np.ones((len(processed_tokens), ), dtype=int))
query_char = text[query_id]
phoneme_mask = [1 if i in char2phonemes[query_char] else 0 for i in range(len(labels))] \
if use_mask else [1] * len(labels)
char_id = chars.index(query_char)
position_id = text2token[
query_id] + 1 # [CLS] token locate at first place
input_ids.append(input_id)
token_type_ids.append(token_type_id)
attention_masks.append(attention_mask)
phoneme_masks.append(phoneme_mask)
char_ids.append(char_id)
position_ids.append(position_id)
outputs = {
'input_ids': np.array(input_ids).astype(np.int64),
'token_type_ids': np.array(token_type_ids).astype(np.int64),
'attention_masks': np.array(attention_masks).astype(np.int64),
'phoneme_masks': np.array(phoneme_masks).astype(np.float32),
'char_ids': np.array(char_ids).astype(np.int64),
'position_ids': np.array(position_ids).astype(np.int64),
}
return outputs
def _truncate_texts(window_size: int, texts: List[str],
query_ids: List[int]) -> Tuple[List[str], List[int]]:
truncated_texts = []
truncated_query_ids = []
for text, query_id in zip(texts, query_ids):
start = max(0, query_id - window_size // 2)
end = min(len(text), query_id + window_size // 2)
truncated_text = text[start:end]
truncated_texts.append(truncated_text)
truncated_query_id = query_id - start
truncated_query_ids.append(truncated_query_id)
return truncated_texts, truncated_query_ids
def _truncate(max_len: int,
text: str,
query_id: int,
tokens: List[str],
text2token: List[int],
token2text: List[Tuple[int]]):
truncate_len = max_len - 2
if len(tokens) <= truncate_len:
return (text, query_id, tokens, text2token, token2text)
token_position = text2token[query_id]
token_start = token_position - truncate_len // 2
token_end = token_start + truncate_len
font_exceed_dist = -token_start
back_exceed_dist = token_end - len(tokens)
if font_exceed_dist > 0:
token_start += font_exceed_dist
token_end += font_exceed_dist
elif back_exceed_dist > 0:
token_start -= back_exceed_dist
token_end -= back_exceed_dist
start = token2text[token_start][0]
end = token2text[token_end - 1][1]
return (text[start:end], query_id - start, tokens[token_start:token_end], [
i - token_start if i is not None else None
for i in text2token[start:end]
], [(s - start, e - start) for s, e in token2text[token_start:token_end]])
def get_phoneme_labels(polyphonic_chars: List[List[str]]
) -> Tuple[List[str], Dict[str, List[int]]]:
labels = sorted(list(set([phoneme for char, phoneme in polyphonic_chars])))
char2phonemes = {}
for char, phoneme in polyphonic_chars:
if char not in char2phonemes:
char2phonemes[char] = []
char2phonemes[char].append(labels.index(phoneme))
return labels, char2phonemes
def get_char_phoneme_labels(polyphonic_chars: List[List[str]]
) -> Tuple[List[str], Dict[str, List[int]]]:
labels = sorted(
list(set([f'{char} {phoneme}' for char, phoneme in polyphonic_chars])))
char2phonemes = {}
for char, phoneme in polyphonic_chars:
if char not in char2phonemes:
char2phonemes[char] = []
char2phonemes[char].append(labels.index(f'{char} {phoneme}'))
return labels, char2phonemes
+154
View File
@@ -0,0 +1,154 @@
# This code is modified from https://github.com/mozillazg/pypinyin-g2pW
import pickle
import os
from pypinyin.constants import RE_HANS
from pypinyin.core import Pinyin, Style
from pypinyin.seg.simpleseg import simple_seg
from pypinyin.converter import UltimateConverter
from pypinyin.contrib.tone_convert import to_tone
from .onnx_api import G2PWOnnxConverter
current_file_path = os.path.dirname(__file__)
CACHE_PATH = os.path.join(current_file_path, "polyphonic.pickle")
PP_DICT_PATH = os.path.join(current_file_path, "polyphonic.rep")
PP_FIX_DICT_PATH = os.path.join(current_file_path, "polyphonic-fix.rep")
class G2PWPinyin(Pinyin):
def __init__(self, model_dir='G2PWModel/', model_source=None,
enable_non_tradional_chinese=True,
v_to_u=False, neutral_tone_with_five=False, tone_sandhi=False, **kwargs):
self._g2pw = G2PWOnnxConverter(
model_dir=model_dir,
style='pinyin',
model_source=model_source,
enable_non_tradional_chinese=enable_non_tradional_chinese,
)
self._converter = Converter(
self._g2pw, v_to_u=v_to_u,
neutral_tone_with_five=neutral_tone_with_five,
tone_sandhi=tone_sandhi,
)
def get_seg(self, **kwargs):
return simple_seg
class Converter(UltimateConverter):
def __init__(self, g2pw_instance, v_to_u=False,
neutral_tone_with_five=False,
tone_sandhi=False, **kwargs):
super(Converter, self).__init__(
v_to_u=v_to_u,
neutral_tone_with_five=neutral_tone_with_five,
tone_sandhi=tone_sandhi, **kwargs)
self._g2pw = g2pw_instance
def convert(self, words, style, heteronym, errors, strict, **kwargs):
pys = []
if RE_HANS.match(words):
pys = self._to_pinyin(words, style=style, heteronym=heteronym,
errors=errors, strict=strict)
post_data = self.post_pinyin(words, heteronym, pys)
if post_data is not None:
pys = post_data
pys = self.convert_styles(
pys, words, style, heteronym, errors, strict)
else:
py = self.handle_nopinyin(words, style=style, errors=errors,
heteronym=heteronym, strict=strict)
if py:
pys.extend(py)
return _remove_dup_and_empty(pys)
def _to_pinyin(self, han, style, heteronym, errors, strict, **kwargs):
pinyins = []
g2pw_pinyin = self._g2pw(han)
if not g2pw_pinyin: # g2pw 不支持的汉字改为使用 pypinyin 原有逻辑
return super(Converter, self).convert(
han, Style.TONE, heteronym, errors, strict, **kwargs)
for i, item in enumerate(g2pw_pinyin[0]):
if item is None: # g2pw 不支持的汉字改为使用 pypinyin 原有逻辑
py = super(Converter, self).convert(
han[i], Style.TONE, heteronym, errors, strict, **kwargs)
pinyins.extend(py)
else:
pinyins.append([to_tone(item)])
return pinyins
def _remove_dup_items(lst, remove_empty=False):
new_lst = []
for item in lst:
if remove_empty and not item:
continue
if item not in new_lst:
new_lst.append(item)
return new_lst
def _remove_dup_and_empty(lst_list):
new_lst_list = []
for lst in lst_list:
lst = _remove_dup_items(lst, remove_empty=True)
if lst:
new_lst_list.append(lst)
else:
new_lst_list.append([''])
return new_lst_list
def cache_dict(polyphonic_dict, file_path):
with open(file_path, "wb") as pickle_file:
pickle.dump(polyphonic_dict, pickle_file)
def get_dict():
if os.path.exists(CACHE_PATH):
with open(CACHE_PATH, "rb") as pickle_file:
polyphonic_dict = pickle.load(pickle_file)
else:
polyphonic_dict = read_dict()
cache_dict(polyphonic_dict, CACHE_PATH)
return polyphonic_dict
def read_dict():
polyphonic_dict = {}
with open(PP_DICT_PATH) as f:
line = f.readline()
while line:
key, value_str = line.split(':')
value = eval(value_str.strip())
polyphonic_dict[key.strip()] = value
line = f.readline()
with open(PP_FIX_DICT_PATH) as f:
line = f.readline()
while line:
key, value_str = line.split(':')
value = eval(value_str.strip())
polyphonic_dict[key.strip()] = value
line = f.readline()
return polyphonic_dict
def correct_pronunciation(word,word_pinyins):
if word in pp_dict:
word_pinyins = pp_dict[word]
return word_pinyins
pp_dict = get_dict()
@@ -0,0 +1,241 @@
# This code is modified from https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/t2s/frontend/g2pw
# This code is modified from https://github.com/GitYCC/g2pW
import warnings
warnings.filterwarnings("ignore")
import json
import os
import zipfile,requests
from typing import Any
from typing import Dict
from typing import List
from typing import Tuple
import numpy as np
import onnxruntime
onnxruntime.set_default_logger_severity(3)
from opencc import OpenCC
from transformers import AutoTokenizer
from pypinyin import pinyin
from pypinyin import Style
from .dataset import get_char_phoneme_labels
from .dataset import get_phoneme_labels
from .dataset import prepare_onnx_input
from .utils import load_config
from ..zh_normalization.char_convert import tranditional_to_simplified
model_version = '1.1'
def predict(session, onnx_input: Dict[str, Any],
labels: List[str]) -> Tuple[List[str], List[float]]:
all_preds = []
all_confidences = []
probs = session.run([], {
"input_ids": onnx_input['input_ids'],
"token_type_ids": onnx_input['token_type_ids'],
"attention_mask": onnx_input['attention_masks'],
"phoneme_mask": onnx_input['phoneme_masks'],
"char_ids": onnx_input['char_ids'],
"position_ids": onnx_input['position_ids']
})[0]
preds = np.argmax(probs, axis=1).tolist()
max_probs = []
for index, arr in zip(preds, probs.tolist()):
max_probs.append(arr[index])
all_preds += [labels[pred] for pred in preds]
all_confidences += max_probs
return all_preds, all_confidences
def download_and_decompress(model_dir: str='G2PWModel/'):
if not os.path.exists(model_dir):
parent_directory = os.path.dirname(model_dir)
zip_dir = os.path.join(parent_directory,"G2PWModel_1.1.zip")
extract_dir = os.path.join(parent_directory,"G2PWModel_1.1")
extract_dir_new = os.path.join(parent_directory,"G2PWModel")
print("Downloading g2pw model...")
modelscope_url = "https://paddlespeech.bj.bcebos.com/Parakeet/released_models/g2p/G2PWModel_1.1.zip"
with requests.get(modelscope_url, stream=True) as r:
r.raise_for_status()
with open(zip_dir, 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
print("Extracting g2pw model...")
with zipfile.ZipFile(zip_dir, "r") as zip_ref:
zip_ref.extractall(parent_directory)
os.rename(extract_dir, extract_dir_new)
return model_dir
class G2PWOnnxConverter:
def __init__(self,
model_dir: str='G2PWModel/',
style: str='bopomofo',
model_source: str=None,
enable_non_tradional_chinese: bool=False):
uncompress_path = download_and_decompress(model_dir)
sess_options = onnxruntime.SessionOptions()
sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_ALL
sess_options.execution_mode = onnxruntime.ExecutionMode.ORT_SEQUENTIAL
sess_options.intra_op_num_threads = 2
self.session_g2pW = onnxruntime.InferenceSession(
os.path.join(uncompress_path, 'g2pW.onnx'),
sess_options=sess_options, providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
# sess_options=sess_options)
self.config = load_config(
config_path=os.path.join(uncompress_path, 'config.py'),
use_default=True)
self.model_source = model_source if model_source else self.config.model_source
self.enable_opencc = enable_non_tradional_chinese
self.tokenizer = AutoTokenizer.from_pretrained(self.model_source)
polyphonic_chars_path = os.path.join(uncompress_path,
'POLYPHONIC_CHARS.txt')
monophonic_chars_path = os.path.join(uncompress_path,
'MONOPHONIC_CHARS.txt')
self.polyphonic_chars = [
line.split('\t')
for line in open(polyphonic_chars_path, encoding='utf-8').read()
.strip().split('\n')
]
self.non_polyphonic = {
'一', '不', '和', '咋', '嗲', '剖', '差', '攢', '倒', '難', '奔', '勁', '拗',
'肖', '瘙', '誒', '泊', '听', '噢'
}
self.non_monophonic = {'似', '攢'}
self.monophonic_chars = [
line.split('\t')
for line in open(monophonic_chars_path, encoding='utf-8').read()
.strip().split('\n')
]
self.labels, self.char2phonemes = get_char_phoneme_labels(
polyphonic_chars=self.polyphonic_chars
) if self.config.use_char_phoneme else get_phoneme_labels(
polyphonic_chars=self.polyphonic_chars)
self.chars = sorted(list(self.char2phonemes.keys()))
self.polyphonic_chars_new = set(self.chars)
for char in self.non_polyphonic:
if char in self.polyphonic_chars_new:
self.polyphonic_chars_new.remove(char)
self.monophonic_chars_dict = {
char: phoneme
for char, phoneme in self.monophonic_chars
}
for char in self.non_monophonic:
if char in self.monophonic_chars_dict:
self.monophonic_chars_dict.pop(char)
self.pos_tags = [
'UNK', 'A', 'C', 'D', 'I', 'N', 'P', 'T', 'V', 'DE', 'SHI'
]
with open(
os.path.join(uncompress_path,
'bopomofo_to_pinyin_wo_tune_dict.json'),
'r',
encoding='utf-8') as fr:
self.bopomofo_convert_dict = json.load(fr)
self.style_convert_func = {
'bopomofo': lambda x: x,
'pinyin': self._convert_bopomofo_to_pinyin,
}[style]
with open(
os.path.join(uncompress_path, 'char_bopomofo_dict.json'),
'r',
encoding='utf-8') as fr:
self.char_bopomofo_dict = json.load(fr)
if self.enable_opencc:
self.cc = OpenCC('s2tw')
def _convert_bopomofo_to_pinyin(self, bopomofo: str) -> str:
tone = bopomofo[-1]
assert tone in '12345'
component = self.bopomofo_convert_dict.get(bopomofo[:-1])
if component:
return component + tone
else:
print(f'Warning: "{bopomofo}" cannot convert to pinyin')
return None
def __call__(self, sentences: List[str]) -> List[List[str]]:
if isinstance(sentences, str):
sentences = [sentences]
if self.enable_opencc:
translated_sentences = []
for sent in sentences:
translated_sent = self.cc.convert(sent)
assert len(translated_sent) == len(sent)
translated_sentences.append(translated_sent)
sentences = translated_sentences
texts, query_ids, sent_ids, partial_results = self._prepare_data(
sentences=sentences)
if len(texts) == 0:
# sentences no polyphonic words
return partial_results
onnx_input = prepare_onnx_input(
tokenizer=self.tokenizer,
labels=self.labels,
char2phonemes=self.char2phonemes,
chars=self.chars,
texts=texts,
query_ids=query_ids,
use_mask=self.config.use_mask,
window_size=None)
preds, confidences = predict(
session=self.session_g2pW,
onnx_input=onnx_input,
labels=self.labels)
if self.config.use_char_phoneme:
preds = [pred.split(' ')[1] for pred in preds]
results = partial_results
for sent_id, query_id, pred in zip(sent_ids, query_ids, preds):
results[sent_id][query_id] = self.style_convert_func(pred)
return results
def _prepare_data(
self, sentences: List[str]
) -> Tuple[List[str], List[int], List[int], List[List[str]]]:
texts, query_ids, sent_ids, partial_results = [], [], [], []
for sent_id, sent in enumerate(sentences):
# pypinyin works well for Simplified Chinese than Traditional Chinese
sent_s = tranditional_to_simplified(sent)
pypinyin_result = pinyin(
sent_s, neutral_tone_with_five=True, style=Style.TONE3)
partial_result = [None] * len(sent)
for i, char in enumerate(sent):
if char in self.polyphonic_chars_new:
texts.append(sent)
query_ids.append(i)
sent_ids.append(sent_id)
elif char in self.monophonic_chars_dict:
partial_result[i] = self.style_convert_func(
self.monophonic_chars_dict[char])
elif char in self.char_bopomofo_dict:
partial_result[i] = pypinyin_result[i][0]
# partial_result[i] = self.style_convert_func(self.char_bopomofo_dict[char][0])
else:
partial_result[i] = pypinyin_result[i][0]
partial_results.append(partial_result)
return texts, query_ids, sent_ids, partial_results
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,53 @@
湖泊: ['hu2','po1']
地壳: ['di4','qiao4']
柏树: ['bai3','shu4']
曝光: ['bao4','guang1']
弹力: ['tan2','li4']
字帖: ['zi4','tie4']
口吃: ['kou3','chi1']
包扎: ['bao1','za1']
哪吒: ['ne2','zha1']
说服: ['shuo1','fu2']
识字: ['shi2','zi4']
骨头: ['gu3','tou5']
对称: ['dui4','chen4']
口供: ['kou3','gong4']
抹布: ['ma1','bu4']
露背: ['lu4','bei4']
圈养: ['juan4', 'yang3']
眼眶: ['yan3', 'kuang4']
品行: ['pin3','xing2']
颤抖: ['chan4','dou3']
差不多: ['cha4','bu5','duo1']
鸭绿江: ['ya1','lu4','jiang1']
撒切尔: ['sa4','qie4','er3']
比比皆是: ['bi3','bi3','jie1','shi4']
身无长物: ['shen1','wu2','chang2','wu4']
手里: ['shou2','li3']
关卡: ['guan1','qia3']
怀揣: ['huai2','chuai1']
挑剔: ['tiao1','ti4']
供称: ['gong4','cheng1']
作坊: ['zuo1', 'fang5']
中医: ['zhong1','yi1']
嚷嚷: ['rang1','rang5']
商厦: ['shang1','sha4']
大厦: ['da4','sha4']
刹车: ['sha1','che1']
嘚瑟: ['de4','se5']
朝鲜: ['chao2','xian3']
阿房宫: ['e1','pang2','gong1']
阿胶: ['e1','jiao1']
咖喱: ['ga1','li5']
时分: ['shi2','fen1']
蚌埠: ['beng4','bu4']
驯服: ['xun4','fu2']
幸免于难: ['xing4','mian3','yu2','nan4']
恶行: ['e4','xing2']
唉: ['ai4']
扎实: ['zha1','shi2']
干将: ['gan4','jiang4']
陈威行: ['chen2', 'wei1', 'hang2']
郭晟: ['guo1', 'sheng4']
中标: ['zhong4', 'biao1']
抗住: ['kang2', 'zhu4']
@@ -0,0 +1,145 @@
# Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Credits
This code is modified from https://github.com/GitYCC/g2pW
"""
import os
import re
def wordize_and_map(text: str):
words = []
index_map_from_text_to_word = []
index_map_from_word_to_text = []
while len(text) > 0:
match_space = re.match(r'^ +', text)
if match_space:
space_str = match_space.group(0)
index_map_from_text_to_word += [None] * len(space_str)
text = text[len(space_str):]
continue
match_en = re.match(r'^[a-zA-Z0-9]+', text)
if match_en:
en_word = match_en.group(0)
word_start_pos = len(index_map_from_text_to_word)
word_end_pos = word_start_pos + len(en_word)
index_map_from_word_to_text.append((word_start_pos, word_end_pos))
index_map_from_text_to_word += [len(words)] * len(en_word)
words.append(en_word)
text = text[len(en_word):]
else:
word_start_pos = len(index_map_from_text_to_word)
word_end_pos = word_start_pos + 1
index_map_from_word_to_text.append((word_start_pos, word_end_pos))
index_map_from_text_to_word += [len(words)]
words.append(text[0])
text = text[1:]
return words, index_map_from_text_to_word, index_map_from_word_to_text
def tokenize_and_map(tokenizer, text: str):
words, text2word, word2text = wordize_and_map(text=text)
tokens = []
index_map_from_token_to_text = []
for word, (word_start, word_end) in zip(words, word2text):
word_tokens = tokenizer.tokenize(word)
if len(word_tokens) == 0 or word_tokens == ['[UNK]']:
index_map_from_token_to_text.append((word_start, word_end))
tokens.append('[UNK]')
else:
current_word_start = word_start
for word_token in word_tokens:
word_token_len = len(re.sub(r'^##', '', word_token))
index_map_from_token_to_text.append(
(current_word_start, current_word_start + word_token_len))
current_word_start = current_word_start + word_token_len
tokens.append(word_token)
index_map_from_text_to_token = text2word
for i, (token_start, token_end) in enumerate(index_map_from_token_to_text):
for token_pos in range(token_start, token_end):
index_map_from_text_to_token[token_pos] = i
return tokens, index_map_from_text_to_token, index_map_from_token_to_text
def _load_config(config_path: os.PathLike):
import importlib.util
spec = importlib.util.spec_from_file_location('__init__', config_path)
config = importlib.util.module_from_spec(spec)
spec.loader.exec_module(config)
return config
default_config_dict = {
'manual_seed': 1313,
'model_source': 'bert-base-chinese',
'window_size': 32,
'num_workers': 2,
'use_mask': True,
'use_char_phoneme': False,
'use_conditional': True,
'param_conditional': {
'affect_location': 'softmax',
'bias': True,
'char-linear': True,
'pos-linear': False,
'char+pos-second': True,
'char+pos-second_lowrank': False,
'lowrank_size': 0,
'char+pos-second_fm': False,
'fm_size': 0,
'fix_mode': None,
'count_json': 'train.count.json'
},
'lr': 5e-5,
'val_interval': 200,
'num_iter': 10000,
'use_focal': False,
'param_focal': {
'alpha': 0.0,
'gamma': 0.7
},
'use_pos': True,
'param_pos ': {
'weight': 0.1,
'pos_joint_training': True,
'train_pos_path': 'train.pos',
'valid_pos_path': 'dev.pos',
'test_pos_path': 'test.pos'
}
}
def load_config(config_path: os.PathLike, use_default: bool=False):
config = _load_config(config_path)
if use_default:
for attr, val in default_config_dict.items():
if not hasattr(config, attr):
setattr(config, attr, val)
elif isinstance(val, dict):
d = getattr(config, attr)
for dict_k, dict_v in val.items():
if dict_k not in d:
d[dict_k] = dict_v
return config
+7 -8
View File
@@ -4,8 +4,6 @@ import sys
import pyopenjtalk
from text import symbols
from text.symbols import punctuation
# Regular expression matching Japanese without punctuation marks:
_japanese_characters = re.compile(
@@ -57,12 +55,13 @@ def post_replace_ph(ph):
"、": ",",
"...": "…",
}
if ph in rep_map.keys():
ph = rep_map[ph]
if ph in symbols:
return ph
if ph not in symbols:
ph = "UNK"
# if ph in symbols:
# return ph
# if ph not in symbols:
# ph = "UNK"
return ph
@@ -190,7 +189,7 @@ def _numeric_feature_by_regex(regex, s):
return -50
return int(match.group(1))
def g2p(norm_text, with_prosody=False):
def g2p(norm_text, with_prosody=True):
phones = preprocess_jap(norm_text, with_prosody)
phones = [post_replace_ph(i) for i in phones]
# todo: implement tones and word2ph
@@ -199,4 +198,4 @@ def g2p(norm_text, with_prosody=False):
if __name__ == "__main__":
phones = g2p("こんにちは, hello, AKITOです,よろしくお願いしますね!")
print(phones)
print(phones)
+265
View File
@@ -0,0 +1,265 @@
# reference: https://github.com/ORI-Muchim/MB-iSTFT-VITS-Korean/blob/main/text/korean.py
import re
from jamo import h2j, j2hcj
import ko_pron
from g2pk2 import G2p
from text.symbols2 import symbols
# This is a list of Korean classifiers preceded by pure Korean numerals.
_korean_classifiers = '군데 권 개 그루 닢 대 두 마리 모 모금 뭇 발 발짝 방 번 벌 보루 살 수 술 시 쌈 움큼 정 짝 채 척 첩 축 켤레 톨 통'
# List of (hangul, hangul divided) pairs:
_hangul_divided = [(re.compile('%s' % x[0]), x[1]) for x in [
# ('ㄳ', 'ㄱㅅ'), # g2pk2, A Syllable-ending Rule
# ('ㄵ', 'ㄴㅈ'),
# ('ㄶ', 'ㄴㅎ'),
# ('ㄺ', 'ㄹㄱ'),
# ('ㄻ', 'ㄹㅁ'),
# ('ㄼ', 'ㄹㅂ'),
# ('ㄽ', 'ㄹㅅ'),
# ('ㄾ', 'ㄹㅌ'),
# ('ㄿ', 'ㄹㅍ'),
# ('ㅀ', 'ㄹㅎ'),
# ('ㅄ', 'ㅂㅅ'),
('ㅘ', 'ㅗㅏ'),
('ㅙ', 'ㅗㅐ'),
('ㅚ', 'ㅗㅣ'),
('ㅝ', 'ㅜㅓ'),
('ㅞ', 'ㅜㅔ'),
('ㅟ', 'ㅜㅣ'),
('ㅢ', 'ㅡㅣ'),
('ㅑ', 'ㅣㅏ'),
('ㅒ', 'ㅣㅐ'),
('ㅕ', 'ㅣㅓ'),
('ㅖ', 'ㅣㅔ'),
('ㅛ', 'ㅣㅗ'),
('ㅠ', 'ㅣㅜ')
]]
# List of (Latin alphabet, hangul) pairs:
_latin_to_hangul = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [
('a', '에이'),
('b', '비'),
('c', '시'),
('d', '디'),
('e', '이'),
('f', '에프'),
('g', '지'),
('h', '에이치'),
('i', '아이'),
('j', '제이'),
('k', '케이'),
('l', '엘'),
('m', '엠'),
('n', '엔'),
('o', '오'),
('p', '피'),
('q', '큐'),
('r', '아르'),
('s', '에스'),
('t', '티'),
('u', '유'),
('v', '브이'),
('w', '더블유'),
('x', '엑스'),
('y', '와이'),
('z', '제트')
]]
# List of (ipa, lazy ipa) pairs:
_ipa_to_lazy_ipa = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [
('t͡ɕ','ʧ'),
('d͡ʑ','ʥ'),
('ɲ','n^'),
('ɕ','ʃ'),
('ʷ','w'),
('ɭ','l`'),
('ʎ','ɾ'),
('ɣ','ŋ'),
('ɰ','ɯ'),
('ʝ','j'),
('ʌ','ə'),
('ɡ','g'),
('\u031a','#'),
('\u0348','='),
('\u031e',''),
('\u0320',''),
('\u0339','')
]]
def fix_g2pk2_error(text):
new_text = ""
i = 0
while i < len(text) - 4:
if (text[i:i+3] == 'ㅇㅡㄹ' or text[i:i+3] == 'ㄹㅡㄹ') and text[i+3] == ' ' and text[i+4] == 'ㄹ':
new_text += text[i:i+3] + ' ' + 'ㄴ'
i += 5
else:
new_text += text[i]
i += 1
new_text += text[i:]
return new_text
def latin_to_hangul(text):
for regex, replacement in _latin_to_hangul:
text = re.sub(regex, replacement, text)
return text
def divide_hangul(text):
text = j2hcj(h2j(text))
for regex, replacement in _hangul_divided:
text = re.sub(regex, replacement, text)
return text
def hangul_number(num, sino=True):
'''Reference https://github.com/Kyubyong/g2pK'''
num = re.sub(',', '', num)
if num == '0':
return '영'
if not sino and num == '20':
return '스무'
digits = '123456789'
names = '일이삼사오육칠팔구'
digit2name = {d: n for d, n in zip(digits, names)}
modifiers = '한 두 세 네 다섯 여섯 일곱 여덟 아홉'
decimals = '열 스물 서른 마흔 쉰 예순 일흔 여든 아흔'
digit2mod = {d: mod for d, mod in zip(digits, modifiers.split())}
digit2dec = {d: dec for d, dec in zip(digits, decimals.split())}
spelledout = []
for i, digit in enumerate(num):
i = len(num) - i - 1
if sino:
if i == 0:
name = digit2name.get(digit, '')
elif i == 1:
name = digit2name.get(digit, '') + '십'
name = name.replace('일십', '십')
else:
if i == 0:
name = digit2mod.get(digit, '')
elif i == 1:
name = digit2dec.get(digit, '')
if digit == '0':
if i % 4 == 0:
last_three = spelledout[-min(3, len(spelledout)):]
if ''.join(last_three) == '':
spelledout.append('')
continue
else:
spelledout.append('')
continue
if i == 2:
name = digit2name.get(digit, '') + '백'
name = name.replace('일백', '백')
elif i == 3:
name = digit2name.get(digit, '') + '천'
name = name.replace('일천', '천')
elif i == 4:
name = digit2name.get(digit, '') + '만'
name = name.replace('일만', '만')
elif i == 5:
name = digit2name.get(digit, '') + '십'
name = name.replace('일십', '십')
elif i == 6:
name = digit2name.get(digit, '') + '백'
name = name.replace('일백', '백')
elif i == 7:
name = digit2name.get(digit, '') + '천'
name = name.replace('일천', '천')
elif i == 8:
name = digit2name.get(digit, '') + '억'
elif i == 9:
name = digit2name.get(digit, '') + '십'
elif i == 10:
name = digit2name.get(digit, '') + '백'
elif i == 11:
name = digit2name.get(digit, '') + '천'
elif i == 12:
name = digit2name.get(digit, '') + '조'
elif i == 13:
name = digit2name.get(digit, '') + '십'
elif i == 14:
name = digit2name.get(digit, '') + '백'
elif i == 15:
name = digit2name.get(digit, '') + '천'
spelledout.append(name)
return ''.join(elem for elem in spelledout)
def number_to_hangul(text):
'''Reference https://github.com/Kyubyong/g2pK'''
tokens = set(re.findall(r'(\d[\d,]*)([\uac00-\ud71f]+)', text))
for token in tokens:
num, classifier = token
if classifier[:2] in _korean_classifiers or classifier[0] in _korean_classifiers:
spelledout = hangul_number(num, sino=False)
else:
spelledout = hangul_number(num, sino=True)
text = text.replace(f'{num}{classifier}', f'{spelledout}{classifier}')
# digit by digit for remaining digits
digits = '0123456789'
names = '영일이삼사오육칠팔구'
for d, n in zip(digits, names):
text = text.replace(d, n)
return text
def korean_to_lazy_ipa(text):
text = latin_to_hangul(text)
text = number_to_hangul(text)
text=re.sub('[\uac00-\ud7af]+',lambda x:ko_pron.romanise(x.group(0),'ipa').split('] ~ [')[0],text)
for regex, replacement in _ipa_to_lazy_ipa:
text = re.sub(regex, replacement, text)
return text
_g2p=G2p()
def korean_to_ipa(text):
text = latin_to_hangul(text)
text = number_to_hangul(text)
text = _g2p(text)
text = fix_g2pk2_error(text)
text = korean_to_lazy_ipa(text)
return text.replace('ʧ','tʃ').replace('ʥ','dʑ')
def post_replace_ph(ph):
rep_map = {
":": ",",
";": ",",
",": ",",
"。": ".",
"!": "!",
"?": "?",
"\n": ".",
"·": ",",
"、": ",",
"...": "…",
" ": "空",
}
if ph in rep_map.keys():
ph = rep_map[ph]
if ph in symbols:
return ph
if ph not in symbols:
ph = "停"
return ph
def g2p(text):
text = latin_to_hangul(text)
text = _g2p(text)
text = divide_hangul(text)
text = fix_g2pk2_error(text)
text = re.sub(r'([\u3131-\u3163])$', r'\1.', text)
# text = "".join([post_replace_ph(i) for i in text])
text = [post_replace_ph(i) for i in text]
return text
+419
View File
@@ -0,0 +1,419 @@
import os
# punctuation = ['!', '?', '…', ",", ".","@"]#@是SP停顿
punctuation = ["!", "?", "…", ",", "."] # @是SP停顿
punctuation.append("-")
pu_symbols = punctuation + ["SP", "SP2", "SP3", "UNK"]
# pu_symbols = punctuation + ["SP", 'SP2', 'SP3','SP4', "UNK"]
pad = "_"
c = [
"AA",
"EE",
"OO",
"b",
"c",
"ch",
"d",
"f",
"g",
"h",
"j",
"k",
"l",
"m",
"n",
"p",
"q",
"r",
"s",
"sh",
"t",
"w",
"x",
"y",
"z",
"zh",
]
v = [
"E1",
"En1",
"a1",
"ai1",
"an1",
"ang1",
"ao1",
"e1",
"ei1",
"en1",
"eng1",
"er1",
"i1",
"i01",
"ia1",
"ian1",
"iang1",
"iao1",
"ie1",
"in1",
"ing1",
"iong1",
"ir1",
"iu1",
"o1",
"ong1",
"ou1",
"u1",
"ua1",
"uai1",
"uan1",
"uang1",
"ui1",
"un1",
"uo1",
"v1",
"van1",
"ve1",
"vn1",
"E2",
"En2",
"a2",
"ai2",
"an2",
"ang2",
"ao2",
"e2",
"ei2",
"en2",
"eng2",
"er2",
"i2",
"i02",
"ia2",
"ian2",
"iang2",
"iao2",
"ie2",
"in2",
"ing2",
"iong2",
"ir2",
"iu2",
"o2",
"ong2",
"ou2",
"u2",
"ua2",
"uai2",
"uan2",
"uang2",
"ui2",
"un2",
"uo2",
"v2",
"van2",
"ve2",
"vn2",
"E3",
"En3",
"a3",
"ai3",
"an3",
"ang3",
"ao3",
"e3",
"ei3",
"en3",
"eng3",
"er3",
"i3",
"i03",
"ia3",
"ian3",
"iang3",
"iao3",
"ie3",
"in3",
"ing3",
"iong3",
"ir3",
"iu3",
"o3",
"ong3",
"ou3",
"u3",
"ua3",
"uai3",
"uan3",
"uang3",
"ui3",
"un3",
"uo3",
"v3",
"van3",
"ve3",
"vn3",
"E4",
"En4",
"a4",
"ai4",
"an4",
"ang4",
"ao4",
"e4",
"ei4",
"en4",
"eng4",
"er4",
"i4",
"i04",
"ia4",
"ian4",
"iang4",
"iao4",
"ie4",
"in4",
"ing4",
"iong4",
"ir4",
"iu4",
"o4",
"ong4",
"ou4",
"u4",
"ua4",
"uai4",
"uan4",
"uang4",
"ui4",
"un4",
"uo4",
"v4",
"van4",
"ve4",
"vn4",
"E5",
"En5",
"a5",
"ai5",
"an5",
"ang5",
"ao5",
"e5",
"ei5",
"en5",
"eng5",
"er5",
"i5",
"i05",
"ia5",
"ian5",
"iang5",
"iao5",
"ie5",
"in5",
"ing5",
"iong5",
"ir5",
"iu5",
"o5",
"ong5",
"ou5",
"u5",
"ua5",
"uai5",
"uan5",
"uang5",
"ui5",
"un5",
"uo5",
"v5",
"van5",
"ve5",
"vn5",
]
v_without_tone = [
"E",
"En",
"a",
"ai",
"an",
"ang",
"ao",
"e",
"ei",
"en",
"eng",
"er",
"i",
"i0",
"ia",
"ian",
"iang",
"iao",
"ie",
"in",
"ing",
"iong",
"ir",
"iu",
"o",
"ong",
"ou",
"u",
"ua",
"uai",
"uan",
"uang",
"ui",
"un",
"uo",
"v",
"van",
"ve",
"vn",
]
# japanese
ja_symbols = [
"I",
"N",
"U",
"a",
"b",
"by",
"ch",
"cl",
"d",
"dy",
"e",
"f",
"g",
"gy",
"h",
"hy",
"i",
"j",
"k",
"ky",
"m",
"my",
"n",
"ny",
"o",
"p",
"py",
"r",
"ry",
"s",
"sh",
"t",
"ts",
"u",
"v",
"w",
"y",
"z",
###楼下2个留到后面加
# "[", #上升调型
# "]", #下降调型
# "$", #结束符
# "^", #开始符
]
arpa = {
"AH0",
"S",
"AH1",
"EY2",
"AE2",
"EH0",
"OW2",
"UH0",
"NG",
"B",
"G",
"AY0",
"M",
"AA0",
"F",
"AO0",
"ER2",
"UH1",
"IY1",
"AH2",
"DH",
"IY0",
"EY1",
"IH0",
"K",
"N",
"W",
"IY2",
"T",
"AA1",
"ER1",
"EH2",
"OY0",
"UH2",
"UW1",
"Z",
"AW2",
"AW1",
"V",
"UW2",
"AA2",
"ER",
"AW0",
"UW0",
"R",
"OW1",
"EH1",
"ZH",
"AE0",
"IH2",
"IH",
"Y",
"JH",
"P",
"AY1",
"EY0",
"OY2",
"TH",
"HH",
"D",
"ER0",
"CH",
"AO1",
"AE1",
"AO2",
"OY1",
"AY2",
"IH1",
"OW0",
"L",
"SH",
}
ko_symbols='ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㄲㄸㅃㅆㅉㅏㅓㅗㅜㅡㅣㅐㅔ空停'
# ko_symbols='ㄱㄴㄷㄹㅁㅂㅅㅇㅈㅊㅋㅌㅍㅎㄲㄸㅃㅆㅉㅏㅓㅗㅜㅡㅣㅐㅔ '
yue_symbols={'Yeot3', 'Yip1', 'Yyu3', 'Yeng4', 'Yut5', 'Yaan5', 'Ym5', 'Yaan6', 'Yang1', 'Yun4', 'Yon2', 'Yui5', 'Yun2', 'Yat3', 'Ye', 'Yeot1', 'Yoeng5', 'Yoek2', 'Yam2', 'Yeon6', 'Yu6', 'Yiu3', 'Yaang6', 'Yp5', 'Yai4', 'Yoek4', 'Yit6', 'Yam5', 'Yoeng6', 'Yg1', 'Yk3', 'Yoe4', 'Yam3', 'Yc', 'Yyu4', 'Yyut1', 'Yiu4', 'Ying3', 'Yip3', 'Yaap3', 'Yau3', 'Yan4', 'Yau1', 'Yap4', 'Yk6', 'Yok3', 'Yai1', 'Yeot6', 'Yan2', 'Yoek6', 'Yt1', 'Yoi1', 'Yit5', 'Yn4', 'Yaau3', 'Yau4', 'Yuk6', 'Ys', 'Yuk', 'Yin6', 'Yung6', 'Ya', 'You', 'Yaai5', 'Yau5', 'Yoi3', 'Yaak3', 'Yaat3', 'Ying2', 'Yok5', 'Yeng2', 'Yyut3', 'Yam1', 'Yip5', 'You1', 'Yam6', 'Yaa5', 'Yi6', 'Yek4', 'Yyu2', 'Yuk5', 'Yaam1', 'Yang2', 'Yai', 'Yiu6', 'Yin4', 'Yok4', 'Yot3', 'Yui2', 'Yeoi5', 'Yyun6', 'Yyu5', 'Yoi5', 'Yeot2', 'Yim4', 'Yeoi2', 'Yaan1', 'Yang6', 'Yong1', 'Yaang4', 'Yung5', 'Yeon1', 'Yin2', 'Ya3', 'Yaang3', 'Yg', 'Yk2', 'Yaau5', 'Yut1', 'Yt5', 'Yip4', 'Yung4', 'Yj', 'Yong3', 'Ya1', 'Yg6', 'Yaau6', 'Yit3', 'Yun3', 'Ying1', 'Yn2', 'Yg4', 'Yl', 'Yp3', 'Yn3', 'Yak1', 'Yang5', 'Yoe6', 'You2', 'Yap2', 'Yak2', 'Yt3', 'Yot5', 'Yim2', 'Yi1', 'Yn6', 'Yaat5', 'Yaam3', 'Yoek5', 'Ye3', 'Yeon4', 'Yaa2', 'Yu3', 'Yim6', 'Ym', 'Yoe3', 'Yaai2', 'Ym2', 'Ya6', 'Yeng6', 'Yik4', 'Yot4', 'Yaai4', 'Yyun3', 'Yu1', 'Yoeng1', 'Yaap2', 'Yuk3', 'Yoek3', 'Yeng5', 'Yeoi1', 'Yiu2', 'Yok1', 'Yo1', 'Yoek1', 'Yoeng2', 'Yeon5', 'Yiu1', 'Yoeng4', 'Yuk2', 'Yat4', 'Yg5', 'Yut4', 'Yan6', 'Yin3', 'Yaa6', 'Yap1', 'Yg2', 'Yoe5', 'Yt4', 'Ya5', 'Yo4', 'Yyu1', 'Yak3', 'Yeon2', 'Yong4', 'Ym1', 'Ye2', 'Yaang5', 'Yoi2', 'Yeng3', 'Yn', 'Yyut4', 'Yau', 'Yaak2', 'Yaan4', 'Yek2', 'Yin1', 'Yi5', 'Yoe2', 'Yei5', 'Yaat6', 'Yak5', 'Yp6', 'Yok6', 'Yei2', 'Yaap1', 'Yyut5', 'Yi4', 'Yim1', 'Yk5', 'Ye4', 'Yok2', 'Yaam6', 'Yat2', 'Yon6', 'Yei3', 'Yyu6', 'Yeot5', 'Yk4', 'Yai6', 'Yd', 'Yg3', 'Yei6', 'Yau2', 'Yok', 'Yau6', 'Yung3', 'Yim5', 'Yut6', 'Yit1', 'Yon3', 'Yat1', 'Yaam2', 'Yyut2', 'Yui6', 'Yt2', 'Yek6', 'Yt', 'Ye6', 'Yang3', 'Ying6', 'Yaau1', 'Yeon3', 'Yng', 'Yh', 'Yang4', 'Ying5', 'Yaap6', 'Yoeng3', 'Yyun4', 'You3', 'Yan5', 'Yat5', 'Yot1', 'Yun1', 'Yi3', 'Yaa1', 'Yaap4', 'You6', 'Yaang2', 'Yaap5', 'Yaa3', 'Yaak6', 'Yeng1', 'Yaak1', 'Yo5', 'Yoi4', 'Yam4', 'Yik1', 'Ye1', 'Yai5', 'Yung1', 'Yp2', 'Yui4', 'Yaak4', 'Yung2', 'Yak4', 'Yaat4', 'Yeoi4', 'Yut2', 'Yin5', 'Yaau4', 'Yap6', 'Yb', 'Yaam4', 'Yw', 'Yut3', 'Yong2', 'Yt6', 'Yaai6', 'Yap5', 'Yik5', 'Yun6', 'Yaam5', 'Yun5', 'Yik3', 'Ya2', 'Yyut6', 'Yon4', 'Yk1', 'Yit4', 'Yak6', 'Yaan2', 'Yuk1', 'Yai2', 'Yik2', 'Yaat2', 'Yo3', 'Ykw', 'Yn5', 'Yaa', 'Ye5', 'Yu4', 'Yei1', 'Yai3', 'Yyun5', 'Yip2', 'Yaau2', 'Yiu5', 'Ym4', 'Yeoi6', 'Yk', 'Ym6', 'Yoe1', 'Yeoi3', 'Yon', 'Yuk4', 'Yaai3', 'Yaa4', 'Yot6', 'Yaang1', 'Yei4', 'Yek1', 'Yo', 'Yp', 'Yo6', 'Yp4', 'Yan3', 'Yoi', 'Yap3', 'Yek3', 'Yim3', 'Yz', 'Yot2', 'Yoi6', 'Yit2', 'Yu5', 'Yaan3', 'Yan1', 'Yon5', 'Yp1', 'Yong5', 'Ygw', 'Yak', 'Yat6', 'Ying4', 'Yu2', 'Yf', 'Ya4', 'Yon1', 'You4', 'Yik6', 'Yui1', 'Yaat1', 'Yeot4', 'Yi2', 'Yaai1', 'Yek5', 'Ym3', 'Yong6', 'You5', 'Yyun1', 'Yn1', 'Yo2', 'Yip6', 'Yui3', 'Yaak5', 'Yyun2'}
# symbols = [pad] + c + v + ja_symbols + pu_symbols + list(arpa)+list(ko_symbols)#+list(yue_symbols)###直接这么加yue顺序乱了
symbols = [pad] + c + v + ja_symbols + pu_symbols + list(arpa)
symbols = sorted(set(symbols))
# print(len(symbols))
symbols+=["[","]"]##日文新增上升下降调型
symbols+=sorted(list(ko_symbols))
symbols+=sorted(list(yue_symbols))##新加的yue统一摆在后头#已查过开头加Y后没有重复,韩文显然不会重复
# print(len(symbols))
if __name__ == "__main__":
print(len(symbols))
'''
粤语:
732-353=379
韩文+粤语:
732-322=410
'''
@@ -28,7 +28,7 @@ UNITS = OrderedDict({
8: '亿',
})
COM_QUANTIFIERS = '(封|艘|把|目|套|段|人|所|朵|匹|张|座|回|场|尾|条|个|首|阙|阵|网|炮|顶|丘|棵|只|支|袭|辆|挑|担|颗|壳|窠|曲|墙|群|腔|砣|座|客|贯|扎|捆|刀|令|打|手|罗|坡|山|岭|江|溪|钟|队|单|双|对|出|口|头|脚|板|跳|枝|件|贴|针|线|管|名|位|身|堂|课|本|页|家|户|层|丝|毫|厘|分|钱|两|斤|担|铢|石|钧|锱|忽|(千|毫|微)克|毫|厘|(公)分|分|寸|尺|丈|里|寻|常|铺|程|(千|分|厘|毫|微)米|米|撮|勺|合|升|斗|石|盘|碗|碟|叠|桶|笼|盆|盒|杯|钟|斛|锅|簋|篮|盘|桶|罐|瓶|壶|卮|盏|箩|箱|煲|啖|袋|钵|年|月|日|季|刻|时|周|天|秒|分|小时|旬|纪|岁|世|更|夜|春|夏|秋|冬|代|伏|辈|丸|泡|粒|颗|幢|堆|条|根|支|道|面|片|张|颗|块|元|(亿|千万|百万|万|千|百)|(亿|千万|百万|万|千|百|美|)元|(亿|千万|百万|万|千|百|十|)吨|(亿|千万|百万|万|千|百|)块|角|毛|分)'
COM_QUANTIFIERS = '(处|台|架|枚|趟|幅|平|方|堵|间|床|株|批|项|例|列|篇|栋|注|亩|封|艘|把|目|套|段|人|所|朵|匹|张|座|回|场|尾|条|个|首|阙|阵|网|炮|顶|丘|棵|只|支|袭|辆|挑|担|颗|壳|窠|曲|墙|群|腔|砣|座|客|贯|扎|捆|刀|令|打|手|罗|坡|山|岭|江|溪|钟|队|单|双|对|出|口|头|脚|板|跳|枝|件|贴|针|线|管|名|位|身|堂|课|本|页|家|户|层|丝|毫|厘|分|钱|两|斤|担|铢|石|钧|锱|忽|(千|毫|微)克|毫|厘|(公)分|分|寸|尺|丈|里|寻|常|铺|程|(千|分|厘|毫|微)米|米|撮|勺|合|升|斗|石|盘|碗|碟|叠|桶|笼|盆|盒|杯|钟|斛|锅|簋|篮|盘|桶|罐|瓶|壶|卮|盏|箩|箱|煲|啖|袋|钵|年|月|日|季|刻|时|周|天|秒|分|小时|旬|纪|岁|世|更|夜|春|夏|秋|冬|代|伏|辈|丸|泡|粒|颗|幢|堆|条|根|支|道|面|片|张|颗|块|元|(亿|千万|百万|万|千|百)|(亿|千万|百万|万|千|百|美|)元|(亿|千万|百万|万|千|百|十|)吨|(亿|千万|百万|万|千|百|)块|角|毛|分)'
# 分数表达式
RE_FRAC = re.compile(r'(-?)(\d+)/(\d+)')
+73 -28
View File
@@ -11,7 +11,7 @@
调用请求缺少参考音频时使用
`-dr` - `默认参考音频路径`
`-dt` - `默认参考音频文本`
`-dl` - `默认参考音频语种, "中文","英文","日文","zh","en","ja"`
`-dl` - `默认参考音频语种, "中文","英文","日文","韩文","粤语,"zh","en","ja","ko","yue"`
`-d` - `推理设备, "cuda","cpu"`
`-a` - `绑定地址, 默认"127.0.0.1"`
@@ -201,6 +201,11 @@ def change_sovits_weights(sovits_path):
hps = dict_s2["config"]
hps = DictToAttrRecursive(hps)
hps.model.semantic_frame_rate = "25hz"
if dict_s2['weight']['enc_p.text_embedding.weight'].shape[0] == 322:
hps.model.version = "v1"
else:
hps.model.version = "v2"
print("sovits版本:",hps.model.version)
model_params_dict = vars(hps.model)
vq_model = SynthesizerTrn(
hps.data.filter_length // 2 + 1,
@@ -251,9 +256,9 @@ def get_bert_feature(text, word2ph):
return phone_level_feature.T
def clean_text_inf(text, language):
phones, word2ph, norm_text = clean_text(text, language)
phones = cleaned_text_to_sequence(phones)
def clean_text_inf(text, language, version):
phones, word2ph, norm_text = clean_text(text, language, version)
phones = cleaned_text_to_sequence(phones, version)
return phones, word2ph, norm_text
@@ -269,54 +274,64 @@ def get_bert_inf(phones, word2ph, norm_text, language):
return bert
def get_phones_and_bert(text,language):
if language in {"en","all_zh","all_ja"}:
from text import chinese
def get_phones_and_bert(text,language,version):
if language in {"en", "all_zh", "all_ja", "all_ko", "all_yue"}:
language = language.replace("all_","")
if language == "en":
LangSegment.setfilters(["en"])
formattext = " ".join(tmp["text"] for tmp in LangSegment.getTexts(text))
else:
# 因无法区别中日文汉字,以用户输入为准
# 因无法区别中日韩文汉字,以用户输入为准
formattext = text
while " " in formattext:
formattext = formattext.replace(" ", " ")
phones, word2ph, norm_text = clean_text_inf(formattext, language)
if language == "zh":
bert = get_bert_feature(norm_text, word2ph).to(device)
if re.search(r'[A-Za-z]', formattext):
formattext = re.sub(r'[a-z]', lambda x: x.group(0).upper(), formattext)
formattext = chinese.text_normalize(formattext)
return get_phones_and_bert(formattext,"zh",version)
else:
phones, word2ph, norm_text = clean_text_inf(formattext, language, version)
bert = get_bert_feature(norm_text, word2ph).to(device)
elif language == "yue" and re.search(r'[A-Za-z]', formattext):
formattext = re.sub(r'[a-z]', lambda x: x.group(0).upper(), formattext)
formattext = chinese.text_normalize(formattext)
return get_phones_and_bert(formattext,"yue",version)
else:
phones, word2ph, norm_text = clean_text_inf(formattext, language, version)
bert = torch.zeros(
(1024, len(phones)),
dtype=torch.float16 if is_half == True else torch.float32,
).to(device)
elif language in {"zh", "ja","auto"}:
elif language in {"zh", "ja", "ko", "yue", "auto", "auto_yue"}:
textlist=[]
langlist=[]
LangSegment.setfilters(["zh","ja","en","ko"])
if language == "auto":
for tmp in LangSegment.getTexts(text):
if tmp["lang"] == "ko":
langlist.append("zh")
textlist.append(tmp["text"])
else:
langlist.append(tmp["lang"])
textlist.append(tmp["text"])
langlist.append(tmp["lang"])
textlist.append(tmp["text"])
elif language == "auto_yue":
for tmp in LangSegment.getTexts(text):
if tmp["lang"] == "zh":
tmp["lang"] = "yue"
langlist.append(tmp["lang"])
textlist.append(tmp["text"])
else:
for tmp in LangSegment.getTexts(text):
if tmp["lang"] == "en":
langlist.append(tmp["lang"])
else:
# 因无法区别中日文汉字,以用户输入为准
# 因无法区别中日韩文汉字,以用户输入为准
langlist.append(language)
textlist.append(tmp["text"])
# logger.info(textlist)
# logger.info(langlist)
phones_list = []
bert_list = []
norm_text_list = []
for i in range(len(textlist)):
lang = langlist[i]
phones, word2ph, norm_text = clean_text_inf(textlist[i], lang)
phones, word2ph, norm_text = clean_text_inf(textlist[i], lang, version)
bert = get_bert_inf(phones, word2ph, norm_text, lang)
phones_list.append(phones)
norm_text_list.append(norm_text)
@@ -328,14 +343,32 @@ def get_phones_and_bert(text,language):
return phones,bert.to(torch.float16 if is_half == True else torch.float32),norm_text
class DictToAttrRecursive:
class DictToAttrRecursive(dict):
def __init__(self, input_dict):
super().__init__(input_dict)
for key, value in input_dict.items():
if isinstance(value, dict):
# 如果值是字典,递归调用构造函数
setattr(self, key, DictToAttrRecursive(value))
else:
setattr(self, key, value)
value = DictToAttrRecursive(value)
self[key] = value
setattr(self, key, value)
def __getattr__(self, item):
try:
return self[item]
except KeyError:
raise AttributeError(f"Attribute {item} not found")
def __setattr__(self, key, value):
if isinstance(value, dict):
value = DictToAttrRecursive(value)
super(DictToAttrRecursive, self).__setitem__(key, value)
super().__setattr__(key, value)
def __delattr__(self, item):
try:
del self[item]
except KeyError:
raise AttributeError(f"Attribute {item} not found")
def get_spepc(hps, filename):
@@ -488,9 +521,11 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
codes = vq_model.extract_latent(ssl_content)
prompt_semantic = codes[0, 0]
t1 = ttime()
version = vq_model.version
os.environ['version'] = version
prompt_language = dict_language[prompt_language.lower()]
text_language = dict_language[text_language.lower()]
phones1, bert1, norm_text1 = get_phones_and_bert(prompt_text, prompt_language)
phones1, bert1, norm_text1 = get_phones_and_bert(prompt_text, prompt_language, version)
texts = text.split("\n")
audio_bytes = BytesIO()
@@ -500,7 +535,7 @@ def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language,
continue
audio_opt = []
phones2, bert2, norm_text2 = get_phones_and_bert(text, text_language)
phones2, bert2, norm_text2 = get_phones_and_bert(text, text_language, version)
bert = torch.cat([bert1, bert2], 1)
all_phoneme_ids = torch.LongTensor(phones1 + phones2).to(device).unsqueeze(0)
@@ -606,17 +641,27 @@ def handle(refer_wav_path, prompt_text, prompt_language, text, text_language, cu
# --------------------------------
dict_language = {
"中文": "all_zh",
"粤语": "all_yue",
"英文": "en",
"日文": "all_ja",
"韩文": "all_ko",
"中英混合": "zh",
"粤英混合": "yue",
"日英混合": "ja",
"韩英混合": "ko",
"多语种混合": "auto", #多语种启动切分识别语种
"多语种混合(粤语)": "auto_yue",
"all_zh": "all_zh",
"all_yue": "all_yue",
"en": "en",
"all_ja": "all_ja",
"all_ko": "all_ko",
"zh": "zh",
"yue": "yue",
"ja": "ja",
"ko": "ko",
"auto": "auto",
"auto_yue": "auto_yue",
}
# logger
+14 -6
View File
@@ -213,16 +213,24 @@
重点:
4-[支持合成语速调节。支持冻结随机性只调节语速。](https://github.com/RVC-Boss/GPT-SoVITS/commit/9588a3c52d9ebdb20b3c5d74f647d12e7c1171c2)
4-[支持合成语速调节。支持冻结随机性只调节语速,](https://github.com/RVC-Boss/GPT-SoVITS/commit/9588a3c52d9ebdb20b3c5d74f647d12e7c1171c2)并将其更新到api.py上https://github.com/RVC-Boss/GPT-SoVITS/pull/1340
todolist:
### 20240806
1-中文多音字推理优化(有没有人来测试的,欢迎把测试结果写在pr评论区里) https://github.com/RVC-Boss/GPT-SoVITS/pull/488
(v2底模训练已经合了,下个版本发布就要合了)
2-正在尝试解决低音质参考音频导致音质较差的问题(202407:已经解决了),节点暂定8月吧
1-增加bs-roformer人声伴奏分离模型支持。 https://github.com/RVC-Boss/GPT-SoVITS/pull/1306 https://github.com/RVC-Boss/GPT-SoVITS/pull/1356 [支持fp16推理。](https://github.com/RVC-Boss/GPT-SoVITS/commit/e62e965323a60a76a025bcaa45268c1ddcbcf05c)
2-更好的中文文本前端。 https://github.com/RVC-Boss/GPT-SoVITS/pull/987 https://github.com/RVC-Boss/GPT-SoVITS/pull/1351 https://github.com/RVC-Boss/GPT-SoVITS/pull/1404 优化多音字逻辑(v2版本特供)。 https://github.com/RVC-Boss/GPT-SoVITS/pull/488
3-自动填充下一步的文件路径 https://github.com/RVC-Boss/GPT-SoVITS/pull/1355
4-增加喂饭逻辑,用户瞎写显卡序号也可以正常运作 [bce451a](https://github.com/RVC-Boss/GPT-SoVITS/commit/bce451a2d1641e581e200297d01f219aeaaf7299) [4c8b761](https://github.com/RVC-Boss/GPT-SoVITS/commit/4c8b7612206536b8b4435997acb69b25d93acb78)
5-增加粤语ASR支持 [8a10147](https://github.com/RVC-Boss/GPT-SoVITS/commit/8a101474b5a4f913b4c94fca2e3ca87d0771bae3)
6-GPT-SoVITS-v2支持
7-计时逻辑优化 https://github.com/RVC-Boss/GPT-SoVITS/pull/1387
+113 -21
View File
@@ -74,18 +74,11 @@ bash install.sh
```bash
conda create -n GPTSoVits python=3.9
conda activate GPTSoVits
pip install -r requirements.txt
```
### 手动安装
#### 安装依赖
```bash
pip install -r requirements.txt
```
#### 安装 FFmpeg
##### Conda 用户
@@ -106,11 +99,19 @@ conda install -c conda-forge 'ffmpeg<7'
下载并将 [ffmpeg.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe) 和 [ffprobe.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe) 放置在 GPT-SoVITS 根目录下。
##### Mac 用户
安装 [Visual Studio 2022](https://visualstudio.microsoft.com/zh-hans/downloads/) 环境(仅限韩语TTS)
##### MacOS 用户
```bash
brew install ffmpeg
```
#### 安装依赖
```bash
pip install -r requirements.txt
```
### 在 Docker 中使用
#### docker-compose.yaml 设置
@@ -142,22 +143,28 @@ docker run --rm -it --gpus=all --env=is_half=False --volume=G:\GPT-SoVITS-Docker
从 [GPT-SoVITS Models](https://huggingface.co/lj1995/GPT-SoVITS) 下载预训练模型,并将它们放置在 `GPT_SoVITS\pretrained_models` 中。
从 [G2PWModel-v2-onnx.zip](https://paddlespeech.bj.bcebos.com/Parakeet/released_models/g2p/G2PWModel_1.1.zip) 下载G2PW模型,并将它们解压重命名为`G2PWModel` 后放置在 `GPT_SoVITS\text` 中。(仅限中文TTS)
对于 UVR5(人声/伴奏分离和混响移除,附加),从 [UVR5 Weights](https://huggingface.co/lj1995/VoiceConversionWebUI/tree/main/uvr5_weights) 下载模型,并将它们放置在 `tools/uvr5/uvr5_weights` 中。
中国地区用户可以进入以下链接并点击“下载副本”下载以上两个模型(如果下载时遇到错误,请退出登录):
- [GPT-SoVITS Models](https://www.icloud.com.cn/iclouddrive/056y_Xog_HXpALuVUjscIwTtg#GPT-SoVITS_Models)
- [GPT-SoVITS Models](https://www.icloud.com/iclouddrive/044boFMiOHHt22SNr-c-tirbA#pretrained_models)
- [UVR5 Weights](https://www.icloud.com.cn/iclouddrive/0bekRKDiJXboFhbfm3lM2fVbA#UVR5_Weights)
- [G2PWModel_1.1.zip](https://paddlespeech.bj.bcebos.com/Parakeet/released_models/g2p/G2PWModel_1.1.zip)(下载G2PW模型,并将它们解压重命名为 `G2PWModel` 后放置在 `GPT_SoVITS\text` 中)
对于中文自动语音识别(附加),从 [Damo ASR Model](https://modelscope.cn/models/damo/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch/files), [Damo VAD Model](https://modelscope.cn/models/damo/speech_fsmn_vad_zh-cn-16k-common-pytorch/files), 和 [Damo Punc Model](https://modelscope.cn/models/damo/punc_ct-transformer_zh-cn-common-vocab272727-pytorch/files) 下载模型,并将它们放置在 `tools/asr/models` 中。
或者从[FunASR模型链接](https://www.icloud.com/iclouddrive/0b52_7SQWYr75kHkPoPXgpeQA#models)下载模型,并将它们解压后替换 `tools/asr/models` 。(点击“下载副本”,如果下载时遇到错误,请退出登录)
对于英语与日语自动语音识别(附加),从 [Faster Whisper Large V3](https://huggingface.co/Systran/faster-whisper-large-v3) 下载模型,并将它们放置在 `tools/asr/models` 中。 此外,[其他模型](https://huggingface.co/Systran)可能具有类似效果,但占用更小的磁盘空间。
中国地区用户可以通过以下链接下载:
- [Faster Whisper Large V3](https://www.icloud.com/iclouddrive/0c4pQxFs7oWyVU1iMTq2DbmLA#faster-whisper-large-v3)(点击“下载副本”,如果下载时遇到错误,请退出登录)
- [Faster Whisper Large V3](https://www.icloud.com/iclouddrive/00bUEp9_mcjMq_dhHu_vrAFDQ#faster-whisper-large-v3)(点击“下载副本”,如果下载时遇到错误,请退出登录)
- [Faster Whisper Large V3](https://hf-mirror.com/Systran/faster-whisper-large-v3)(Hugging Face镜像站)
- [Faster Whisper Large V3](https://hf-mirror.com/Systran/faster-whisper-large-v3)(Hugging Face镜像站)
## 数据集格式
@@ -170,22 +177,104 @@ vocal_path|speaker_name|language|text
语言字典:
- 'zh': Chinese
- 'ja': Japanese
- 'en': English
- 'zh': 中文
- 'ja': 日语
- 'en': 英语
- 'ko': 韩语
- 'yue': 粤语
示例:
```
D:\GPT-SoVITS\xxx/xxx.wav|xxx|en|I like playing Genshin.
D:\GPT-SoVITS\xxx/xxx.wav|xxx|zh|我爱玩原神。
```
## 微调与推理
### 打开WebUI
#### 整合包用户
双击`go-webui.bat`或者使用`go-webui.ps`
若想使用V1,则双击`go-webui-v1.bat`或者使用`go-webui-v1.ps`
#### 其他
```bash
python webui.py <language(optional)>
```
若想使用V1,则
```bash
python webui.py v1 <language(optional)>
```
或者在webUI内动态切换
### 微调
#### 现已支持自动填充路径
1.填入训练音频路径
2.切割音频
3.进行降噪(可选)
4.进行ASR
5.校对标注
6.前往下一个窗口,点击训练
### 打开推理WebUI
#### 整合包用户
双击 `go-webui.bat` 或者使用 `go-webui.ps` ,然后在 `1-GPT-SoVITS-TTS/1C-推理` 中打开推理webUI
#### 其他
```bash
python GPT_SoVITS/inference_webui.py <language(optional)>
```
或者
```bash
python webui.py
```
然后在 `1-GPT-SoVITS-TTS/1C-推理` 中打开推理webUI
## V2发布说明
新特性:
1.支持韩语及粤语
2.更好的文本前端
3.底模由2k小时扩展至5k小时
4.对低音质参考音频(尤其是来源于网络的高频严重缺失、听着很闷的音频)合成出来音质更好
详见[wiki](https://github.com/RVC-Boss/GPT-SoVITS/wiki/GPT%E2%80%90SoVITS%E2%80%90v2%E2%80%90features-(%E6%96%B0%E7%89%B9%E6%80%A7))
从v1环境迁移至v2
1.需要pip安装requirements.txt更新环境
2.需要克隆github上的最新代码
3.需要从[huggingface](https://huggingface.co/lj1995/GPT-SoVITS/tree/main/gsv-v2final-pretrained) 下载预训练模型文件放到GPT_SoVITS\pretrained_models\gsv-v2final-pretrained下
中文额外需要下载[G2PWModel_1.1.zip](https://paddlespeech.bj.bcebos.com/Parakeet/released_models/g2p/G2PWModel_1.1.zip)(下载G2PW模型,解压并重命名为`G2PWModel`,将其放到`GPT_SoVITS\text`目录下
## 待办事项清单
- [ ] **高优先级:**
- [x] 日语和英语的本地化。
- [ ] 用户指南。
- [x] 用户指南。
- [x] 日语和英语数据集微调训练。
- [ ] **功能:**
@@ -205,10 +294,10 @@ D:\GPT-SoVITS\xxx/xxx.wav|xxx|en|I like playing Genshin.
````
python tools/uvr5/webui.py "<infer_device>" <is_half> <webui_port_uvr5>
````
如果打不开浏览器,请按照下面的格式进行UVR处理,这是使用mdxnet进行音频处理的方式
<!-- 如果打不开浏览器,请按照下面的格式进行UVR处理,这是使用mdxnet进行音频处理的方式
````
python mdxnet.py --model --input_root --output_vocal --output_ins --agg_level --format --device --is_half_precision
````
```` -->
这是使用命令行完成数据集的音频切分的方式
````
python audio_slicer.py \
@@ -226,9 +315,9 @@ python tools/asr/funasr_asr.py -i <input> -o <output>
通过Faster_Whisper进行ASR处理(除中文之外的ASR标记)
(没有进度条,GPU性能可能会导致时间延迟)
````
python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language>
````
```
python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language> -p <precision>
```
启用自定义列表保存路径
## 致谢
@@ -249,6 +338,9 @@ python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language>
### 推理用文本前端
- [paddlespeech zh_normalization](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/t2s/frontend/zh_normalization)
- [LangSegment](https://github.com/juntaosun/LangSegment)
- [g2pW](https://github.com/GitYCC/g2pW)
- [pypinyin-g2pW](https://github.com/mozillazg/pypinyin-g2pW)
- [paddlespeech g2pw](https://github.com/PaddlePaddle/PaddleSpeech/tree/develop/paddlespeech/t2s/frontend/g2pw)
### WebUI 工具
- [ultimatevocalremovergui](https://github.com/Anjok07/ultimatevocalremovergui)
- [audio-slicer](https://github.com/openvpi/audio-slicer)
+12 -6
View File
@@ -163,10 +163,16 @@
4. [Commit 9588a3c](https://github.com/RVC-Boss/GPT-SoVITS/commit/9588a3c52d9ebdb20b3c5d74f647d12e7c1171c2) supported speech rate adjustment for synthesis.
Enabled freezing randomness while only adjusting the speech rate.
### TODO list:
### 20240806 Update
1. Optimize inference for Chinese polyphonic characters.
(Seeking testers, feel free to comment your results in the [PR 488](https://github.com/RVC-Boss/GPT-SoVITS/pull/488))
**Caution: This PR have been merged in v2 base model and will be included in the next release**.
2. Working on solving the issue of low-quality reference audio causing poor audio quality.
**Caution: Resolved in July 2024, scheduled for August 2024 release**.
1. [PR 1306](https://github.com/RVC-Boss/GPT-SoVITS/pull/1306), [PR 1356](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) Added support for the BS RoFormer vocal accompaniment separation model. [Commit e62e965](https://github.com/RVC-Boss/GPT-SoVITS/commit/e62e965323a60a76a025bcaa45268c1ddcbcf05c) Enabled FP16 inference.
2. Improved Chinese text frontend.
- [PR 488](https://github.com/RVC-Boss/GPT-SoVITS/pull/488) added support for polyphonic characters (v2 only);
- [PR 987](https://github.com/RVC-Boss/GPT-SoVITS/pull/987) added quantifier;
- [PR 1351](https://github.com/RVC-Boss/GPT-SoVITS/pull/1351) supports arithmetic and basic math formulas;
- [PR 1404](https://github.com/RVC-Boss/GPT-SoVITS/pull/1404) fixed mixed text errors.
3. [PR 1355](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) automatically filled in the paths when processing audio in the WebUI.
4. [Commit bce451a](https://github.com/RVC-Boss/GPT-SoVITS/commit/bce451a2d1641e581e200297d01f219aeaaf7299), [Commit 4c8b761](https://github.com/RVC-Boss/GPT-SoVITS/commit/4c8b7612206536b8b4435997acb69b25d93acb78) optimized GPU recognition logic.
5. [Commit 8a10147](https://github.com/RVC-Boss/GPT-SoVITS/commit/8a101474b5a4f913b4c94fca2e3ca87d0771bae3) added support for Cantonese ASR.
6. Added support for GPT-SoVITS v2.
7. [PR 1387](https://github.com/RVC-Boss/GPT-SoVITS/pull/1387) optimized timing logic.
+124 -32
View File
@@ -1,85 +1,177 @@
### 20240121 更新
1. `config`に`is_share`を追加し、Colab などの環境でこれを`True`に設定すると、webui を公共ネットワークにマッピングできます。
2. WebUI に英語システムの英語翻訳を追加しました。
3. `cmd-asr`は damo モデルが既に含まれているかどうかを自動的に確認し、デフォルトのパスにない場合は modelscope から自動的にダウンロードします。
3. `cmd-asr`は FunASR モデルが既に含まれているかどうかを自動的に確認し、デフォルトのパスにない場合は modelscope から自動的にダウンロードします。
4. [SoVITS 训练报错 ZeroDivisionError](https://github.com/RVC-Boss/GPT-SoVITS/issues/79) 修復を試みます(長さ 0 のサンプルをフィルタリングなど)
5. TEMP ファイルフォルダからオーディオやその他のファイルをクリーンアップして最適化します。
6. 合成オーディオがリファレンスオーディオの終わりを含む問題を大幅に改善しました。
### 20240122 更新
1. 短すぎる出力ファイルが重複したリファレンスオーディオを返す問題を修正しました。
2. 英語-日本語学習がスムーズに進む QA を完了しました。(ただし、日本語学習はルートディレクトリに英語以外の文字が含まれていない必要があります)
3. オーディオパスをチェックします。間違ったパスを読み取ろうとすると、「パスが存在しません」というエラーメッセージが返されます。これは ffmpeg モジュールのエラーではありません。
### 20240123 更新
1. hubert から nan 抽出による SoVITS/GPT 学習中の ZeroDivisionError 関連エラーを修正しました。
2. 推論インターフェースでモデルを素早く切り替えることができるようにサポートしました。
3. モデルファイルのソートロジックを最適化しました。
4. 中国語の分析に`jieba_fast`を`jieba`に置き換えました。
4. 中国語の分析に `jieba_fast` を `jieba` に置き換えました。
### 20240126 更新
1. 中国語と英語、日本語と英語が混在した出力テキストをサポートします。
2. 出力で選択的な分割モードをサポートします。
3. uvr5 がディレクトリを読み取り、自動的に終了する問題を修正しました。
4. 複数の改行による推論エラーを修正しました。
5. 推論インターフェースから不要なログを削除しました。
6. MacOS での学習と推論をサポートします。
7. 半精度をサポートしていないカードを自動的に識別して単精度を強制し、CPU 推論では単精度を強制します。
### 20240128 更新
1. 数字を漢字で読む問題を修正しました。
2. 文章の先頭の一部の単語が欠落する問題を修正しました。
3. 不適切な長さのリファレンスオーディオを制限しました。
4. GPT 学習時の ckpt が保存されない問題を修正しました。
5. Dockerfile のモデルダウンロードプロセスを改善しました。
### 20240129 更新
1. 16 系などの半精度学習に問題があるカードは、学習構成を単精度学習に変更しました。
2. Colab でも使用可能なバージョンをテストして更新しました。
3. `git clone modelscope funasr`リポジトリと古いバージョンの funasr を使用してインターフェースが一致しないエラーを修正しました。
3. ModelScope FunASR リポジトリの古いバージョンで git クローンを行う際のインターフェース不整合エラーの問題を修正しました。
### 20240130 更新
1. パスと関連する文字列を解析して、二重引用符を自動的に削除します。また、パスをコピーする場合、二重引用符が含まれていてもエラーが発生しません。
2. 中国語と英語、日本語と英語の混合出力をサポートします。
3. 出力で選択的な分割モードをサポートします。
todolist:
### 20240201 更新
1. 同音異義語(中国語)の推論の最適化
1. UVR5 形式の読み取りエラーによる分離失敗を修正しました。
2. 中国語・日本語・英語の混合テキストに対する自動分割と言語認識をサポートしました。
2. 英語大文字認識と英語ハイフン [問題](https://github.com/RVC-Boss/GPT-SoVITS/issues/271)
### 20240202 更新
3. テキストに%記号が含まれているとエラーが発生し、推論が不可能です。また、「元/吨」が「元吨」ではなく「元每吨」と読まれるなどの問題があります。このような問題を解決するには、どのライブラリを使用する必要があり、それに対する改善を検討しています。
1. ASRパスが `/` で終わることによるファイル名保存エラーの問題を修正しました。
2. [PR 377](https://github.com/RVC-Boss/GPT-SoVITS/pull/377) で PaddleSpeech の Normalizer を導入し、"xx.xx%"(パーセント記号)の読み取りや"元/吨"が"元吨"ではなく"元每吨"と読まれる問題、アンダースコアエラーを修正しました。
4. 中-日-英、中-英、日-英を含む 5 つの言語をサポートすることを目標にしています。
### 20240207 更新
1. [Issue 391](https://github.com/RVC-Boss/GPT-SoVITS/issues/391) で報告された中国語推論品質の低下を引き起こした言語パラメータの混乱を修正しました。
2. [PR 403](https://github.com/RVC-Boss/GPT-SoVITS/pull/403) で UVR5 を librosa のより高いバージョンに適応させました。
3. [Commit 14a2851](https://github.com/RVC-Boss/GPT-SoVITS/commit/14a285109a521679f8846589c22da8f656a46ad8) で、`is_half` パラメータがブール値に変換されず、常に半精度推論が行われ、16 シリーズの GPU で `inf` が発生する UVR5 inf everywhereエラーを修正しました。
4. 英語テキストフロントエンドを最適化しました。
5. Gradio の依存関係を修正しました。
6. データセット準備中にルートディレクトリが空白の場合、`.list` フルパスの自動読み取りをサポートしました。
7. 日本語と英語のために Faster Whisper ASR を統合しました。
### 20240208 更新
1. [Commit 59f35ad](https://github.com/RVC-Boss/GPT-SoVITS/commit/59f35adad85815df27e9c6b33d420f5ebfd8376b) で、Windows 10 1909 および [Issue 232](https://github.com/RVC-Boss/GPT-SoVITS/issues/232)(繁体字中国語システム言語)での GPT トレーニングのハングを修正する試みを行いました。
### 20240212 更新
1. Faster Whisper と FunASR のロジックを最適化し、Faster Whisper をミラーダウンロードに切り替えて Hugging Face の接続問題を回避しました。
2. [PR 457](https://github.com/RVC-Boss/GPT-SoVITS/pull/457) で、GPT の繰り返しと文字欠落を軽減するために、トレーニング中に負のサンプルを構築する実験的なDPO Lossトレーニングオプションを有効にし、いくつかの推論パラメータを推論WebUIで利用可能にしました。
### 20240214 更新
1. トレーニングで中国語の実験名をサポート(以前はエラーが発生していました)。
2. DPOトレーニングを必須ではなくオプション機能に変更。選択された場合、バッチサイズは自動的に半分になります。推論 WebUI で新しいパラメータが渡されない問題を修正しました。
### 20240216 更新
1. 参照テキストなしでの入力をサポート。
2. [Issue 475](https://github.com/RVC-Boss/GPT-SoVITS/issues/475) で報告された中国語フロントエンドのバグを修正しました。
### 20240221 更新
1. データ処理中のノイズ低減オプションを追加(ノイズ低減は16kHzサンプリングレートのみを残します;背景ノイズが大きい場合にのみ使用してください)。
2. [PR 559](https://github.com/RVC-Boss/GPT-SoVITS/pull/559), [PR 556](https://github.com/RVC-Boss/GPT-SoVITS/pull/556), [PR 532](https://github.com/RVC-Boss/GPT-SoVITS/pull/532), [PR 507](https://github.com/RVC-Boss/GPT-SoVITS/pull/507), [PR 509](https://github.com/RVC-Boss/GPT-SoVITS/pull/509) で中国語と日本語のフロントエンド処理を最適化しました。
3. Mac CPU 推論を MPS ではなく CPU を使用するように切り替え、パフォーマンスを向上させました。
4. Colab のパブリック URL の問題を修正しました。
### 20240306 更新
1. [PR 672](https://github.com/RVC-Boss/GPT-SoVITS/pull/672) で推論速度を50%向上させました(RTX3090 + PyTorch 2.2.1 + CU11.8 + Win10 + Py39 でテスト)。
2. Faster Whisper非中国語ASRを使用する際、最初に中国語FunASRモデルをダウンロードする必要がなくなりました。
3. [PR 610](https://github.com/RVC-Boss/GPT-SoVITS/pull/610) で UVR5 残響除去モデルの設定が逆になっていた問題を修正しました。
4. [PR 675](https://github.com/RVC-Boss/GPT-SoVITS/pull/675) で、CUDA が利用できない場合に Faster Whisper の自動 CPU 推論を有効にしました。
5. [PR 573](https://github.com/RVC-Boss/GPT-SoVITS/pull/573) で、Mac での適切なCPU推論を確保するために `is_half` チェックを修正しました。
### 202403/202404/202405 更新
#### マイナー修正:
1. 参照テキストなしモードの問題を修正しました。
2. 中国語と英語のテキストフロントエンドを最適化しました。
3. API フォーマットを改善しました。
4. CMD フォーマットの問題を修正しました。
5. トレーニングデータ処理中のサポートされていない言語に対するエラープロンプトを追加しました。
6. Hubert 抽出のバグを修正しました。
#### メジャー修正:
1. SoVITS トレーニングで VQ を凍結せずに品質低下を引き起こす問題を修正しました。
2. クイック推論ブランチを追加しました。
### 20240610 更新
#### マイナー修正:
1. [PR 1168](https://github.com/RVC-Boss/GPT-SoVITS/pull/1168) & [PR 1169](https://github.com/RVC-Boss/GPT-SoVITS/pull/1169)で、純粋な句読点および複数の句読点を含むテキスト入力のロジックを改善しました。
2. [Commit 501a74a](https://github.com/RVC-Boss/GPT-SoVITS/commit/501a74ae96789a26b48932babed5eb4e9483a232)で、UVR5 の MDXNet デリバブをサポートする CMD フォーマットを修正し、スペースを含むパスをサポートしました。
3. [PR 1159](https://github.com/RVC-Boss/GPT-SoVITS/pull/1159)で、`s2_train.py` の SoVITS トレーニングのプログレスバーロジックを修正しました。
#### メジャー修正:
4. [Commit 99f09c8](https://github.com/RVC-Boss/GPT-SoVITS/commit/99f09c8bdc155c1f4272b511940717705509582a) で、WebUI の GPT ファインチューニングが中国語入力テキストの BERT 特徴を読み取らず、推論との不一致や品質低下の可能性を修正しました。
**注意: 以前に大量のデータでファインチューニングを行った場合、品質向上のためにモデルを再調整することをお勧めします。**
### 20240706 更新
#### マイナー修正:
1. [Commit 1250670](https://github.com/RVC-Boss/GPT-SoVITS/commit/db50670598f0236613eefa6f2d5a23a271d82041) で、CPU 推論のデフォルトバッチサイズの小数点問題を修正しました。
2. [PR 1258](https://github.com/RVC-Boss/GPT-SoVITS/pull/1258), [PR 1265](https://github.com/RVC-Boss/GPT-SoVITS/pull/1265), [PR 1267](https://github.com/RVC-Boss/GPT-SoVITS/pull/1267) で、ノイズ除去またはASRが例外に遭遇した場合に、すべての保留中のオーディオファイルが終了する問題を修正しました。
3. [PR 1253](https://github.com/RVC-Boss/GPT-SoVITS/pull/1253) で、句読点で分割する際の小数点分割の問題を修正しました。
4. [Commit a208698](https://github.com/RVC-Boss/GPT-SoVITS/commit/a208698e775155efc95b187b746d153d0f2847ca) で、マルチGPUトレーニングのマルチプロセス保存ロジックを修正しました。
5. [PR 1251](https://github.com/RVC-Boss/GPT-SoVITS/pull/1251) で、不要な `my_utils` を削除しました。
#### メジャー修正:
6. [PR 672](https://github.com/RVC-Boss/GPT-SoVITS/pull/672) の加速推論コードが検証され、メインブランチにマージされ、ベースとの推論効果の一貫性が確保されました。
また、参照テキストなしモードでの加速推論もサポートしています。
**今後の更新では、`fast_inference`ブランチの変更の一貫性を継続的に検証します**。
### 20240727 更新
#### マイナー修正:
1. [PR 1298](https://github.com/RVC-Boss/GPT-SoVITS/pull/1298) で、不要な i18n コードをクリーンアップしました。
2. [PR 1299](https://github.com/RVC-Boss/GPT-SoVITS/pull/1299) で、ユーザーファイルパスの末尾のスラッシュがコマンドラインエラーを引き起こす問題を修正しました。
3. [PR 756](https://github.com/RVC-Boss/GPT-SoVITS/pull/756) で、GPT トレーニングのステップ計算ロジックを修正しました。
#### メジャー修正:
4. [Commit 9588a3c](https://github.com/RVC-Boss/GPT-SoVITS/commit/9588a3c52d9ebdb20b3c5d74f647d12e7c1171c2) で、合成のスピーチレート調整をサポートしました。
スピーチレートのみを調整しながらランダム性を固定できるようになりました。
### 20240806 更新
1. [PR 1306](https://github.com/RVC-Boss/GPT-SoVITS/pull/1306)、[PR 1356](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) BS RoFormer ボーカルアコムパニ分離モデルのサポートを追加しました。[Commit e62e965](https://github.com/RVC-Boss/GPT-SoVITS/commit/e62e965323a60a76a025bcaa45268c1ddcbcf05c) FP16 推論を有効にしました。
2. 中国語テキストフロントエンドを改善しました。
- [PR 488](https://github.com/RVC-Boss/GPT-SoVITS/pull/488) 多音字のサポートを追加(v2 のみ);
- [PR 987](https://github.com/RVC-Boss/GPT-SoVITS/pull/987) 量詞を追加;
- [PR 1351](https://github.com/RVC-Boss/GPT-SoVITS/pull/1351) 四則演算と基本数式のサポート;
- [PR 1404](https://github.com/RVC-Boss/GPT-SoVITS/pull/1404) 混合テキストエラーを修正。
3. [PR 1355](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) WebUIでオーディオ処理時にパスを自動入力しました。
4. [Commit bce451a](https://github.com/RVC-Boss/GPT-SoVITS/commit/bce451a2d1641e581e200297d01f219aeaaf7299), [Commit 4c8b761](https://github.com/RVC-Boss/GPT-SoVITS/commit/4c8b7612206536b8b4435997acb69b25d93acb78) GPU 認識ロジックを最適化しました。
5. [Commit 8a10147](https://github.com/RVC-Boss/GPT-SoVITS/commit/8a101474b5a4f913b4c94fca2e3ca87d0771bae3) 広東語ASRのサポートを追加しました。
6. GPT-SoVITS v2 のサポートを追加しました。
7. [PR 1387](https://github.com/RVC-Boss/GPT-SoVITS/pull/1387) タイミングロジックを最適化しました。
+2 -2
View File
@@ -102,7 +102,7 @@ conda install -c conda-forge 'ffmpeg<7'
[ffmpeg.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe) と [ffprobe.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe) をダウンロードし、GPT-SoVITS のルートディレクトリに置きます。
##### Mac ユーザー
##### MacOS ユーザー
```bash
brew install ffmpeg
```
@@ -209,7 +209,7 @@ ASR処理はFaster_Whisperを通じて実行されます(中国語を除くASR
(進行状況バーは表示されません。GPU のパフォーマンスにより時間遅延が発生する可能性があります)
```
python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language>
python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language> -p <precision>
```
カスタムリストの保存パスが有効になっています
+129 -60
View File
@@ -1,109 +1,178 @@
### 20240121 업데이트
1. `config`에 `is_share` 추가, Colab 등의 환경에서 이를 `True`로 설정하여 webui를 공용 네트워크에 매핑되도록 할 수 있습니다.
2. WebUI에 영어 번역이 추가되었습니다.
3. `cmd-asr`은 damo 모델이 이미 포함되어 있는지 자동으로 확인하고, 기본 경로에 없는 경우 modelscope에서 자동 다운로드 되도록 수정하였습니다.
4. [SoVITS 학습 중 ZeroDivisionError가 발생](https://github.com/RVC-Boss/GPT-SoVITS/issues/79)하는 경우 복구를 시도합니다. (길이가 0인 샘플 필터링 등)
5. TEMP 파일 폴더에서 오디오 및 기타 파일을 정리하여 최적화합니다.
6. 합성 오디오가 레퍼런스 오디오의 끝부분을 포함하는 문제를 개선하였습니다.
1. `config`에 `is_share`를 추가했습니다. Colab과 같은 시나리오에서는 이 값을 `True`로 설정하여 WebUI를 공개 네트워크에 매핑할 수 있습니다.
2. WebUI에 영어 시스템 번역 지원을 추가했습니다.
3. `cmd-asr`이 FunASR 모델이 포함되어 있는지 자동으로 감지합니다; 기본 디렉토리에서 찾을 수 없으면 ModelScope에서 다운로드됩니다.
4. [Issue 79](https://github.com/RVC-Boss/GPT-SoVITS/issues/79)에서 보고된 SoVITS 훈련의 ZeroDivisionError를 필터링 샘플 등으로 해결하려고 시도했습니다.
5. `TEMP` 폴더의 캐시된 오디오 파일 및 기타 파일을 정리했습니다.
6. 참조 오디오의 끝이 포함된 합성 오디오 문제를 크게 줄였습니다.
### 20240122 업데이트
1. 너무 짧은 출력 파일이 중복된 레퍼런스 오디오를 반환하는 문제 수정하였습니다.
2. 영어-일본어 학습이 원활하게 진행되는 QA를 완료하였습니다. (다만, 일본어 학습은 루트 디렉토리에 영어 이외의 문자가 없어야 합니다)
3. 오디오 경로를 검사합니다. 잘못된 경로를 읽으려고 할 때 '경로가 존재하지 않습니다'라는 에러 메시지를 반환하도록 수정하였습니다. 이는 ffmpeg 모듈의 에러가 아닙니다.
1. 지나치게 짧은 출력 파일로 인해 참조 오디오가 반복되는 문제를 수정했습니다.
2. 영어 및 일본어 훈련의 네이티브 지원을 테스트했습니다 (일본어 훈련 시 루트 디렉토리에 비영어 특수 문자가 없어야 합니다).
3. 오디오 경로 확인을 개선했습니다. 잘못된 입력 경로에서 읽으려는 시도가 있을 경우, ffmpeg 오류 대신 경로가 존재하지 않는다고 보고합니다.
### 20240123 업데이트
1. hubert에서 nan 추출로 인한 SoVITS/GPT 학습 중 ZeroDivisionError 관련 에러를 해결하였습니다.
2. 추론 인터페이스에서 모델을 빠르게 전환할 수 있도록 지원하도록 수정되었습니다.
3. 모델 파일 정렬 로직 최적화하였습니다.
4. 중문 분석에 `jieba_fast`를 `jieba`로 대체하였습니다.
1. Hubert 추출로 인해 NaN 오류가 발생하여 SoVITS/GPT 훈련에서 ZeroDivisionError가 발생하는 문제를 해결했습니다.
2. 추론 WebUI에서 빠른 모델 전환 지원을 추가했습니다.
3. 모델 파일 정렬 로직을 최적화했습니다.
4. 중국어 단어 분할을 위해 `jieba`를 `jieba_fast`로 교체했습니다.
### 20240126 업데이트
1. 중국어와 영어, 일본어와 영어가 혼합된 출력 텍스트를 지원합니다.
2. 출력에서 선택적 분할 모드를 지원합니다.
3. uvr5가 디렉토리를 읽고 자동으로 종료되는 문제를 수정하였습니다.
4. 여러 줄바꿈으로 인한 추론 오류를 수정하였습니다.
5. 추론 인터페이스에서 불필요한 로그 제거하였습니다.
6. MacOS에서의 학습 및 추론을 지원합니다.
7. 반정밀을 지원하지 않는 카드를 자동으로 식별하여 단일 정밀도를 강제 적용하고, CPU 추론에서 단일 정밀도를 강제 적용합니다.
1. 중국어-영어 혼합 및 일본어-영어 혼합 출력 텍스트를 지원합니다.
2. 출력에 대한 선택적 분할 모드를 추가했습니다.
3. UVR5 읽기 문제 및 디렉토리 자동 탈출 문제를 수정했습니다.
4. 추론 오류를 일으키는 여러 줄 바꿈 문제를 수정했습니다.
5. 추론 WebUI 에서 중복 로그를 제거했습니다.
6. Mac에서 훈련 및 추론을 지원합니다.
7. 절반 정밀도를 지원하지 않는 GPU에 대해 자동으로 단정밀도를 강제하며, CPU 추론 시 단정밀도를 적용합니다.
### 20240128 업데이트
1. 숫자를 한자로 읽는 문제를 수정했습니다.
2. 문장 시작 부분의 일부 단어가 누락되는 문제 수정하였습니다.
3. 부적절한 길이의 레퍼런스 오디오를 제한하였습니다.
4. GPT 학습 시 ckpt가 저장되지 않는 문제 수정하였습니다.
5. Dockerfile에서 모델 다운로드 프로세스 개선하였습니다.
1. 숫자의 발음이 중국어 문자로 변환되는 문제를 수정했습니다.
2. 문장 시작 부분에서 몇 개의 문자가 누락되는 문제를 수정했습니다.
3. 비합리적인 참조 오디오 길이를 설정하여 제외했습니다.
4. GPT 훈련 시 체크포인트가 저장되지 않는 문제를 수정했습니다.
5. Dockerfile 에서 모델 다운로드 프로세스를 완료했습니다.
### 20240129 업데이트
1. 반정밀도 훈련에 문제가 있는 16 시리즈 및 기타 그래픽 카드의 훈련 구성을 단정밀도 훈련으로 변경했습니다.
2. Colab에서도 사용이 가능한 버전을 테스트 및 업데이트 하였습니다.
3. `git clone modelscope funasr` 저장소와 오래된 버전의 funasr 사용으로 인해 인터페이스가 일치하지 않는 오류를 수정하였습니다.
1. 절반 정밀도 훈련에 문제가 있는 16 시리즈와 같은 GPU의 훈련 구성을 단정밀도로 변경했습니다.
2. 사용 가능한 Colab 버전을 테스트하고 업데이트했습니다.
3. 이전 버전의 FunASR 로 인해 인터페이스 정렬 오류가 발생하는 ModelScope FunASR 저장소의 git 클로닝 문제를 수정했습니다.
### 20240130 업데이트
1. 경로와 관련된 문자열을 파싱하여 큰따옴표를 자동으로 제거합니다. 또한, 경로를 복사하는 경우 큰따옴표가 포함되어도 오류가 발생하지 않습니다.
2. 중국어 및 영어 문자열의 문장 부호가 잘리는 문제 및 문장의 시작과 끝에 문장 부호가 추가되는 문제를 수정했습니다.
3. 문장 부호의 수를 확장하였습니다.
1. 모든 경로 관련 항목에서 이중 따옴표를 자동으로 제거하여 초보자가 이중 따옴표가 포함된 경로를 복사하는 오류를 방지했습니다.
2. 중국어 및 영어 문장 부호 분할 문제를 수정하고 문장 시작과 끝에 부호를 추가했습니다.
3. 부호에 의한 분할을 추가했습니다.
### 20240201 업데이트
1. uvr5가 잘못된 형식으로 읽어들이는 문제를 수정하였습니다.
2. 중국어, 일본어, 영어가 혼합된 여러 텍스트를 자동으로 분리하여 언어를 인식합니다.
1. 분리 실패를 일으킨 UVR5 형식 읽기 오류를 수정했습니다.
2. 혼합된 중국어-일본어-영어 텍스트에 대한 자동 분할 및 언어 인식을 지원합니다.
### 20240202 업데이트
1. asr 경로의 끝에 `/`가 포함되어 있는 경우 오류가 발생하는 문제를 수정하였습니다.
2. paddlespeech의 Normalizer를 도입하여 [문제를 해결](https://github.com/RVC-Boss/GPT-SoVITS/pull/377)하여, 예를 들어 xx.xx%(백분율), 元/吨이 元吨으로 읽히는 문제를 해결하였습니다. 또한, 밑줄이 더 이상 오류를 발생시키지 않습니다.
1. `/` 로 끝나는 ASR 경로가 파일 이름 저장 시 오류를 발생시키는 문제를 수정했습니다.
2. [PR 377](https://github.com/RVC-Boss/GPT-SoVITS/pull/377) 에서는 PaddleSpeech 의 Normalizer 를 도입하여 "xx.xx%" (백분율 기호)와 "元/吨"이 "元吨"으로 읽히는 문제를 "元每吨"으로 수정하고, 밑줄 오류를 수정했습니다.
### 20240207 업데이트
1. 언어 전달 매개변수가 혼란스러워져 [중국어 추론 효과가 저하되는 문제](https://github.com/RVC-Boss/GPT-SoVITS/issues/391)를 수정하였습니다.
2. uvr5가 `inf everywhere` [오류를 반환하는 문제](https://github.com/RVC-Boss/GPT-SoVITS/pull/403)를 수정하였습니다.
3. uvr5의 `is_half` 매개변수가 bool로 변환되지 않아 항상 반정밀도 추론으로 설정되어 16 시리즈 그래픽 카드에서 `inf`가 반환되는 [문제](https://github.com/RVC-Boss/GPT-SoVITS/commit/14a285109a521679f8846589c22da8f656a46ad8)를 수정하였습니다.
4. 영어 텍스트 입력을 최적화하였습니다.
5. gradio 종속성을 지원합니다.
6. 루트 디렉토리가 비어 있으면 `.list` 전체 경로를 자동으로 읽습니다.
7. faster whisper ASR 일본어 및 영어를 지원합니다.
1. [Issue 391](https://github.com/RVC-Boss/GPT-SoVITS/issues/391) 에서 보고된 중국어 추론 품질 저하를 일으킨 언어 매개변수 혼동을 수정했습니다.
2. [PR 403](https://github.com/RVC-Boss/GPT-SoVITS/pull/403) 에서는 UVR5 를 높은 버전의 librosa에 맞게 조정했습니다.
3. [Commit 14a2851](https://github.com/RVC-Boss/GPT-SoVITS/commit/14a285109a521679f8846589c22da8f656a46ad8)에서는 `is_half` 매개변수가 불리언으로 변환되지 않아 발생한 UVR5 `inf` 오류를 수정했습니다. 이로 인해 16 시리즈 GPU에서 `inf` 가 발생했습니다.
4. 영어 텍스트 프론트엔드를 최적화했습니다.
5. Gradio 종속성 문제를 수정했습니다.
6. 데이터셋 준비 시 루트 디렉토리를 비워두면 `.list` 전체 경로를 자동으로 읽도록 지원합니다.
7. 일본어와 영어에 대한 Faster Whisper ASR을 통합했습니다.
### 20240208 업데이트
1. GPT 학습이 카드에 따라 멈추는 문제와 [GPT 학습 중 ZeroDivisionError](https://github.com/RVC-Boss/GPT-SoVITS/commit/59f35adad85815df27e9c6b33d420f5ebfd8376b) 문제를 수정하였습니다.
1. [Commit 59f35ad](https://github.com/RVC-Boss/GPT-SoVITS/commit/59f35adad85815df27e9c6b33d420f5ebfd8376b)에서는 Windows 10 1909와 [Issue 232](https://github.com/RVC-Boss/GPT-SoVITS/issues/232) (전통 중국어 시스템 언어)에서 GPT 훈련 멈춤 문제를 수정하려고 했습니다.
### 20240212 업데이트
1. faster whisper 및 funasr 로직을 최적화하였습니다. faster whisper는 이미지 스토어에서 다운로드하여 huggingface에 연결하지 못하는 문제를 회피합니다.
2. DPO Loss 실험적 학습 옵션을 활성화하여 부정적 샘플을 생성하여 [GPT 반복 및 누락 문자 문제](https://github.com/RVC-Boss/GPT-SoVITS/pull/457)를 완화합니다. 추론 인터페이스에 몇 가지 추론 매개변수를 공개합니다.
1. Faster Whisper와 FunASR의 로직을 최적화하고, Faster Whisper를 미러 다운로드로 전환하여 Hugging Face 연결 문제를 피했습니다.
2. [PR 457](https://github.com/RVC-Boss/GPT-SoVITS/pull/457)은 DPO Loss 실험적 훈련 옵션을 활성화하여 GPT의 반복 및 문자 누락 문제를 완화하고, 훈련 중 부정 샘플을 구성하며 여러 추론 매개변수를 추론 WebUI에서 사용할 수 있게 했습니다.
### 20240214 업데이트
1. 학습에서 중국어 실험 이름을 지원합니다. (이전에 오류가 발생했습니다)
2. DPO 학습을 선택적으로 설정할 수 있도록 변경하였습니다. 배치 크기를 선택하면 자동으로 절반으로 줄어듭니다. 추론 인터페이스에서 새로운 매개변수를 전달하지 않는 문제를 수정하였습니다.
1. 훈련 시 중국어 실험 이름을 지원합니다 (이전에는 오류가 발생했습니다).
2. DPO 훈련을 필수 기능 대신 선택적 기능으로 변경했습니다. 선택 시, 배치 크기가 자동으로 절반으로 줄어듭니다. 추론 WebUI에서 새로운 매개변수가 전달되지 않는 문제를 수정했습니다.
### 20240216 업데이트
1. 참조 텍스트 입력을 지원합니다.
2. 프론트엔드에 있던 중국어 텍스트 입력 버그를 수정하였습니다.
1. 참조 텍스트 없이 입력을 지원합니다.
2. [Issue 475](https://github.com/RVC-Boss/GPT-SoVITS/issues/475)에서 보고된 중국어 프론트엔드의 버그를 수정했습니다.
### 20240221 업데이트
1. 데이터 처리에 음성 노이즈 감소 옵션을 추가하였습니다. (노이즈 감소는 16k 샘플링률만 남기며, 노이즈가 크지 않다면 사용하지 마십시오.)
2. 중국어 및 일본어 프론트엔드 처리를 최적화하였습니다. https://github.com/RVC-Boss/GPT-SoVITS/pull/559 https://github.com/RVC-Boss/GPT-SoVITS/pull/556 https://github.com/RVC-Boss/GPT-SoVITS/pull/532 https://github.com/RVC-Boss/GPT-SoVITS/pull/507 https://github.com/RVC-Boss/GPT-SoVITS/pull/509
3. Mac에서 CPU 추론이 더 빨라졌으므로 추론 장치를 mps에서 CPU로 변경하였습니다.
4. colab에서 공용 URL을 열지 않는 문제를 수정하였습니다.
1. 데이터 처리 중 노이즈 감소 옵션을 추가했습니다 (노이즈 감소는 16kHz 샘플링 비율만 남깁니다; 배경 노이즈가 심한 경우에만 사용하십시오).
2. [PR 559](https://github.com/RVC-Boss/GPT-SoVITS/pull/559), [PR 556](https://github.com/RVC-Boss/GPT-SoVITS/pull/556), [PR 532](https://github.com/RVC-Boss/GPT-SoVITS/pull/532), [PR 507](https://github.com/RVC-Boss/GPT-SoVITS/pull/507), [PR 509](https://github.com/RVC-Boss/GPT-SoVITS/pull/509) 중국어 및 일본어 프론트엔드 처리를 최적화했습니다.
3. Mac CPU 추론을 MPS 대신 CPU를 사용하도록 전환하여 성능을 향상시켰습니다.
4. Colab 공개 URL 문제를 수정했습니다.
### 20240306 업데이트
1. 추론 속도를 50% 빠르게 하였습니다. (RTX3090+pytorch2.2.1+cu11.8+win10+py39 테스트 완료) https://github.com/RVC-Boss/GPT-SoVITS/pull/672
2. faster whisper를 사용할 때 중국어 ASR을 먼저 다운로드할 필요가 없습니다.
3. uvr5의 잔향 제거 모델이 잔향이 있는지 여부를 반대로 반환하는 문제를 수정하였습니다.
4. faster whisper가 CUDA를 사용할 수 없는 경우 자동으로 CPU 추론을 사용하도록 수정하였습니다.
5. is_half의 판단을 수정하여 Mac에서 CPU 추론이 정상적으로 작동하도록 수정하였습니다.
1. [PR 672](https://github.com/RVC-Boss/GPT-SoVITS/pull/672)는 추론 속도를 50% 가속화했습니다 (RTX3090 + PyTorch 2.2.1 + CU11.8 + Win10 + Py39에서 테스트됨).
2. Faster Whisper의 비중국어 ASR을 사용할 때 중국어 FunASR 모델을 먼저 다운로드할 필요가 없습니다.
3. [PR 610](https://github.com/RVC-Boss/GPT-SoVITS/pull/610)은 UVR5 리버브 제거 모델에서 설정이 반대로 되어 있는 문제를 수정했습니다.
4. [PR 675](https://github.com/RVC-Boss/GPT-SoVITS/pull/675)는 CUDA가 없는 경우 Faster Whisper의 자동 CPU 추론을 가능하게 했습니다.
5. [PR 573](https://github.com/RVC-Boss/GPT-SoVITS/pull/573)은 Mac에서 올바른 CPU 추론을 보장하기 위해 `is_half` 체크를 수정했습니다.
todolist:
### 202403/202404/202405 업데이트
1. 중국어 다양한 발음 단어 추론 최적화(테스트 결과를 작성하시는 분은 pr 코멘트 영역에 작성해주시면 감사하겠습니다)
#### 사소한 수정:
1. 참조 텍스트 없는 모드의 문제를 수정했습니다.
2. 중국어 및 영어 텍스트 프론트엔드를 최적화했습니다.
3. API 형식을 개선했습니다.
4. CMD 형식 문제를 수정했습니다.
5. 훈련 데이터 처리 중 지원되지 않는 언어에 대한 오류 프롬프트를 추가했습니다.
6. Hubert 추출의 버그를 수정했습니다.
#### 주요 수정:
1. VQ를 고정하지 않고 SoVITS 훈련의 문제를 수정했습니다(품질 저하를 일으킬 수 있음).
2. 빠른 추론 분기를 추가했습니다.
### 20240610 업데이트
#### 사소한 수정:
1. [PR 1168](https://github.com/RVC-Boss/GPT-SoVITS/pull/1168) & [PR 1169](https://github.com/RVC-Boss/GPT-SoVITS/pull/1169) 순수 구두점 및 다중 구두점 텍스트 입력 로직을 개선했습니다.
2. [Commit 501a74a](https://github.com/RVC-Boss/GPT-SoVITS/commit/501a74ae96789a26b48932babed5eb4e9483a232) UVR5에서 MDXNet 디러버브를 위한 CMD 형식을 수정하고 공백이 있는 경로를 지원했습니다.
3. [PR 1159](https://github.com/RVC-Boss/GPT-SoVITS/pull/1159) `s2_train.py`에서 SoVITS 훈련을 위한 진행률 표시줄 로직을 수정했습니다.
#### 주요 수정:
4. [Commit 99f09c8](https://github.com/RVC-Boss/GPT-SoVITS/commit/99f09c8bdc155c1f4272b511940717705509582a) WebUI의 GPT 미세 조정이 중국어 입력 텍스트의 BERT 기능을 읽지 않아 추론과 불일치 및 잠재적 품질 저하를 일으키는 문제를 수정했습니다.
**주의: 이전에 많은 양의 데이터로 미세 조정한 경우 품질을 향상시키기 위해 모델을 다시 조정하는 것이 좋습니다.**
### 20240706 업데이트
#### 사소한 수정:
1. [Commit 1250670](https://github.com/RVC-Boss/GPT-SoVITS/commit/db50670598f0236613eefa6f2d5a23a271d82041) CPU 추론에서 기본 배치 크기 소수점 문제를 수정했습니다.
2. [PR 1258](https://github.com/RVC-Boss/GPT-SoVITS/pull/1258), [PR 1265](https://github.com/RVC-Boss/GPT-SoVITS/pull/1265), [PR 1267](https://github.com/RVC-Boss/GPT-SoVITS/pull/1267) 노이즈 제거 또는 ASR이 예외를 만나면 모든 보류 중인 오디오 파일이 종료되는 문제를 수정했습니다.
3. [PR 1253](https://github.com/RVC-Boss/GPT-SoVITS/pull/1253) 구두점으로 분할할 때 소수점 분할 문제를 수정했습니다.
4. [Commit a208698](https://github.com/RVC-Boss/GPT-SoVITS/commit/a208698e775155efc95b187b746d153d0f2847ca) 다중 GPU 훈련을 위한 다중 프로세스 저장 로직을 수정했습니다.
5. [PR 1251](https://github.com/RVC-Boss/GPT-SoVITS/pull/1251) 불필요한 `my_utils`를 제거했습니다.
#### 주요 수정:
6. [PR 672](https://github.com/RVC-Boss/GPT-SoVITS/pull/672)의 가속 추론 코드가 검증되어 메인 브랜치에 병합되었으며, 기본과 일관된 추론 효과를 보장합니다.
또한 참조 텍스트 없는 모드에서 가속 추론을 지원합니다.
**향후 업데이트에서는 `fast_inference` 브랜치의 변경 사항의 일관성을 계속 검증할 것입니다**.
### 20240727 업데이트
#### 사소한 수정:
1. [PR 1298](https://github.com/RVC-Boss/GPT-SoVITS/pull/1298) 불필요한 i18n 코드를 정리했습니다.
2. [PR 1299](https://github.com/RVC-Boss/GPT-SoVITS/pull/1299) 사용자 파일 경로의 후행 슬래시가 명령줄 오류를 일으키는 문제를 수정했습니다.
3. [PR 756](https://github.com/RVC-Boss/GPT-SoVITS/pull/756) GPT 훈련의 단계 계산 로직을 수정했습니다.
#### 주요 수정:
4. [Commit 9588a3c](https://github.com/RVC-Boss/GPT-SoVITS/commit/9588a3c52d9ebdb20b3c5d74f647d12e7c1171c2) 합성을 위한 음성 속도 조절을 지원했습니다.
음성 속도만 조절하면서 무작위성을 고정할 수 있습니다.
### 20240806 업데이트
1. [PR 1306](https://github.com/RVC-Boss/GPT-SoVITS/pull/1306), [PR 1356](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) BS RoFormer 보컬 반주 분리 모델에 대한 지원을 추가했습니다. [Commit e62e965](https://github.com/RVC-Boss/GPT-SoVITS/commit/e62e965323a60a76a025bcaa45268c1ddcbcf05c) FP16 추론을 활성화했습니다.
2. 중국어 텍스트 프론트엔드를 개선했습니다.
- [PR 488](https://github.com/RVC-Boss/GPT-SoVITS/pull/488) 중국어 다의자 지원 (v2 전용);
- [PR 987](https://github.com/RVC-Boss/GPT-SoVITS/pull/987) 추가된 양자;
- [PR 1351](https://github.com/RVC-Boss/GPT-SoVITS/pull/1351) 사칙연산 및 기본 수학 공식을 지원합니다;
- [PR 1404](https://github.com/RVC-Boss/GPT-SoVITS/pull/1404) 혼합 텍스트 오류를 수정했습니다.
3. [PR 1355](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) WebUI 에서 오디오를 처리할 때 경로를 자동으로 채웠습니다.
4. [Commit bce451a](https://github.com/RVC-Boss/GPT-SoVITS/commit/bce451a2d1641e581e200297d01f219aeaaf7299), [Commit 4c8b761](https://github.com/RVC-Boss/GPT-SoVITS/commit/4c8b7612206536b8b4435997acb69b25d93acb78) GPU 인식 로직을 최적화했습니다.
5. [Commit 8a10147](https://github.com/RVC-Boss/GPT-SoVITS/commit/8a101474b5a4f913b4c94fca2e3ca87d0771bae3) 광동어 ASR 지원을 추가했습니다.
6. GPT-SoVITS v2 지원을 추가했습니다.
7. [PR 1387](https://github.com/RVC-Boss/GPT-SoVITS/pull/1387) 타이밍 로직을 최적화했습니다.
+2 -2
View File
@@ -102,7 +102,7 @@ conda install -c conda-forge 'ffmpeg<7'
[ffmpeg.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe)와 [ffprobe.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe)를 GPT-SoVITS root 디렉토리에 넣습니다.
##### Mac 사용자
##### MacOS 사용자
```bash
brew install ffmpeg
```
@@ -213,7 +213,7 @@ ASR 처리는 Faster_Whisper(중국어를 제외한 ASR 마킹)를 통해 수행
(진행률 표시줄 없음, GPU 성능으로 인해 시간 지연이 발생할 수 있음)
```
python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language>
python ./tools/asr/fasterwhisper_asr.py -i <input> -o <output> -l <language> -p <precision>
```
사용자 정의 목록 저장 경로가 활성화되었습니다.
+178
View File
@@ -0,0 +1,178 @@
### 20240121 Güncellemesi
1. `config`e `is_share` eklendi. Colab gibi senaryolarda, WebUI'yi halka açık ağa yönlendirmek için bu değeri `True` olarak ayarlayabilirsiniz.
2. WebUI'ye İngilizce sistem çeviri desteği eklendi.
3. `cmd-asr`, FunASR modelinin dahil olup olmadığını otomatik olarak tespit eder; eğer varsayılan dizinde bulunamazsa, ModelScope'dan indirilecektir.
4. [Issue 79](https://github.com/RVC-Boss/GPT-SoVITS/issues/79)de bildirilen SoVITS eğitimindeki ZeroDivisionError'u sıfır uzunlukta örnekleri filtreleyerek düzeltmeye çalıştık.
5. `TEMP` klasöründeki önbelleğe alınmış ses dosyaları ve diğer dosyaları temizledik.
6. Referans sesinin sonunu içeren sentezlenmiş ses sorununu önemli ölçüde azalttık.
### 20240122 Güncellemesi
1. Aşırı kısa çıktı dosyalarının referans sesini tekrarlamasına neden olan sorun giderildi.
2. İngilizce ve Japonca eğitim için yerel destek test edildi (Japonca eğitim için kök dizinin İngilizce olmayan özel karakterlerden arındırılmış olması gerekir).
3. Ses yolu denetimi iyileştirildi. Yanlış bir giriş yolundan okumaya çalışıldığında, ffmpeg hatası yerine yolun mevcut olmadığını bildirir.
### 20240123 Güncellemesi
1. Hubert çıkarımının NaN hatalarına neden olup SoVITS/GPT eğitiminde ZeroDivisionError'a yol açtığı sorun çözüldü.
2. İnferans WebUI'de hızlı model değiştirme desteği eklendi.
3. Model dosyası sıralama mantığı optimize edildi.
4. Çince kelime ayrımı için `jieba` `jieba_fast` ile değiştirildi.
### 20240126 Güncellemesi
1. Çince-İngilizce ve Japonca-İngilizce karışık çıktı metinleri için destek eklendi.
2. Çıktı için isteğe bağlı bir bölme modu eklendi.
3. UVR5'in dizinlerden otomatik olarak çıkmasına neden olan okuma sorununu düzelttik.
4. Çeşitli yeni satır sorunlarını düzelterek çıkarım hatalarını giderdik.
5. Çıkarım WebUI'deki gereksiz günlükleri kaldırdık.
6. Mac'te eğitim ve çıkarım desteği eklendi.
7. Yarım hassasiyeti desteklemeyen GPU'lar için otomatik olarak tek hassasiyet zorlandı; CPU çıkarımında tek hassasiyet uygulandı.
### 20240128 Güncellemesi
1. Sayıların Çince karakterlere dönüştürülmesiyle ilgili sorunu düzelttik.
2. Cümlelerin başındaki birkaç karakterin yutulması sorununu düzelttik.
3. Mantıksız referans ses uzunluklarını sınırlamalar koyarak hariç tuttuk.
4. GPT eğitiminin kontrol noktalarını kaydetmemesi sorununu düzelttik.
5. Dockerfile'da model indirme sürecini tamamladık.
### 20240129 Güncellemesi
1. Yarım hassasiyet eğitimi ile ilgili sorun yaşayan 16 serisi gibi GPU'lar için eğitim yapılandırmalarını tek hassasiyete değiştirdik.
2. Mevcut Colab sürümünü test ettik ve güncelledik.
3. Eski sürüm FunASR ile ModelScope FunASR deposunun git klonlanmasıyla oluşan arayüz hizalama hatalarını düzelttik.
### 20240130 Güncellemesi
1. Çift tırnaklarla yol kopyalama hatalarını önlemek için tüm yol ile ilgili girdilerden otomatik olarak çift tırnakları kaldırdık.
2. Çince ve İngilizce noktalama işaretlerini ayırma sorunlarını düzelttik ve cümlelerin başına ve sonuna noktalama işaretleri ekledik.
3. Noktalama işaretlerine göre ayırma özelliğini ekledik.
### 20240201 Güncellemesi
1. Ayrılma hatalarına neden olan UVR5 format okuma hatasını düzelttik.
2. Karışık Çince-Japonca-İngilizce metinler için otomatik segmentasyon ve dil tanıma desteği sağladık.
### 20240202 Güncellemesi
1. `/` ile biten bir ASR yolunun dosya adını kaydetme hatasına neden olma sorununu düzelttik.
2. [PR 377](https://github.com/RVC-Boss/GPT-SoVITS/pull/377) PaddleSpeech'in Normalizer'ını tanıtarak "xx.xx%" (yüzde sembolleri) ve "元/吨" ifadesinin "元吨" yerine "元每吨" olarak okunması gibi sorunları düzelttik ve alt çizgi hatalarını giderdik.
### 20240207 Güncellemesi
1. [Issue 391](https://github.com/RVC-Boss/GPT-SoVITS/issues/391)de bildirilen dil parametresi karışıklığının Çinçe çıkarım kalitesini düşürme sorununu düzelttik.
2. [PR 403](https://github.com/RVC-Boss/GPT-SoVITS/pull/403) ile UVR5'i daha yüksek versiyonlarda librosa'ya uyarladık.
3. [Commit 14a2851](https://github.com/RVC-Boss/GPT-SoVITS/commit/14a285109a521679f8846589c22da8f656a46ad8) `is_half` parametresinin booleana dönüştürülmemesi nedeniyle sürekli yarım hassasiyet çıkarımı yaparak 16 serisi GPU'larda `inf` hatasına neden olan UVR5 inf hatasını düzelttik.
4. İngilizce metin önyüzünü optimize ettik.
5. Gradio bağımlılıklarını düzelttik.
6. Veri seti hazırlığı sırasında kök dizini boş bırakıldığında `.list` tam yollarının otomatik olarak okunmasını destekledik.
7. Japonca ve İngilizce için Faster Whisper ASR'yi entegre ettik.
### 20240208 Güncellemesi
1. [Commit 59f35ad](https://github.com/RVC-Boss/GPT-SoVITS/commit/59f35adad85815df27e9c6b33d420f5ebfd8376b) ile Windows 10 1909'da ve [Issue 232](https://github.com/RVC-Boss/GPT-SoVITS/issues/232)de (Geleneksel Çince Sistem Dili) bildirilen GPT eğitim durma sorununu düzeltmeye çalıştık.
### 20240212 Güncellemesi
1. Faster Whisper ve FunASR için mantığı optimize ettik, Hugging Face bağlantı sorunlarını önlemek için Faster Whisper'ı ayna indirmelere yönlendirdik.
2. [PR 457](https://github.com/RVC-Boss/GPT-SoVITS/pull/457) GPT tekrarı ve eksik karakterleri azaltmak için eğitim sırasında negatif örnekler oluşturarak deneysel DPO Loss eğitim seçeneğini etkinleştirdi ve çıkarım WebUI'de çeşitli çıkarım parametrelerini kullanılabilir hale getirdi.
### 20240214 Güncellemesi
1. Eğitimde Çince deney adlarını destekledik (önceden hatalara neden oluyordu).
2. DPO eğitimini zorunlu yerine isteğe bağlı bir özellik yaptık. Seçilirse, parti boyutu otomatik olarak yarıya indirilir. Çıkarım WebUI'de yeni parametrelerin iletilmemesi sorunlarını düzelttik.
### 20240216 Güncellemesi
1. Referans metin olmadan girişi destekledik.
2. [Issue 475](https://github.com/RVC-Boss/GPT-SoVITS/issues/475) de bildirilen Çince önyüz hatalarını düzelttik.
### 20240221 Güncellemesi
1. Veri işleme sırasında bir gürültü azaltma seçeneği ekledik (gürültü azaltma sadece 16kHz örnekleme hızını bırakır; yalnızca arka plan gürültüsü önemliyse kullanın).
2. [PR 559](https://github.com/RVC-Boss/GPT-SoVITS/pull/559), [PR 556](https://github.com/RVC-Boss/GPT-SoVITS/pull/556), [PR 532](https://github.com/RVC-Boss/GPT-SoVITS/pull/532), [PR 507](https://github.com/RVC-Boss/GPT-SoVITS/pull/507), [PR 509](https://github.com/RVC-Boss/GPT-SoVITS/pull/509) ile Çince ve Japonca önyüz işlemesini optimize ettik.
3. Mac CPU çıkarımını daha hızlı performans için MPS yerine CPU kullanacak şekilde değiştirdik.
4. Colab genel URL sorununu düzelttik.
### 20240306 Güncellemesi
1. [PR 672](https://github.com/RVC-Boss/GPT-SoVITS/pull/672) çıkarımı %50 hızlandırdı (RTX3090 + PyTorch 2.2.1 + CU11.8 + Win10 + Py39 üzerinde test edildi).
2. Faster Whisper'ın Çince olmayan ASR'sini kullanırken artık önce Çin FunASR modelini indirmeyi gerektirmiyor.
3. [PR 610](https://github.com/RVC-Boss/GPT-SoVITS/pull/610) UVR5 yankı giderme modelindeki ayarın tersine çevrildiği sorunu düzeltti.
4. [PR 675](https://github.com/RVC-Boss/GPT-SoVITS/pull/675) CUDA mevcut olmadığında Faster Whisper için otomatik CPU çıkarımını etkinleştirdi.
5. [PR 573](https://github.com/RVC-Boss/GPT-SoVITS/pull/573) Mac'te doğru CPU çıkarımı sağlamak için `is_half` kontrolünü değiştirdi.
### 202403/202404/202405 Güncellemeleri
#### Küçük Düzeltmeler:
1. Referans metin olmayan mod ile ilgili sorunlar düzeltildi.
2. Çince ve İngilizce metin önyüzü optimize edildi.
3. API formatı iyileştirildi.
4. CMD format sorunları düzeltildi.
5. Eğitim verisi işleme sırasında desteklenmeyen diller için hata uyarıları eklendi.
6. Hubert çıkarımındaki hata düzeltildi.
#### Büyük Düzeltmeler:
1. VQ'yu dondurmadan yapılan SoVITS eğitimi sorunu (bu kalite düşüşüne neden olabilir) düzeltildi.
2. Hızlı çıkarım dalı eklendi.
### 20240610 Güncellemesi
#### Küçük Düzeltmeler:
1. [PR 1168](https://github.com/RVC-Boss/GPT-SoVITS/pull/1168) & [PR 1169](https://github.com/RVC-Boss/GPT-SoVITS/pull/1169) saf noktalama işareti ve çoklu noktalama işareti metin girdisi için mantığı geliştirdi.
2. [Commit 501a74a](https://github.com/RVC-Boss/GPT-SoVITS/commit/501a74ae96789a26b48932babed5eb4e9483a232) UVR5'teki MDXNet yankı giderme için CMD formatını düzeltti, boşluk içeren yolları destekledi.
3. [PR 1159](https://github.com/RVC-Boss/GPT-SoVITS/pull/1159) `s2_train.py` içindeki SoVITS eğitimi için ilerleme çubuğu mantığını düzeltti.
#### Büyük Düzeltmeler:
4. [Commit 99f09c8](https://github.com/RVC-Boss/GPT-SoVITS/commit/99f09c8bdc155c1f4272b511940717705509582a) WebUI'nin GPT ince ayarının, Çince giriş metinlerinin BERT özelliğini okumaması sorununu düzeltti, bu da çıkarım ile tutarsızlığa ve potansiyel kalite düşüşüne neden oluyordu.
**Dikkat: Daha önce büyük miktarda veri ile ince ayar yaptıysanız, modelin kalitesini artırmak için yeniden ayar yapmanız önerilir.**
### 20240706 Güncellemesi
#### Küçük Düzeltmeler:
1. [Commit 1250670](https://github.com/RVC-Boss/GPT-SoVITS/commit/db50670598f0236613eefa6f2d5a23a271d82041) CPU çıkarımında varsayılan yığın boyutu ondalık sorununu düzeltti.
2. [PR 1258](https://github.com/RVC-Boss/GPT-SoVITS/pull/1258), [PR 1265](https://github.com/RVC-Boss/GPT-SoVITS/pull/1265), [PR 1267](https://github.com/RVC-Boss/GPT-SoVITS/pull/1267) gürültü giderme veya ASR ile ilgili istisnalarla karşılaşıldığında bekleyen tüm ses dosyalarının çıkış yapmasına neden olan sorunları düzeltti.
3. [PR 1253](https://github.com/RVC-Boss/GPT-SoVITS/pull/1253) noktalama işaretlerine göre ayrılırken ondalıkların bölünmesi sorununu düzeltti.
4. [Commit a208698](https://github.com/RVC-Boss/GPT-SoVITS/commit/a208698e775155efc95b187b746d153d0f2847ca) çoklu GPU eğitimi için çoklu işlem kaydetme mantığını düzeltti.
5. [PR 1251](https://github.com/RVC-Boss/GPT-SoVITS/pull/1251) gereksiz `my_utils`'ı kaldırdı.
#### Büyük Düzeltmeler:
6. [PR 672](https://github.com/RVC-Boss/GPT-SoVITS/pull/672) hızlandırılmış çıkarım kodu doğrulandı ve ana dala birleştirildi, taban ile tutarlı çıkarım etkileri sağlandı.
Ayrıca referans metni olmayan modda hızlandırılmış çıkarımı destekler.
**Gelecek güncellemeler, `fast_inference` dalındaki değişikliklerin tutarlılığını doğrulamaya devam edecek.**
### 20240727 Güncellemesi
#### Küçük Düzeltmeler:
1. [PR 1298](https://github.com/RVC-Boss/GPT-SoVITS/pull/1298) gereksiz i18n kodlarını temizledi.
2. [PR 1299](https://github.com/RVC-Boss/GPT-SoVITS/pull/1299) kullanıcı dosya yollarındaki sonlandırma eğik çizgilerinin komut satırı hatalarına neden olduğu sorunları düzeltti.
3. [PR 756](https://github.com/RVC-Boss/GPT-SoVITS/pull/756) GPT eğitimindeki adım hesaplama mantığını düzeltti.
#### Büyük Düzeltmeler:
4. [Commit 9588a3c](https://github.com/RVC-Boss/GPT-SoVITS/commit/9588a3c52d9ebdb20b3c5d74f647d12e7c1171c2) sentez için konuşma hızı ayarlamasını destekledi.
Konuşma hızını ayarlarken rastgeleliği dondurmayı etkinleştirdi.
### 20240806 Güncellemesi
1. [PR 1306](https://github.com/RVC-Boss/GPT-SoVITS/pull/1306), [PR 1356](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) BS RoFormer vokal eşlik ayırma modelini desteklemeye başladı. [Commit e62e965](https://github.com/RVC-Boss/GPT-SoVITS/commit/e62e965323a60a76a025bcaa45268c1ddcbcf05c) FP16 çıkarımı etkinleştirdi.
2. Çince metin ön yüzünü geliştirdi.
- [PR 488](https://github.com/RVC-Boss/GPT-SoVITS/pull/488) çoklu heceli karakterler için destek ekledi (v2 sadece);
- [PR 987](https://github.com/RVC-Boss/GPT-SoVITS/pull/987) sayı belirleyici ekledi;
- [PR 1351](https://github.com/RVC-Boss/GPT-SoVITS/pull/1351) aritmetik ve temel matematik formüllerini destekler;
- [PR 1404](https://github.com/RVC-Boss/GPT-SoVITS/pull/1404) karışık metin hatalarını düzeltti.
3. [PR 1355](https://github.com/RVC-Boss/GPT-SoVITS/pull/1356) WebUI'de ses işlenirken yolları otomatik olarak doldurdu.
4. [Commit bce451a](https://github.com/RVC-Boss/GPT-SoVITS/commit/bce451a2d1641e581e200297d01f219aeaaf7299), [Commit 4c8b761](https://github.com/RVC-Boss/GPT-SoVITS/commit/4c8b7612206536b8b4435997acb69b25d93acb78) GPU tanıma mantığını optimize etti.
5. [Commit 8a10147](https://github.com/RVC-Boss/GPT-SoVITS/commit/8a101474b5a4f913b4c94fca2e3ca87d0771bae3) Kantonca ASR desteği ekledi.
6. GPT-SoVITS v2 desteği eklendi.
7. [PR 1387](https://github.com/RVC-Boss/GPT-SoVITS/pull/1387) zamanlama mantığını optimize etti.
+1 -1
View File
@@ -102,7 +102,7 @@ conda install -c conda-forge 'ffmpeg<7'
[ffmpeg.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffmpeg.exe) ve [ffprobe.exe](https://huggingface.co/lj1995/VoiceConversionWebUI/blob/main/ffprobe.exe) dosyalarını indirin ve GPT-SoVITS kök dizinine yerleştirin.
##### Mac Kullanıcıları
##### MacOS Kullanıcıları
```bash
brew install ffmpeg
```
+2
View File
@@ -0,0 +1,2 @@
runtime\python.exe webui.py v1 zh_CN
pause
+4
View File
@@ -0,0 +1,4 @@
$ErrorActionPreference = "SilentlyContinue"
chcp 65001
& "$PSScriptRoot\runtime\python.exe" "$PSScriptRoot\webui.py v1 zh_CN"
pause
+1 -1
View File
@@ -1,2 +1,2 @@
runtime\python.exe webui.py
runtime\python.exe webui.py zh_CN
pause
+1 -1
View File
@@ -1,4 +1,4 @@
$ErrorActionPreference = "SilentlyContinue"
chcp 65001
& "$PSScriptRoot\runtime\python.exe" "$PSScriptRoot\webui.py"
& "$PSScriptRoot\runtime\python.exe" "$PSScriptRoot\webui.py zh_CN"
pause
+10 -3
View File
@@ -7,9 +7,10 @@ pytorch-lightning
gradio==3.38.0
gradio_client==0.8.1
ffmpeg-python
onnxruntime
onnxruntime; sys_platform == 'darwin'
onnxruntime-gpu; sys_platform != 'darwin'
tqdm
funasr==1.0.0
funasr==1.0.27
cn2an
pypinyin
pyopenjtalk
@@ -26,4 +27,10 @@ jieba
LangSegment>=0.2.0
Faster_Whisper
wordsegment
rotary_embedding_torch
rotary_embedding_torch
pyjyutping
g2pk2
ko_pron
opencc; sys_platform != 'linux'
opencc==1.1.1; sys_platform == 'linux'
python_mecab_ko; sys_platform != 'win32'
+6 -4
View File
@@ -18,14 +18,16 @@ def check_fw_local_models():
asr_dict = {
"达摩 ASR (中文)": {
'lang': ['zh'],
'lang': ['zh','yue'],
'size': ['large'],
'path': 'funasr_asr.py',
'precision': ['float32']
},
"Faster Whisper (多语种)": {
'lang': ['auto', 'zh', 'en', 'ja'],
'lang': ['auto', 'zh', 'en', 'ja', 'ko', 'yue'],
'size': check_fw_local_models(),
'path': 'fasterwhisper_asr.py'
}
'path': 'fasterwhisper_asr.py',
'precision': ['float32', 'float16', 'int8']
},
}
@@ -101,8 +101,8 @@ if __name__ == '__main__':
parser.add_argument("-l", "--language", type=str, default='ja',
choices=language_code_list,
help="Language of the audio files.")
parser.add_argument("-p", "--precision", type=str, default='float16', choices=['float16','float32'],
help="fp16 or fp32")
parser.add_argument("-p", "--precision", type=str, default='float16', choices=['float16','float32','int8'],
help="fp16, int8 or fp32")
cmd = parser.parse_args()
output_file_path = execute_asr(
+43 -29
View File
@@ -4,24 +4,10 @@ import argparse
import os
import traceback
from tqdm import tqdm
# from funasr.utils import version_checker
# version_checker.check_for_update = lambda: None
from funasr import AutoModel
path_asr = 'tools/asr/models/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch'
path_vad = 'tools/asr/models/speech_fsmn_vad_zh-cn-16k-common-pytorch'
path_punc = 'tools/asr/models/punc_ct-transformer_zh-cn-common-vocab272727-pytorch'
path_asr = path_asr if os.path.exists(path_asr) else "iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch"
path_vad = path_vad if os.path.exists(path_vad) else "iic/speech_fsmn_vad_zh-cn-16k-common-pytorch"
path_punc = path_punc if os.path.exists(path_punc) else "iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch"
model = AutoModel(
model = path_asr,
model_revision = "v2.0.4",
vad_model = path_vad,
vad_model_revision = "v2.0.4",
punc_model = path_punc,
punc_model_revision = "v2.0.4",
)
def only_asr(input_file):
try:
@@ -40,6 +26,7 @@ def execute_asr(input_folder, output_folder, model_size, language):
for file_name in tqdm(input_file_names):
try:
print(file_name)
file_path = os.path.join(input_folder, file_name)
text = model.generate(input=file_path)[0]["text"]
output.append(f"{file_path}|{output_file_name}|{language.upper()}|{text}")
@@ -55,20 +42,47 @@ def execute_asr(input_folder, output_folder, model_size, language):
print(f"ASR 任务完成->标注文件路径: {output_file_path}\n")
return output_file_path
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input_folder", type=str, required=True,
help="Path to the folder containing WAV files.")
parser.add_argument("-o", "--output_folder", type=str, required=True,
help="Output folder to store transcriptions.")
parser.add_argument("-s", "--model_size", type=str, default='large',
help="Model Size of FunASR is Large")
parser.add_argument("-l", "--language", type=str, default='zh', choices=['zh'],
help="Language of the audio files.")
parser.add_argument("-p", "--precision", type=str, default='float16', choices=['float16','float32'],
help="fp16 or fp32")#还没接入
cmd = parser.parse_args()
parser = argparse.ArgumentParser()
parser.add_argument("-i", "--input_folder", type=str, required=True,
help="Path to the folder containing WAV files.")
parser.add_argument("-o", "--output_folder", type=str, required=True,
help="Output folder to store transcriptions.")
parser.add_argument("-s", "--model_size", type=str, default='large',
help="Model Size of FunASR is Large")
parser.add_argument("-l", "--language", type=str, default='zh', choices=['zh','yue','auto'],
help="Language of the audio files.")
parser.add_argument("-p", "--precision", type=str, default='float16', choices=['float16','float32'],
help="fp16 or fp32")#还没接入
cmd = parser.parse_args()
path_vad = 'tools/asr/models/speech_fsmn_vad_zh-cn-16k-common-pytorch'
path_punc = 'tools/asr/models/punc_ct-transformer_zh-cn-common-vocab272727-pytorch'
path_vad = path_vad if os.path.exists(path_vad) else "iic/speech_fsmn_vad_zh-cn-16k-common-pytorch"
path_punc = path_punc if os.path.exists(path_punc) else "iic/punc_ct-transformer_zh-cn-common-vocab272727-pytorch"
vad_model_revision=punc_model_revision="v2.0.4"
if(cmd.language=="zh"):
path_asr = 'tools/asr/models/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch'
path_asr = path_asr if os.path.exists(path_asr) else "iic/speech_paraformer-large_asr_nat-zh-cn-16k-common-vocab8404-pytorch"
model_revision="v2.0.4"
else:
path_asr = 'tools/asr/models/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online'
path_asr = path_asr if os.path.exists(path_asr) else "iic/speech_UniASR_asr_2pass-cantonese-CHS-16k-common-vocab1468-tensorflow1-online"
model_revision="master"
path_vad=path_punc=vad_model_revision=punc_model_revision=None###友情提示:粤语带VAD识别可能会有少量shape不对报错的,但是不带VAD可以.不带vad只能分阶段单独加标点。不过标点模型对粤语效果真的不行…
model = AutoModel(
model=path_asr,
model_revision=model_revision,
vad_model=path_vad,
vad_model_revision=vad_model_revision,
punc_model=path_punc,
punc_model_revision=punc_model_revision,
)
if __name__ == '__main__':
execute_asr(
input_folder = cmd.input_folder,
output_folder = cmd.output_folder,
+6
View File
@@ -9,6 +9,12 @@ def load_language_list(language):
language_list = json.load(f)
return language_list
def scan_language_list():
language_list = []
for name in os.listdir(I18N_JSON_DIR):
if name.endswith(".json"):language_list.append(name.split('.')[0])
return language_list
class I18nAuto:
def __init__(self, language=None):
if language in ["Auto", None]:
+15 -8
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR output log",
"GPT模型列表": "GPT weight list",
"GPT训练进程输出信息": "GPT training output log",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT sampling parameters (not too low when there's no reference text. Use default if unsure):",
"GPU卡号,只能填1个整数": "GPU number, can only input ONE integer",
"GPU卡号以-分割,每个卡号一个进程": "GPU number is separated by -, each GPU will run one process ",
"SSL进程输出信息": "SSL output log",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 opened ",
"UVR5进程输出信息": "UVR5 process output log",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix: proportion of normalized audio merged into dataset",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT sampling parameters (not too low when there's no reference text. Use default if unsure):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size: FO hop size, the smaller the value, the higher the accuracy)",
"max:归一化后最大值多少": "Loudness multiplier after normalized",
"max_sil_kept:切完后静音最多留多长": "Maximum length for silence to be kept",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "Multiple audio files can also be imported. If a folder path exists, this input is ignored.",
"人声伴奏分离批量处理, 使用UVR5模型。": "Batch processing for vocal and instrumental separation, using the UVR5 model.",
"人声提取激进程度": "Vocal extraction aggressiveness",
"以下文件或文件夹不存在:": "No Such File or Folder:",
"以下模型不存在:": "No Such Model:",
"伴奏人声分离&去混响&去回声": "Vocals/Accompaniment Separation & Reverberation Removal",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "When using the no-reference text mode, it is recommended to use a fine-tuned GPT. If the reference audio is unclear and you don't know what to write, you can enable this feature, which will ignore the reference text you've entered.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "When using the no-reference text mode, it is recommended to use a fine-tuned GPT. If the reference audio is unclear and you don't know what to write, you can enable this feature, which will ignore the reference text you've entered.",
"保存频率save_every_epoch": "Save frequency (save_every_epoch):",
"凑50字一切": "Cut per 50 characters",
"凑50字一切": "Slice per 50 characters",
"凑四句一切": "Slice once every 4 sentences",
"切分后文本": "Text after sliced",
"切分后的子音频的输出根目录": "Audio slicer output folder",
"切割使用的进程数": "CPU threads used for audio slicing",
"刷新模型路径": "refreshing model paths",
@@ -84,9 +85,9 @@
"参考音频的语种": "Language for reference audio",
"合成语音": "Start inference",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "An example of a valid folder path format: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例 (simply copy the address from the file manager's address bar).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": " Step-to-step phoneme transformation and modification coming soon!",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Please fill in the segmented audio files' directory! The full path of the audio file = the directory concatenated with the filename corresponding to the waveform in the list file (not the full path). If left blank, the absolute full path in the .list file will be used.",
"多语种混合": "Multilingual Mixed",
"多语种混合(粤语)": "Multilingual Mixed(Yue)",
"实际输入的参考文本:": "Actual Input Reference Text:",
"实际输入的目标文本(切句后):": "Actual Input Target Text (after sentence segmentation):",
"实际输入的目标文本(每句):": "Actual Input Target Text (per sentence):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Slice by Chinese punct",
"按标点符号切": "Slice by every punct",
"按英文句号.切": "Slice by English punct",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Text slicer tool, since there will be issues when infering long texts, so it is advised to cut first. When infering, it will infer respectively then combined together.",
"数据类型精度": "Computing precision",
"文本模块学习率权重": "Text model learning rate weighting",
"文本进程输出信息": "Text processing output",
"施工中,请静候佳音": "In construction, please wait",
@@ -121,7 +122,7 @@
"日英混合": "Japanese-English Mixed",
"是否仅保存最新的ckpt文件以节省硬盘空间": "Save only the latest '.ckpt' file to save disk space:",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "Save a small final model to the 'weights' folder at each save point:",
"是否开启TTS推理WebUI": "Open TTS inference WEBUI",
"是否开启TTS推理WebUI": "Open TTS inference WebUI",
"是否开启UVR5-WebUI": "Open UVR5-WebUI",
"是否开启dpo训练选项(实验性)": "Enable DPO training (experimental feature)",
"是否开启打标WebUI": "Open labelling WebUI",
@@ -132,6 +133,9 @@
"模型分为三类:": "Models are categorized into three types:",
"模型切换": "Model switch",
"每张显卡的batch_size": "Batch size per GPU:",
"版本": "Version",
"粤英混合": "Yue-English Mixed",
"粤语": "Yue",
"终止ASR进程": "Stop ASR task",
"终止GPT训练": "Stop GPT training",
"终止SSL提取进程": "Stop SSL extraction",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Audio slicer output log",
"语音降噪进程输出信息": "Voice Denoiser Process Output Information",
"请上传3~10秒内参考音频,超过会报错!": "Please upload a reference audio within the 3-10 second range; if it exceeds this duration, it will raise errors.",
"请上传参考音频": "Please Upload the Reference Audio",
"请填入推理文本": "Please Fill in the Terget Text",
"请输入有效文本": "Please enter valid text.",
"转换": "Convert",
"输入待处理音频文件夹路径": "Enter the path of the audio folder to be processed:",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Choose the models from SoVITS_weights and GPT_weights. The default one is a pretrain, so you can experience zero shot TTS.",
"降噪结果输出文件夹": "Denoised Results Output Folder",
"降噪音频文件输入文件夹": "Denoising Audio File Input Folder",
"需要合成的切分前文本": "Inference text that needs to be sliced",
"需要合成的文本": "Inference text",
"需要合成的语种": "Inference text language",
"韩文": "Korean",
"韩英混合": "Korean-English Mixed",
"音频自动切分输入路径,可文件可文件夹": "Audio slicer input (file or folder)",
"预训练的GPT模型路径": "Pretrained GPT model path",
"预训练的SSL模型路径": "Pretrained SSL model path",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "Información de salida del proceso ASR",
"GPT模型列表": "Lista de modelos GPT",
"GPT训练进程输出信息": "Información de salida del proceso de entrenamiento de GPT",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "Parámetros de muestreo de GPT (no demasiado bajos cuando no hay texto de referencia. Use los valores por defecto si no está seguro):",
"GPU卡号,只能填1个整数": "Número de tarjeta GPU, solo se puede ingresar un número entero",
"GPU卡号以-分割,每个卡号一个进程": "Número de tarjeta GPU separado por '-', cada número de tarjeta es un proceso",
"SSL进程输出信息": "Información de salida del proceso SSL",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 está habilitado",
"UVR5进程输出信息": "Información de salida del proceso UVR5",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix: proporción de mezcla de audio normalizado que entra",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "Parámetros de muestreo de GPT (no demasiado bajos cuando no hay texto de referencia. Use los valores por defecto si no está seguro):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size: cómo calcular la curva de volumen, cuanto más pequeño, mayor precisión pero mayor carga computacional (mayor precisión no significa mejor rendimiento)",
"max:归一化后最大值多少": "max: valor máximo después de la normalización",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept: duración máxima del silencio después del corte",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "También se pueden ingresar archivos de audio por lotes, seleccionar uno, prioridad para leer carpetas",
"人声伴奏分离批量处理, 使用UVR5模型。": "Procesamiento por lotes de separación de voz y acompañamiento utilizando el modelo UVR5",
"人声提取激进程度": "Nivel de agresividad en la extracción de voz",
"以下文件或文件夹不存在:": "No Existe Tal Archivo o Carpeta:",
"以下模型不存在:": "No Existe tal Modelo:",
"伴奏人声分离&去混响&去回声": "Separación de acompañamiento y voz principal y eliminación de reverberación y eco",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "Se recomienda usar un GPT ajustado en modo sin texto de referencia; habilítelo si no puede entender el audio de referencia (si no sabe qué escribir). Una vez habilitado, ignorará el texto de referencia ingresado.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "Se recomienda usar un GPT ajustado en modo sin texto de referencia; habilítelo si no puede entender el audio de referencia (si no sabe qué escribir). Una vez habilitado, ignorará el texto de referencia ingresado.",
"保存频率save_every_epoch": "Frecuencia de guardado (cada epoch)",
"凑50字一切": "Todo para alcanzar las 50 palabras",
"凑四句一切": "Completa cuatro oraciones para rellenar todo",
"切分后文本": "Texto después de la división",
"切分后的子音频的输出根目录": "Directorio raíz de salida de los sub-audios después de la división",
"切割使用的进程数": "Número de procesos utilizados para la división",
"刷新模型路径": "Actualizar la ruta del modelo",
@@ -84,9 +85,9 @@
"参考音频的语种": "Idioma del audio de referencia",
"合成语音": "Síntesis de voz",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Ejemplo de formato de ruta de carpeta válida: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例 (simplemente copie desde la barra de direcciones del administrador de archivos).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "En el futuro se admitirá la conversión de fonemas, la modificación manual de fonemas y la síntesis de voz paso a paso.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Ingrese el directorio donde se encuentran los audios después de la división. La ruta completa de los archivos de audio leídos = este directorio + nombre de archivo correspondiente en el archivo .list (no la ruta completa). Si se deja en blanco, se utilizará la ruta completa del archivo .list.",
"多语种混合": "Mezcla de varios idiomas",
"多语种混合(粤语)": "Mezcla Multilingüe (Cantonés)",
"实际输入的参考文本:": "Texto de referencia realmente ingresado:",
"实际输入的目标文本(切句后):": "Texto objetivo realmente ingresado (después de dividir en frases):",
"实际输入的目标文本(每句):": "Texto objetivo realmente ingresado (por frase):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Cortar según puntos en chino",
"按标点符号切": "Cortar según los signos de puntuación",
"按英文句号.切": "Cortar por puntos en inglés.",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Herramienta de división de texto. El resultado de la síntesis puede no ser bueno para textos demasiado largos, por lo que se recomienda dividirlos primero. La síntesis se realiza separando el texto según los saltos de línea y luego uniendo los fragmentos.",
"数据类型精度": "precisión del tipo de datos",
"文本模块学习率权重": "Peso de la tasa de aprendizaje del módulo de texto",
"文本进程输出信息": "Información de salida del proceso de obtención de texto",
"施工中,请静候佳音": "En construcción, por favor espere pacientemente",
@@ -132,6 +133,9 @@
"模型分为三类:": "Los modelos se dividen en tres categorías:",
"模型切换": "Cambio de modelo",
"每张显卡的batch_size": "Tamaño de lote por tarjeta gráfica",
"版本": "Versión",
"粤英混合": "Mezcla Cantonés-Inglés",
"粤语": "Cantonés",
"终止ASR进程": "Terminar el proceso ASR",
"终止GPT训练": "Detener entrenamiento de GPT",
"终止SSL提取进程": "Terminar el proceso de extracción SSL",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Información de salida del proceso de división de voz",
"语音降噪进程输出信息": "Información de salida del proceso de reducción de ruido de voz",
"请上传3~10秒内参考音频,超过会报错!": "Por favor, suba un audio de referencia de entre 3 y 10 segundos, ¡más de eso causará un error!",
"请上传参考音频": "Por Favor, Suba el Audio de Referencia",
"请填入推理文本": "Por Favor, Ingrese el Texto Objetivo",
"请输入有效文本": "Por favor, introduzca un texto válido",
"转换": "Convertir",
"输入待处理音频文件夹路径": "Ingrese la ruta de la carpeta de audio a procesar",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Seleccione el modelo almacenado en SoVITS_weights y GPT_weights después del entrenamiento. Uno de ellos es el modelo base, útil para experimentar con TTS de 5 segundos sin entrenamiento.",
"降噪结果输出文件夹": "Carpeta de salida de los resultados de reducción de ruido",
"降噪音频文件输入文件夹": "Carpeta de entrada de archivos de audio para reducción de ruido",
"需要合成的切分前文本": "Texto a sintetizar antes de la división",
"需要合成的文本": "Texto a sintetizar",
"需要合成的语种": "Idioma para la síntesis",
"韩文": "Coreano",
"韩英混合": "Mezcla Coreano-Inglés",
"音频自动切分输入路径,可文件可文件夹": "Ruta de entrada para la división automática de audio, puede ser un archivo o una carpeta",
"预训练的GPT模型路径": "Ruta del modelo GPT preentrenado",
"预训练的SSL模型路径": "Ruta del modelo SSL preentrenado",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "Informations de processus ASR",
"GPT模型列表": "Liste des modèles GPT",
"GPT训练进程输出信息": "Informations de processus d'entraînement GPT",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "Paramètres d'échantillonnage de GPT (ne pas mettre trop bas lorsqu'il n'y a pas de texte de référence. Utilisez les valeurs par défaut si vous n'êtes pas sûr):",
"GPU卡号,只能填1个整数": "Numéro de carte GPU, ne peut contenir qu'un seul entier",
"GPU卡号以-分割,每个卡号一个进程": "Numéro de carte GPU séparé par des tirets, un processus par numéro de carte",
"SSL进程输出信息": "Informations de processus SSL",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 est activé",
"UVR5进程输出信息": "Informations de processus UVR5",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix: proportion d'audio normalisé mélangé",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "Paramètres d'échantillonnage de GPT (ne pas mettre trop bas lorsqu'il n'y a pas de texte de référence. Utilisez les valeurs par défaut si vous n'êtes pas sûr):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size: comment calculer la courbe de volume, plus petit pour une précision plus élevée mais une charge de calcul plus élevée (ce n'est pas une meilleure précision)",
"max:归一化后最大值多少": "max: valeur maximale après normalisation",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept: durée maximale de silence après la coupe",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "Également possible d'entrer en lot des fichiers audio, au choix, privilégiez la lecture du dossier",
"人声伴奏分离批量处理, 使用UVR5模型。": "Traitement par lot de séparation voix-accompagnement en utilisant le modèle UVR5.",
"人声提取激进程度": "Degré d'extraction des voix",
"以下文件或文件夹不存在:": "Aucun fichier ou dossier de ce type:",
"以下模型不存在:": "Aucun Modèle de ce Type:",
"伴奏人声分离&去混响&去回声": "Séparation de la voix et de l'accompagnement, suppression de la réverbération et de l'écho",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "Il est recommandé d'utiliser GPT finement ajusté en mode sans texte de référence. Si vous ne comprenez pas ce que dit l'audio de référence (vous ne savez pas quoi écrire), vous pouvez l'activer ; une fois activé, ignorez le texte de référence saisi.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "Il est recommandé d'utiliser GPT finement ajusté en mode sans texte de référence. Si vous ne comprenez pas ce que dit l'audio de référence (vous ne savez pas quoi écrire), vous pouvez l'activer ; une fois activé, ignorez le texte de référence saisi.",
"保存频率save_every_epoch": "Fréquence de sauvegarde (sauvegarder à chaque époque)",
"凑50字一切": "Assembler 50 mots tout",
"凑四句一切": "Composez quatre phrases pour tout remplir",
"切分后文本": "Texte après découpage",
"切分后的子音频的输出根目录": "Répertoire racine de sortie des sous-audios après découpage",
"切割使用的进程数": "Nombre de processus utilisés pour le découpage",
"刷新模型路径": "Actualiser le chemin du modèle",
@@ -84,9 +85,9 @@
"参考音频的语种": "Langue de l'audio de référence",
"合成语音": "Synthèse vocale",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Exemple de format de chemin de dossier valide : E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例 (copiez-le depuis la barre d'adresse de l'explorateur de fichiers).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "Des fonctionnalités futures incluront la conversion en phonèmes, la modification manuelle des phonèmes et l'exécution par étapes de la synthèse vocale.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Veuillez indiquer le répertoire contenant les audio découpés ! Le chemin complet du fichier audio à lire = ce répertoire - nom du fichier correspondant à l'onde dans le fichier .list (pas le chemin complet). Si laissé vide, le chemin absolu dans le fichier .list sera utilisé.",
"多语种混合": "Mélange multilingue",
"多语种混合(粤语)": "Mélange Multilingue (Cantonais)",
"实际输入的参考文本:": "Texte de référence réellement saisi:",
"实际输入的目标文本(切句后):": "Texte cible réellement saisi (après découpage):",
"实际输入的目标文本(每句):": "Texte cible réellement saisi (par phrase):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Couper selon les points en chinois.",
"按标点符号切": "Couper selon les signes de ponctuation",
"按英文句号.切": "Découpez par des points en anglais",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Outil de découpage de texte. Un texte trop long peut ne pas donner un bon résultat, donc il est recommandé de le couper d'abord s'il est trop long. La synthèse se fera en séparant le texte par les sauts de ligne puis en les assemblant.",
"数据类型精度": "précision du type de données",
"文本模块学习率权重": "Poids du taux d'apprentissage du module de texte",
"文本进程输出信息": "Informations de processus de texte",
"施工中,请静候佳音": "En construction, veuillez attendre patiemment",
@@ -132,6 +133,9 @@
"模型分为三类:": "Les modèles sont classés en trois catégories:",
"模型切换": "Changement de modèle",
"每张显卡的batch_size": "Taille de lot par carte graphique",
"版本": "Version",
"粤英混合": "Mélange Cantonais-Anglais",
"粤语": "Cantonais",
"终止ASR进程": "Arrêter le processus ASR",
"终止GPT训练": "Arrêter l'entraînement GPT",
"终止SSL提取进程": "Arrêter le processus d'extraction SSL",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Informations de processus de découpage vocal",
"语音降噪进程输出信息": "Informations de sortie du processus de réduction du bruit vocal",
"请上传3~10秒内参考音频,超过会报错!": "Veuillez télécharger une référence audio de 3 à 10 secondes ; les fichiers plus longs généreront une erreur!",
"请上传参考音频": "Veuillez télécharger l'audio de référence",
"请填入推理文本": "Veuillez remplir le texte cible",
"请输入有效文本": "Veuillez entrer un texte valide",
"转换": "Conversion",
"输入待处理音频文件夹路径": "Entrez le chemin du dossier audio à traiter",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Choisissez le modèle entraîné stocké sous SoVITS_weights et GPT_weights. Par défaut, l'un d'eux est un modèle de base pour l'expérience de TTS Zero Shot de 5 secondes.",
"降噪结果输出文件夹": "Dossier de sortie des résultats de réduction du bruit",
"降噪音频文件输入文件夹": "Dossier d'entrée des fichiers audio de réduction du bruit",
"需要合成的切分前文本": "Texte préalable à la synthèse",
"需要合成的文本": "Texte à synthétiser",
"需要合成的语种": "Langue de synthèse requise",
"韩文": "Coreano",
"韩英混合": "Mezcla Coreano-Inglés",
"音频自动切分输入路径,可文件可文件夹": "Chemin d'entrée automatique de découpage audio, peut être un fichier ou un dossier",
"预训练的GPT模型路径": "Chemin du modèle GPT pré-entraîné",
"预训练的SSL模型路径": "Chemin du modèle SSL pré-entraîné",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "Informazioni sull'output del processo ASR",
"GPT模型列表": "Elenco dei modelli GPT",
"GPT训练进程输出信息": "Informazioni sull'output del processo di allenamento di GPT",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "Parametri di campionamento di GPT (non troppo bassi quando non c'è testo di riferimento. Utilizzare i valori predefiniti in caso di incertezza):",
"GPU卡号,只能填1个整数": "Numero della scheda grafica, può essere inserito solo un numero intero",
"GPU卡号以-分割,每个卡号一个进程": "Numero di GPU separati da '-'; ogni numero corrisponde a un processo",
"SSL进程输出信息": "Informazioni sull'output del processo SSL",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 è attivato",
"UVR5进程输出信息": "Informazioni sull'output del processo UVR5",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix: Quanta proporzione dell'audio normalizzato deve essere miscelata",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "Parametri di campionamento di GPT (non troppo bassi quando non c'è testo di riferimento. Utilizzare i valori predefiniti in caso di incertezza):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size: Come calcolare la curva del volume. Più piccolo è, maggiore è la precisione ma aumenta la complessità computazionale (non significa che una maggiore precisione dà risultati migliori)",
"max:归一化后最大值多少": "max: Massimo valore dopo la normalizzazione",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept: Massima durata del silenzio dopo il taglio",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "È possibile anche inserire file audio in batch, una delle due opzioni, con priorità alla lettura della cartella",
"人声伴奏分离批量处理, 使用UVR5模型。": "Separazione voce-accompagnamento in batch, utilizza il modello UVR5.",
"人声提取激进程度": "Grado di aggressività dell'estrazione vocale",
"以下文件或文件夹不存在:": "Nessun file o cartella trovati:",
"以下模型不存在:": "Nessun Modello del Genere:",
"伴奏人声分离&去混响&去回声": "Separazione tra accompagnamento e voce & Rimozione dell'eco & Rimozione dell'eco",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "Si consiglia di utilizzare GPT fine-tuned quando si utilizza la modalità senza testo di riferimento. Se non si riesce a capire cosa dice l'audio di riferimento (e non si sa cosa scrivere), è possibile abilitare questa opzione, ignorando il testo di riferimento inserito.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "Si consiglia di utilizzare GPT fine-tuned quando si utilizza la modalità senza testo di riferimento. Se non si riesce a capire cosa dice l'audio di riferimento (e non si sa cosa scrivere), è possibile abilitare questa opzione, ignorando il testo di riferimento inserito.",
"保存频率save_every_epoch": "Frequenza di salvataggio ogni epoca",
"凑50字一切": "Riempire con 50 caratteri per tutto",
"凑四句一切": "Riempire con quattro frasi per tutto",
"切分后文本": "Testo dopo il taglio",
"切分后的子音频的输出根目录": "Directory radice di output per gli audio segmentati",
"切割使用的进程数": "Numero di processi utilizzati per il taglio",
"刷新模型路径": "Aggiorna il percorso del modello",
@@ -84,9 +85,9 @@
"参考音频的语种": "Lingua dell'audio di riferimento",
"合成语音": "Sintesi vocale",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Formato di percorso della cartella valido: E:\\codes\\py39\\vits_vc_gpu\\Esempio di test di BaiLuShuangHua (copiare direttamente dalla barra degli indirizzi del gestore file).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "In futuro, sarà supportata la conversione in fonemi, la modifica manuale dei fonemi e l'esecuzione passo-passo della sintesi vocale.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Inserisci la directory dell'audio segmentato! Il percorso completo del file audio letto = questa directory - unione del nome del file corrispondente alle forme d'onda nel file .list (non il percorso completo). Se lasciato vuoto, verrà utilizzato il percorso assoluto nel file .list.",
"多语种混合": "Mix multilingue",
"多语种混合(粤语)": "Misto Multilingue (Cantonese)",
"实际输入的参考文本:": "Testo di riferimento effettivamente inserito:",
"实际输入的目标文本(切句后):": "Testo di destinazione effettivamente inserito (dopo il taglio delle frasi):",
"实际输入的目标文本(每句):": "Testo di destinazione effettivamente inserito (per frase):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Taglia secondo il punto cinese.",
"按标点符号切": "Taglia secondo i segni di punteggiatura",
"按英文句号.切": "Taglia secondo il punto inglese",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Strumento di divisione del testo. I testi troppo lunghi potrebbero non avere un buon effetto di sintesi, quindi è consigliabile dividerli prima della sintesi. La sintesi verrà separata in base ai ritorni a capo nel testo e successivamente ricomposta.",
"数据类型精度": "precisione del tipo di dati",
"文本模块学习率权重": "Peso del tasso di apprendimento del modulo di testo",
"文本进程输出信息": "Informazioni sull'output del processo di estrazione del testo",
"施工中,请静候佳音": "In costruzione, attendi pazientemente le buone notizie",
@@ -132,6 +133,9 @@
"模型分为三类:": "I modelli sono divisi in tre categorie:",
"模型切换": "Cambio del modello",
"每张显卡的batch_size": "Batch size per ogni scheda grafica",
"版本": "Versione",
"粤英混合": "Misto Cantonese-Inglese",
"粤语": "Cantonese",
"终止ASR进程": "Terminare il processo ASR",
"终止GPT训练": "Terminare l'allenamento di GPT",
"终止SSL提取进程": "Terminare il processo di estrazione SSL",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Informazioni sull'output del processo di segmentazione vocale",
"语音降噪进程输出信息": "Informazioni sull'output del processo di riduzione del rumore vocale",
"请上传3~10秒内参考音频,超过会报错!": "Carica un audio di riferimento della durata compresa tra 3 e 10 secondi. Superiore a questo, verrà generato un errore!",
"请上传参考音频": "Si prega di caricare l'audio di riferimento",
"请填入推理文本": "Si prega di inserire il testo di destinazione",
"请输入有效文本": "Inserisci un testo valido",
"转换": "Converti",
"输入待处理音频文件夹路径": "Inserisci il percorso della cartella dei file audio da elaborare",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Scegli il modello salvato in SoVITS_weights e GPT_weights dopo l'addestramento. Uno di default è il modello di base, utilizzato per l'esperienza di Zero Shot TTS in 5 secondi.",
"降噪结果输出文件夹": "Cartella di output dei risultati di riduzione del rumore",
"降噪音频文件输入文件夹": "Cartella di input dei file audio per la riduzione del rumore",
"需要合成的切分前文本": "Testo da sintetizzare prima del taglio",
"需要合成的文本": "Testo da sintetizzare",
"需要合成的语种": "Lingua da sintetizzare",
"韩文": "Coreano",
"韩英混合": "Misto Coreano-Inglese",
"音频自动切分输入路径,可文件可文件夹": "Percorso di input per la segmentazione automatica dell'audio, può essere un file o una cartella",
"预训练的GPT模型路径": "Percorso del modello preaddestrato GPT",
"预训练的SSL模型路径": "Percorso del modello SSL preaddestrato",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASRプロセスの出力情報",
"GPT模型列表": "GPTモデルリスト",
"GPT训练进程输出信息": "GPTトレーニングプロセスの出力情報",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT サンプリングパラメーター(参照テキストがない場合はあまり低くしないでください。わからない場合はデフォルトを使用してください):",
"GPU卡号,只能填1个整数": "GPU番号、1つの整数しか入力できません",
"GPU卡号以-分割,每个卡号一个进程": "GPUカード番号はハイフンで区切り、各カード番号ごとに1つのプロセスが実行されます",
"SSL进程输出信息": "SSLプロセスの出力情報",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5がオンになっています",
"UVR5进程输出信息": "UVR5プロセスの出力情報",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:正規化後のオーディオが入る割合",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT サンプリングパラメーター(参照テキストがない場合はあまり低くしないでください。わからない場合はデフォルトを使用してください):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size: 音量曲線の計算方法、小さいほど精度が高くなりますが、計算量が増加します(精度が高いほど必ずしも効果が良いわけではありません)",
"max:归一化后最大值多少": "max:正規化後の最大値",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:切り終えた後、最大でどれだけ静かにするか",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "複数のオーディオファイルもインポートできます。フォルダパスが存在する場合、この入力は無視されます。",
"人声伴奏分离批量处理, 使用UVR5模型。": "人声と伴奏の分離をバッチ処理で行い、UVR5モデルを使用します。",
"人声提取激进程度": "人声抽出の積極性",
"以下文件或文件夹不存在:": "そのようなファイルやフォルダは存在しません:",
"以下模型不存在:": "モデルが存在しません:",
"伴奏人声分离&去混响&去回声": "ボーカル/伴奏の分離と残響の除去",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "参考テキストなしモードを使用する場合は、微調整されたGPTの使用をお勧めします。参考音声が聞き取れない場合(何を書けば良いかわからない場合)は、有効にすると、入力した参考テキストを無視します。",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "参考テキストなしモードを使用する場合は、微調整されたGPTの使用をお勧めします。参考音声が聞き取れない場合(何を書けば良いかわからない場合)は、有効にすると、入力した参考テキストを無視します。",
"保存频率save_every_epoch": "保存頻度save_every_epoch",
"凑50字一切": "50文字ずつカット",
"凑四句一切": "4つの文で埋める",
"切分后文本": "分割後のテキスト",
"切分后的子音频的输出根目录": "分割後のサブオーディオの出力ルートディレクトリ",
"切割使用的进程数": "分割に使用されるプロセス数",
"刷新模型路径": "モデルのパスを更新",
@@ -84,9 +85,9 @@
"参考音频的语种": "参照オーディオの言語",
"合成语音": "推論を開始",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "適切なフォルダパスの例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华テストサンプル(ファイルマネージャのアドレスバーからコピーしてください)。",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "今後、音素変換、手動音素修正、音声合成の段階的実行をサポートする予定です。",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "切断後の音声ファイルが格納されているディレクトリを入力してください!読み取り対象の音声ファイルの完全パス = このディレクトリ - 結合 - listファイル内の波形に対応するファイル名(完全パスではありません)。空白の場合、.listファイル内の絶対完全パスを使用します。",
"多语种混合": "多言語混合",
"多语种混合(粤语)": "多言語混合(粤語)",
"实际输入的参考文本:": "実際に入力された参照テキスト:",
"实际输入的目标文本(切句后):": "実際に入力された目標テキスト(文分割後):",
"实际输入的目标文本(每句):": "実際に入力された目標テキスト(文ごと):",
@@ -113,7 +114,7 @@
"按中文句号。切": "中国語の句点でカット",
"按标点符号切": "句読点で分割",
"按英文句号.切": "英文のピリオドで切ってください",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "テキストスライサーツール。長文を変換すると効果が不安定になる可能性があるため、長文の場合は事前に切り分けることをお勧めします。推論時には、テキストを個別に推論し、それを組み合わせて再構築します。",
"数据类型精度": "データ型の精度",
"文本模块学习率权重": "テキストモジュールの学習率の重み",
"文本进程输出信息": "テキストプロセスの出力情報",
"施工中,请静候佳音": "施工中、お待ちください",
@@ -132,6 +133,9 @@
"模型分为三类:": "モデルは3種類に分かれています:",
"模型切换": "モデル切り替え",
"每张显卡的batch_size": "各グラフィックカードのバッチサイズ",
"版本": "バージョン",
"粤英混合": "粤英混合",
"粤语": "粤語",
"终止ASR进程": "ASRプロセスを停止",
"终止GPT训练": "GPTトレーニングを停止",
"终止SSL提取进程": "SSL抽出プロセスを停止",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "音声分割プロセスの出力情報",
"语音降噪进程输出信息": "音声ノイズ除去プロセスの出力情報",
"请上传3~10秒内参考音频,超过会报错!": "3~10秒以内の参照音声をアップロードしてください。それを超えるとエラーが発生します!",
"请上传参考音频": "リファレンスオーディオをアップロードしてください",
"请填入推理文本": "ターゲットテキストを入力してください",
"请输入有效文本": "有効なテキストを入力してください",
"转换": "変換",
"输入待处理音频文件夹路径": "処理するオーディオフォルダのパスを入力してください:",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "SoVITS_weightsおよびGPT_weightsに保存されたモデルを選択します。デフォルトのものはプレトレインであり、ゼロショットTTSを体験できます。",
"降噪结果输出文件夹": "ノイズ除去結果出力フォルダ",
"降噪音频文件输入文件夹": "ノイズ除去音声ファイル入力フォルダ",
"需要合成的切分前文本": "推論が必要な分割前のテキスト",
"需要合成的文本": "推論テキスト",
"需要合成的语种": "推論テキストの言語",
"韩文": "韓国語",
"韩英混合": "韓英混合",
"音频自动切分输入路径,可文件可文件夹": "オーディオの自動分割入力パス、ファイルまたはフォルダを指定できます",
"预训练的GPT模型路径": "事前にトレーニングされたGPTモデルのパス",
"预训练的SSL模型路径": "事前にトレーニングされたSSLモデルのパス",
+14 -7
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR 프로세스 출력 정보",
"GPT模型列表": "GPT 모델 목록",
"GPT训练进程输出信息": "GPT 훈련 프로세스 출력 정보",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 샘플링 매개변수 (참조 텍스트가 없을 때 너무 낮게 설정하지 마십시오. 확실하지 않으면 기본값을 사용하십시오):",
"GPU卡号,只能填1个整数": "GPU 카드 번호, 1개의 정수만 입력 가능",
"GPU卡号以-分割,每个卡号一个进程": "GPU 카드 번호는 -로 구분되며 각 카드 번호에 하나의 프로세스가 있어야 함",
"SSL进程输出信息": "SSL 프로세스 출력 정보",
@@ -50,13 +51,12 @@
"UVR5已开启": "UVR5가 활성화되었습니다",
"UVR5进程输出信息": "UVR5 프로세스 출력 정보",
"alpha_mix:混多少比例归一化后音频进来": "알파 믹스: 정규화된 오디오가 들어오는 비율",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 샘플링 매개변수 (참조 텍스트가 없을 때 너무 낮게 설정하지 마십시오. 확실하지 않으면 기본값을 사용하십시오):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop 크기: 볼륨 곡선을 계산하는 방법. 작을수록 정확도가 높아지지만 계산량이 높아집니다 (정확도가 높다고 효과가 좋아지지 않음)",
"max:归一化后最大值多少": "최대 값 (정규화 후)",
"max_sil_kept:切完后静音最多留多长": "최대 유지되는 정적 길이 (분리 후)",
"min_interval:最短切割间隔": "최소 분리 간격",
"min_length:每段最小多长,如果第一段太短一直和后面段连起来直到超过这个值": "min_length:각 부분의 최소 길이, 첫 번째 부분이 너무 짧으면 다음 부분과 계속 연결하여 이 값을 초과할 때까지",
"temperature": "온도",
"temperature": "temperature",
"threshold:音量小于这个值视作静音的备选切割点": "임계 값: 이 값보다 작은 볼륨은 대체 분리 지점으로 간주됩니다.",
"top_k": "top_k",
"top_p": "top_p",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "오디오 파일을 일괄로 입력할 수도 있습니다. 둘 중 하나를 선택하고 폴더를 읽기를 우선합니다.",
"人声伴奏分离批量处理, 使用UVR5模型。": "보컬과 반주 분리 배치 처리, UVR5 모델 사용.",
"人声提取激进程度": "보컬 추출의 공격성",
"以下文件或文件夹不存在:": "해당 파일 또는 폴더가 존재하지 않습니다:",
"以下模型不存在:": "해당 모델이 존재하지 않습니다:",
"伴奏人声分离&去混响&去回声": "반주 및 보컬 분리 & 리버브 제거 & 에코 제거",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "참고 텍스트가 없을 때는 미세 조정된 GPT를 사용하는 것이 좋습니다. 참고 오디오에서 무엇을 말하는지 잘 들리지 않으면 이 모드를 켜서 입력한 참고 텍스트를 무시할 수 있습니다.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "참고 텍스트가 없을 때는 미세 조정된 GPT를 사용하는 것이 좋습니다. 참고 오디오에서 무엇을 말하는지 잘 들리지 않으면 이 모드를 켜서 입력한 참고 텍스트를 무시할 수 있습니다.",
"保存频率save_every_epoch": "저장 빈도 (각 라운드마다)",
"凑50字一切": "50자를 채우십시오",
"凑四句一切": "네 문장의 세트를 완성하세요.",
"切分后文本": "분리된 텍스트",
"切分后的子音频的输出根目录": "분리된 하위 오디오의 출력 기본 디렉터리",
"切割使用的进程数": "사용되는 프로세스 수로 자르기",
"刷新模型路径": "모델 경로 새로 고침",
@@ -84,9 +85,9 @@
"参考音频的语种": "참고 오디오의 언어",
"合成语音": "합성 음성",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "적절한 폴더 경로 형식 예: E:\\codes\\py39\\vits_vc_gpu\\백로서리 테스트 샘플 (파일 관리자 주소 표시줄에서 복사하면 됩니다).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "앞으로 음소 변환, 음소 수동 수정, 음성 합성 단계별 실행을 지원할 예정입니다.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "분리된 오디오가 위치한 디렉터리를 입력하세요! 읽어들인 오디오 파일의 전체 경로 = 이 디렉터리 - list 파일에서 파형에 해당하는 파일명(전체 경로가 아님). 비워 두면 .list 파일의 절대 전체 경로를 사용합니다.",
"多语种混合": "다국어 혼합",
"多语种混合(粤语)": "다국어 혼합(粤語)",
"实际输入的参考文本:": "실제 입력된 참고 텍스트:",
"实际输入的目标文本(切句后):": "실제 입력된 목표 텍스트(문장 분리 후):",
"实际输入的目标文本(每句):": "실제 입력된 목표 텍스트(문장별):",
@@ -113,7 +114,7 @@
"按中文句号。切": "중국어 문장으로 분리하십시오.",
"按标点符号切": "구두점을 기준으로 자르기",
"按英文句号.切": "영어 문장으로 분리하기",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "텍스트 분리 도구. 너무 긴 텍스트는 합성 결과가 항상 좋지 않을 수 있으므로 너무 길면 먼저 분리하는 것이 좋습니다. 합성은 텍스트 줄 바꿈을 기준으로 분리되어 다시 조합됩니다.",
"数据类型精度": "데이터 유형 정밀도",
"文本模块学习率权重": "텍스트 모듈 학습률 가중치",
"文本进程输出信息": "텍스트 프로세스 출력 정보",
"施工中,请静候佳音": "공사 중입니다. 기다려주십시오.",
@@ -132,6 +133,9 @@
"模型分为三类:": "모델은 3가지로 나뉩니다:",
"模型切换": "모델 전환",
"每张显卡的batch_size": "각 그래픽 카드의 배치 크기",
"版本": "버전",
"粤英混合": "粤영 혼합",
"粤语": "粤語",
"终止ASR进程": "ASR 프로세스 종료",
"终止GPT训练": "GPT 훈련 종료",
"终止SSL提取进程": "SSL 추출 프로세스 종료",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "음성 분리 프로세스 출력 정보",
"语音降噪进程输出信息": "음성 노이즈 제거 프로세스 출력 정보",
"请上传3~10秒内参考音频,超过会报错!": "3~10초 이내의 참고 오디오를 업로드하십시오. 초과하면 오류가 발생합니다!",
"请上传参考音频": "참고 오디오를 업로드하세요",
"请填入推理文本": "목표 텍스트를 입력하세요",
"请输入有效文本": "유효한 텍스트를 입력하세요",
"转换": "변환",
"输入待处理音频文件夹路径": "처리 대기 중인 오디오 폴더 경로 입력",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "SoVITS_weights 및 GPT_weights에 저장된 훈련 완료된 모델 중 선택. 기본적으로 하나는 기본 모델이며 5초 Zero Shot TTS를 체험할 수 있습니다.",
"降噪结果输出文件夹": "노이즈 제거 결과 출력 폴더",
"降噪音频文件输入文件夹": "노이즈 제거 오디오 파일 입력 폴더",
"需要合成的切分前文本": "합성해야 할 분할 전 텍스트",
"需要合成的文本": "합성해야 할 텍스트",
"需要合成的语种": "합성해야 할 언어",
"韩文": "한국어",
"韩英混合": "한영 혼합",
"音频自动切分输入路径,可文件可文件夹": "오디오 자동 분리 입력 경로, 파일 또는 폴더 가능",
"预训练的GPT模型路径": "사전 훈련된 GPT 모델 경로",
"预训练的SSL模型路径": "사전 훈련된 SSL 모델 경로",
+14 -7
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "Informações de saída do processo ASR",
"GPT模型列表": "Lista de modelos GPT",
"GPT训练进程输出信息": "Informações de saída do processo de treinamento GPT",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "Parâmetros de amostragem do GPT (não muito baixos quando não houver texto de referência. Use o padrão se não tiver certeza):",
"GPU卡号,只能填1个整数": "Número da placa de vídeo, só é possível preencher com um número inteiro",
"GPU卡号以-分割,每个卡号一个进程": "Número da placa de vídeo dividido por-, cada número de placa é um processo",
"SSL进程输出信息": "Informações de saída do processo SSL",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 está ativado",
"UVR5进程输出信息": "Informações de saída do processo UVR5",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix: Em que proporção o áudio normalizado é misturado de volta",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "Parâmetros de amostragem do GPT (não muito baixos quando não houver texto de referência. Use o padrão se não tiver certeza):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "HOP_SIZE: Como calcular a curva de volume, quanto menor a precisão, maior a quantidade de cálculos (não significa que quanto maior a precisão, melhor o efeito)",
"max:归一化后最大值多少": "MAX: Qual é o valor máximo após a normalização?",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept: Depois de cortar, por quanto tempo no máximo o silêncio é mantido",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "Também é possível inserir arquivos de áudio em lote; escolha uma opção, preferencialmente leia a pasta.",
"人声伴奏分离批量处理, 使用UVR5模型。": "Processamento em lote de separação de voz e acompanhamento, usando o modelo UVR5.",
"人声提取激进程度": "Grau de agressividade da extração de voz",
"以下文件或文件夹不存在:": "Nenhum Arquivo ou Pasta Encontrado:",
"以下模型不存在:": "Nenhum Modelo Tal:",
"伴奏人声分离&去混响&去回声": "Separação de acompanhamento e voz & remoção de reverberação & remoção de eco",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "Ao usar o modo sem texto de referência, recomenda-se usar um GPT ajustado. Se não conseguir ouvir claramente o áudio de referência (não sabe o que escrever), você pode ativar o modo e ignorar o texto de referência fornecido.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "Ao usar o modo sem texto de referência, recomenda-se usar um GPT ajustado. Se não conseguir ouvir claramente o áudio de referência (não sabe o que escrever), você pode ativar o modo e ignorar o texto de referência fornecido.",
"保存频率save_every_epoch": "Frequência de salvamento save_every_epoch",
"凑50字一切": "Complete com 50 caracteres",
"凑四句一切": "Complete com quatro frases",
"切分后文本": "Texto após divisão",
"切分后的子音频的输出根目录": "Diretório raiz de saída do sub-áudio após o corte",
"切割使用的进程数": "Número de processos para corte",
"刷新模型路径": "Atualizar caminho do modelo",
@@ -84,9 +85,9 @@
"参考音频的语种": "Idioma do áudio de referência",
"合成语音": "Voz sintetizada",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Exemplo de formato de caminho de pasta válido: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例 (copie do endereço da barra do gerenciador de arquivos).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "Futuramente, serão suportadas a conversão de fonemas, a modificação manual de fonemas e a execução em etapas da síntese de voz.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Preencha o diretório onde os áudios cortados estão localizados! O caminho completo dos arquivos de áudio lidos = este diretório - concatenação com o nome do arquivo de forma correspondente no arquivo .list (não o caminho completo). Se deixar em branco, use o caminho absoluto no arquivo .list.",
"多语种混合": "Mistura de múltiplos idiomas",
"多语种混合(粤语)": "Mistura Multilíngue (Yue)",
"实际输入的参考文本:": "Texto de referência realmente inserido:",
"实际输入的目标文本(切句后):": "Texto alvo realmente inserido (após divisão de frases):",
"实际输入的目标文本(每句):": "Texto alvo realmente inserido (por frase):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Dividir por ponto final chinês",
"按标点符号切": "Dividir por sinais de pontuação",
"按英文句号.切": "Dividir por ponto final em inglês",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Ferramenta de divisão de texto. Textos muito longos podem não ter bons resultados de síntese, então é recomendado dividir textos muito longos primeiro. A síntese será feita dividindo e recombinando com base nas quebras de linha do texto.",
"数据类型精度": "precisão do tipo de dado",
"文本模块学习率权重": "Weight da taxa de aprendizado do módulo de texto",
"文本进程输出信息": "Informações de saída do processo de texto",
"施工中,请静候佳音": "Em construção, por favor, aguarde por um bom som",
@@ -122,7 +123,7 @@
"是否仅保存最新的ckpt文件以节省硬盘空间": "Se deve salvar apenas o último arquivo CKPT para economizar espaço em disco",
"是否在每次保存时间点将最终小模型保存至weights文件夹": "Se deve salvar o modelo pequeno final na pasta Weights em cada ponto de salvamento de tempo",
"是否开启TTS推理WebUI": "Se deseja ativar o webui de raciocínio TTS",
"是否开启UVR5-WebUI": "Se deseja ativar a UVR5-WEBUI",
"是否开启UVR5-WebUI": "Se deseja ativar a UVR5-WebUI",
"是否开启dpo训练选项(实验性)": "Se deseja ativar a opção de treinamento DPO (experimental)",
"是否开启打标WebUI": "Se deseja abrir o webui de marcação",
"是否直接对上次合成结果调整语速。防止随机性。": "Se deve ajustar diretamente a velocidade da fala do último resultado de síntese para evitar aleatoriedade.",
@@ -132,6 +133,9 @@
"模型分为三类:": "Modelos dividem-se em três categorias:",
"模型切换": "Troca de modelo",
"每张显卡的batch_size": "Tamanho do lote de cada placa de vídeo",
"版本": "Versão",
"粤英混合": "Mistura Yue-Inglês",
"粤语": "Yue",
"终止ASR进程": "Encerrar processo ASR",
"终止GPT训练": "Encerrar treinamento GPT",
"终止SSL提取进程": "Encerrar processo de extração SSL",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Informações de saída do processo de corte de voz",
"语音降噪进程输出信息": "Informações de saída do processo de redução de ruído de voz",
"请上传3~10秒内参考音频,超过会报错!": "Por favor, faça upload de um áudio de referência com duração entre 3 e 10 segundos. Áudios fora dessa faixa causarão erro!",
"请上传参考音频": "Por Favor, Carregue o Áudio de Referência",
"请填入推理文本": "Por Favor, Preencha o Texto de Inferência",
"请输入有效文本": "Por favor, insira um texto válido",
"转换": "Converter",
"输入待处理音频文件夹路径": "Caminho da pasta de arquivos de áudio a ser processados",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Selecione os modelos armazenados em Sovits_weights e GPT_WEIGHTS. O padrão é o modelo inferior, experiência para 5 segundos de Zero Shot TTS",
"降噪结果输出文件夹": "Pasta de saída dos resultados de redução de ruído",
"降噪音频文件输入文件夹": "Pasta de entrada dos arquivos de áudio para redução de ruído",
"需要合成的切分前文本": "Texto a ser sintetizado antes da divisão",
"需要合成的文本": "Texto a ser sintetizado",
"需要合成的语种": "Idioma a ser sintetizado",
"韩文": "Coreano",
"韩英混合": "Mistura Coreano-Inglês",
"音频自动切分输入路径,可文件可文件夹": "Caminho de entrada automático de corte de áudio, pode ser um arquivo ou uma pasta",
"预训练的GPT模型路径": "Caminho do modelo GPT pre-train",
"预训练的SSL模型路径": "Caminho do modelo SSL pre-train",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "Информация о процессе ASR",
"GPT模型列表": "Список моделей GPT",
"GPT训练进程输出信息": "Информация о процессе обучения GPT",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "Параметры выборки GPT (не устанавливайте слишком низкие значения, если нет ссылочного текста. Используйте значения по умолчанию, если не уверены):",
"GPU卡号,只能填1个整数": "Номер GPU, можно указать только одно целое число",
"GPU卡号以-分割,每个卡号一个进程": "Номера GPU разделяются дефисом, на каждый номер отдельный процесс",
"SSL进程输出信息": "Информация о процессе SSL",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 включен",
"UVR5进程输出信息": "Вывод информации процесса UVR5",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:Какая доля нормализованного аудио смешивается",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "Параметры выборки GPT (не устанавливайте слишком низкие значения, если нет ссылочного текста. Используйте значения по умолчанию, если не уверены):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size:Как рассчитывается кривая громкости, чем меньше, тем выше точность и больше вычислительная нагрузка (большая точность не всегда означает лучший результат)",
"max:归一化后最大值多少": "max:Максимальное значение после нормализации",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:Максимальная длительность тишины после разреза",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "Можно также импортировать несколько аудиофайлов. Если путь к папке существует, то этот ввод игнорируется.",
"人声伴奏分离批量处理, 使用UVR5模型。": "Обработка разделения вокала и аккомпанемента пакетно с использованием модели UVR5.",
"人声提取激进程度": "Степень агрессивности извлечения вокала",
"以下文件或文件夹不存在:": "Нет такого файла или папки:",
"以下模型不存在:": "Этот модель не существует",
"伴奏人声分离&去混响&去回声": "Разделение вокала/аккомпанемента и удаление эхо",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "При использовании режима без референсного текста рекомендуется использовать настроенную модель GPT. Если не удается разобрать, что говорит референсное аудио (не знаете, что писать), можете включить этот режим, и он проигнорирует введенный референсный текст.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "При использовании режима без референсного текста рекомендуется использовать настроенную модель GPT. Если не удается разобрать, что говорит референсное аудио (не знаете, что писать), можете включить этот режим, и он проигнорирует введенный референсный текст.",
"保存频率save_every_epoch": "Частота сохранения save_every_epoch",
"凑50字一切": "Соберите все в 50 символов",
"凑四句一切": "Собрать четыре предложения и разрезать",
"切分后文本": "Текст после разделения",
"切分后的子音频的输出根目录": "Корневой каталог вывода для подаудио после разделения",
"切割使用的进程数": "Количество процессов, используемых для разрезания",
"刷新模型路径": "Обновить путь к модели",
@@ -84,9 +85,9 @@
"参考音频的语种": "Язык референтного аудио",
"合成语音": "Синтезированный голос",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Пример допустимого формата пути к папке: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例 (просто скопируйте из адресной строки файлового менеджера).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "В будущем будет поддерживаться преобразование в фонемы, ручная коррекция фонем, пошаговая синтезация речи.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Заполните каталог, где находятся аудиофайлы после разрезания! Полный путь к читаемым аудиофайлам = каталог - файл .list, имя файла соответствует волне (не полный путь). Если оставить пустым, будет использоваться абсолютный путь из файла .list.",
"多语种混合": "Смешанные языки",
"多语种混合(粤语)": "Многоязычная смесь (кантонский)",
"实际输入的参考文本:": "Фактически введенный референсный текст:",
"实际输入的目标文本(切句后):": "Фактически введенный целевой текст (после разбиения на предложения):",
"实际输入的目标文本(每句):": "Фактически введенный целевой текст (каждое предложение):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Разделение по китайским точкам.",
"按标点符号切": "Разрезать по пунктуационным знакам",
"按英文句号.切": "Разрезать по английской точке.",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Инструмент для разделения текста. Слишком длинные тексты могут не давать хороших результатов синтеза, поэтому рекомендуется сначала их разделить. Синтез будет выполняться отдельно для каждого абзаца, а затем результаты будут соединены вместе.",
"数据类型精度": "точность типа данных",
"文本模块学习率权重": "Веса скорости обучения текстового модуля",
"文本进程输出信息": "Информация о процессе обработки текста",
"施工中,请静候佳音": "В разработке, ожидайте хороших новостей",
@@ -132,6 +133,9 @@
"模型分为三类:": "Модели делятся на три типа:",
"模型切换": "Переключение модели",
"每张显卡的batch_size": "Размер пакета для каждой видеокарты",
"版本": "Версия",
"粤英混合": "Кантоно-английская смесь",
"粤语": "Кантонийский",
"终止ASR进程": "Прекратить процесс ASR",
"终止GPT训练": "Прекратить обучение GPT",
"终止SSL提取进程": "Прекратить процесс извлечения SSL",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Информация о процессе разрезания речи",
"语音降噪进程输出信息": "Информация о процессе шумоподавления",
"请上传3~10秒内参考音频,超过会报错!": "Пожалуйста, загрузите референтное аудио длительностью от 3 до 10 секунд, иначе будет ошибка!",
"请上传参考音频": "Пожалуйста, загрузите эталонное аудио",
"请填入推理文本": "Пожалуйста, введите целевой текст",
"请输入有效文本": "Введите действительный текст",
"转换": "Преобразовать",
"输入待处理音频文件夹路径": "Путь к папке с аудиофайлами для обработки:",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Выберите модель, сохраненную в SoVITS_weights и GPT_weights после обучения. По умолчанию используется базовая модель для 5-секундного Zero Shot TTS.",
"降噪结果输出文件夹": "Папка для вывода результатов шумоподавления",
"降噪音频文件输入文件夹": "Папка для ввода аудиофайлов для шумоподавления",
"需要合成的切分前文本": "Текст для синтеза до разделения",
"需要合成的文本": "Текст для синтеза",
"需要合成的语种": "Язык для синтеза",
"韩文": "Корейский",
"韩英混合": "Корейско-английская смесь",
"音频自动切分输入路径,可文件可文件夹": "Путь ввода для автоматического разделения аудио, может быть файлом или папкой",
"预训练的GPT模型路径": "Путь к предварительно обученной модели GPT",
"预训练的SSL模型路径": "Путь к предварительно обученной модели SSL",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR işlemi çıktı bilgisi",
"GPT模型列表": "GPT model listesi",
"GPT训练进程输出信息": "GPT eğitimi işlemi çıktı bilgisi",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT örnekleme parametreleri (referans metin olmadığında çok düşük olmamalıdır. Emin değilseniz varsayılanı kullanın):",
"GPU卡号,只能填1个整数": "GPU kart numarası, sadece bir tamsayı girilebilir",
"GPU卡号以-分割,每个卡号一个进程": "GPU kart numaraları - ile ayrılır, her kart numarası için bir işlem",
"SSL进程输出信息": "SSL işlemi çıktı bilgisi",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5 açıldı",
"UVR5进程输出信息": "UVR5 işlem çıktı bilgisi",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:Normalizasyondan sonraki sesin ne kadarlık bir oranı karıştırılsın",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT örnekleme parametreleri (referans metin olmadığında çok düşük olmamalıdır. Emin değilseniz varsayılanı kullanın):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size:Ses seviyesi eğrisi nasıl hesaplanır, ne kadar küçükse hassasiyet o kadar yüksek ve hesaplama yükü o kadar artar (hassasiyet arttıkça etki mutlaka daha iyi olmaz)",
"max:归一化后最大值多少": "max:Normalizasyondan sonra maksimum değer ne kadar",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:Kesimden sonra en fazla ne kadar sessizlik bırakılır",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "Ses dosyaları ayrıca toplu olarak, iki seçimle, öncelikli okuma klasörüyle içe aktarılabilir",
"人声伴奏分离批量处理, 使用UVR5模型。": "Vokal ve akor ayırma toplu işleme, UVR5 modelini kullanarak.",
"人声提取激进程度": "Vokal çıkarma agresiflik derecesi",
"以下文件或文件夹不存在:": "Böyle Bir Dosya veya Klasör Yok:",
"以下模型不存在:": "Böyle bir model yok:",
"伴奏人声分离&去混响&去回声": "Vokal/Müzik Ayrıştırma ve Yankı Giderme",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "Referans metin modu olmadan kullanıldığında, referans sesi net duyulmadığında (ne yazılacağı bilinmiyorsa) açık bırakılması önerilir, bu durumda girilen referans metni göz ardı edilir.",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "Referans metin modu olmadan kullanıldığında, referans sesi net duyulmadığında (ne yazılacağı bilinmiyorsa) açık bırakılması önerilir, bu durumda girilen referans metni göz ardı edilir.",
"保存频率save_every_epoch": "Kayıt sıklığı save_every_epoch",
"凑50字一切": "50 kelime birleştir ve kes",
"凑四句一切": "Dört cümleyi bir araya getirip kes",
"切分后文本": "Bölündükten sonra metin",
"切分后的子音频的输出根目录": "Bölündükten sonra alt ses dosyalarının çıktı kök dizini",
"切割使用的进程数": "Kesim için kullanılan işlem sayısı",
"刷新模型路径": "Model yolu yenile",
@@ -84,9 +85,9 @@
"参考音频的语种": "Referans ses dosyasının dili",
"合成语音": "Ses sentezi",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "Geçerli klasör yolu formatı örneği: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例 (dosya yöneticisi adres çubuğundan kopyalayabilirsiniz).",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "İlerleyen zamanlarda fonem dönüştürme, manuel fonem düzenleme ve adım adım ses sentezi desteklenecek.",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "Kesmeye uygun ses dosyalarının bulunduğu dizini doldurun! Okunan ses dosyasının tam yolu = bu dizin + list dosyasındaki dalga biçimiyle eşleşen dosya adı (tam yol değil). Boş bırakılırsa, .list dosyasındaki tam yol kullanılır.",
"多语种混合": "Çok dilli karışım",
"多语种混合(粤语)": "Çok dilli karışık (Yue)",
"实际输入的参考文本:": "Gerçekten girilen referans metin:",
"实际输入的目标文本(切句后):": "Gerçekten girilen hedef metin (cümleler kesildikten sonra):",
"实际输入的目标文本(每句):": "Gerçekten girilen hedef metin (her cümle):",
@@ -113,7 +114,7 @@
"按中文句号。切": "Çince dönem işaretine göre kes",
"按标点符号切": "Noktalama işaretlerine göre kes",
"按英文句号.切": "İngilizce nokta işaretine göre kes",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "Metin bölme aracı. Çok uzun metinlerin sentezi her zaman iyi sonuçlar vermez, bu yüzden önerilen önce kesmektir. Sentez, metnin yeni satırlarına göre ayrı ayrı yapılır ve daha sonra birleştirilir.",
"数据类型精度": "veri türü doğruluğu",
"文本模块学习率权重": "Metin modülü öğrenme oranı ağırlığı",
"文本进程输出信息": "Metin işlemi çıktı bilgisi",
"施工中,请静候佳音": "Yapım aşamasında, lütfen iyi haberler için bekleyin",
@@ -132,6 +133,9 @@
"模型分为三类:": "Modeller üç türdedir:",
"模型切换": "Model değiştirme",
"每张显卡的batch_size": "Her bir ekran kartı için batch_size",
"版本": "Versiyon",
"粤英混合": "Yue-İngilizce Karışık",
"粤语": "Yue",
"终止ASR进程": "ASR işlemini durdur",
"终止GPT训练": "GPT eğitimini durdur",
"终止SSL提取进程": "SSL çıkarma işlemini durdur",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "Ses kesim işlemi çıktı bilgisi",
"语音降噪进程输出信息": "Gürültü azaltma işlemi çıktı bilgisi",
"请上传3~10秒内参考音频,超过会报错!": "Lütfen 3~10 saniye arasında bir referans ses dosyası yükleyin, aşım durumunda hata verilecektir!",
"请上传参考音频": "Lütfen Referans Sesi Yükleyin",
"请填入推理文本": "Lütfen Hedef Metni Girin",
"请输入有效文本": "Geçerli metin girin",
"转换": "Dönüştür",
"输入待处理音频文件夹路径": "İşlenecek ses klasörünün yolunu girin:",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "Eğitimi tamamlanmış ve SoVITS_weights ile GPT_weights altına kaydedilmiş modeli seçin. Varsayılan bir temel modeldir, 5 saniyelik Zero Shot TTS deneyimi için kullanılır.",
"降噪结果输出文件夹": "Gürültü azaltma sonuçları çıktı klasörü",
"降噪音频文件输入文件夹": "Gürültü azaltma ses dosyaları giriş klasörü",
"需要合成的切分前文本": "Bölünmeden önce sentezlenmesi gereken metin",
"需要合成的文本": "Sentezlenmesi gereken metin",
"需要合成的语种": "Sentezlenmesi gereken dil",
"韩文": "Korece",
"韩英混合": "Korece-İngilizce Karışık",
"音频自动切分输入路径,可文件可文件夹": "Ses otomatik bölme giriş yolu, dosya veya klasör olabilir",
"预训练的GPT模型路径": "Ön eğitilmiş GPT model yolu",
"预训练的SSL模型路径": "Ön eğitilmiş SSL model yolu",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR进程输出信息",
"GPT模型列表": "GPT模型列表",
"GPT训练进程输出信息": "GPT训练进程输出信息",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT采样参数(无参考文本时不要太低。不懂就用默认):",
"GPU卡号,只能填1个整数": "GPU卡号,只能填1个整数",
"GPU卡号以-分割,每个卡号一个进程": "GPU卡号以-分割,每个卡号一个进程",
"SSL进程输出信息": "SSL进程输出信息",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5已开启",
"UVR5进程输出信息": "UVR5进程输出信息",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:混多少比例归一化后音频进来",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "gpt采样参数(无参考文本时不要太低。不懂就用默认):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)",
"max:归一化后最大值多少": "max:归一化后最大值多少",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:切完后静音最多留多长",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹",
"人声伴奏分离批量处理, 使用UVR5模型。": "人声伴奏分离批量处理, 使用UVR5模型。",
"人声提取激进程度": "人声提取激进程度",
"以下文件或文件夹不存在:": "以下文件或文件夹不存在:",
"以下模型不存在:": "以下模型不存在:",
"伴奏人声分离&去混响&去回声": "伴奏人声分离&去混响&去回声",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。",
"保存频率save_every_epoch": "保存频率save_every_epoch",
"凑50字一切": "凑50字一切",
"凑四句一切": "凑四句一切",
"切分后文本": "切分后文本",
"切分后的子音频的输出根目录": "切分后的子音频的输出根目录",
"切割使用的进程数": "切割使用的进程数",
"刷新模型路径": "刷新模型路径",
@@ -84,9 +85,9 @@
"参考音频的语种": "参考音频的语种",
"合成语音": "合成语音",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "后续将支持转音素、手工修改音素、语音合成分步执行。",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。",
"多语种混合": "多语种混合",
"多语种混合(粤语)": "多语种混合(粤语)",
"实际输入的参考文本:": "实际输入的参考文本:",
"实际输入的目标文本(切句后):": "实际输入的目标文本(切句后):",
"实际输入的目标文本(每句):": "实际输入的目标文本(每句):",
@@ -113,7 +114,7 @@
"按中文句号。切": "按中文句号。切",
"按标点符号切": "按标点符号切",
"按英文句号.切": "按英文句号.切",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。",
"数据类型精度": "数据类型精度",
"文本模块学习率权重": "文本模块学习率权重",
"文本进程输出信息": "文本进程输出信息",
"施工中,请静候佳音": "施工中,请静候佳音",
@@ -132,6 +133,9 @@
"模型分为三类:": "模型分为三类:",
"模型切换": "模型切换",
"每张显卡的batch_size": "每张显卡的batch_size",
"版本": "版本",
"粤英混合": "粤英混合",
"粤语": "粤语",
"终止ASR进程": "终止ASR进程",
"终止GPT训练": "终止GPT训练",
"终止SSL提取进程": "终止SSL提取进程",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "语音切割进程输出信息",
"语音降噪进程输出信息": "语音降噪进程输出信息",
"请上传3~10秒内参考音频,超过会报错!": "请上传3~10秒内参考音频,超过会报错!",
"请上传参考音频": "请上传参考音频",
"请填入推理文本": "请填入推理文本",
"请输入有效文本": "请输入有效文本",
"转换": "转换",
"输入待处理音频文件夹路径": "输入待处理音频文件夹路径",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。",
"降噪结果输出文件夹": "降噪结果输出文件夹",
"降噪音频文件输入文件夹": "降噪音频文件输入文件夹",
"需要合成的切分前文本": "需要合成的切分前文本",
"需要合成的文本": "需要合成的文本",
"需要合成的语种": "需要合成的语种",
"韩文": "韩文",
"韩英混合": "韩英混合",
"音频自动切分输入路径,可文件可文件夹": "音频自动切分输入路径,可文件可文件夹",
"预训练的GPT模型路径": "预训练的GPT模型路径",
"预训练的SSL模型路径": "预训练的SSL模型路径",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR進程輸出信息",
"GPT模型列表": "GPT模型列表",
"GPT训练进程输出信息": "GPT訓練進程輸出信息",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 采样参数(无参考文本时不要太低。不懂就用默认):",
"GPU卡号,只能填1个整数": "GPU卡號,只能填1個整數",
"GPU卡号以-分割,每个卡号一个进程": "GPU卡號以-分割,每個卡號一個進程",
"SSL进程输出信息": "SSL進程輸出信息",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5已開啟",
"UVR5进程输出信息": "UVR5進程輸出信息",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:混多少比例歸一化後音頻進來",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 采样参数(无参考文本时不要太低。不懂就用默认):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size:怎麼算音量曲線,越小精度越大計算量越高(不是精度越大效果越好)",
"max:归一化后最大值多少": "max:歸一化後最大值多少",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:切完後靜音最多留多長",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹",
"人声伴奏分离批量处理, 使用UVR5模型。": "人聲伴奏分離批量處理, 使用UVR5模型。",
"人声提取激进程度": "人聲提取激進程度",
"以下文件或文件夹不存在:": "沒有這樣的檔案或文件夾:",
"以下模型不存在:": "以下模型不存在:",
"伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "使用無參考文本模式時建議使用微調的GPT,聽不清參考音頻說的是啥(不知道寫啥)可以開啟,開啟後無視填寫的參考文本。",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "使用無參考文本模式時建議使用微調的GPT,聽不清參考音頻說的是啥(不知道寫啥)可以開啟,開啟後無視填寫的參考文本。",
"保存频率save_every_epoch": "保存頻率save_every_epoch",
"凑50字一切": "湊50字一切",
"凑四句一切": "湊四句一切",
"切分后文本": "切分後文本",
"切分后的子音频的输出根目录": "切分後的子音頻的輸出根目錄",
"切割使用的进程数": "切割使用的進程數",
"刷新模型路径": "刷新模型路徑",
@@ -84,9 +85,9 @@
"参考音频的语种": "參考音頻的語種",
"合成语音": "合成語音",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "合格的文件夾路徑格式舉例: E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試樣例(去文件管理器地址欄拷就行了)。",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "後續將支持轉音素、手工修改音素、語音合成分步執行。",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "填切割後音頻所在目錄!讀取的音頻文件完整路徑=該目錄-拼接-list文件裡波形對應的文件名(不是全路徑)。如果留空則使用.list文件裡的絕對全路徑。",
"多语种混合": "多語種混合",
"多语种混合(粤语)": "多語種混合 (粵語)",
"实际输入的参考文本:": "實際輸入的參考文本:",
"实际输入的目标文本(切句后):": "實際輸入的目標文本(切句後):",
"实际输入的目标文本(每句):": "實際輸入的目標文本(每句):",
@@ -113,7 +114,7 @@
"按中文句号。切": "按中文句號。切",
"按标点符号切": "按標點符號切",
"按英文句号.切": "按英文句號.切",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "文本切分工具。太長的文本合成出來效果不一定好,所以太長建議先切。合成會根據文本的換行分開合成再拼起來。",
"数据类型精度": "數據類型精度",
"文本模块学习率权重": "文本模塊學習率權重",
"文本进程输出信息": "文本進程輸出信息",
"施工中,请静候佳音": "施工中,請靜候佳音",
@@ -132,6 +133,9 @@
"模型分为三类:": "模型分為三類:",
"模型切换": "模型切換",
"每张显卡的batch_size": "每張顯卡的batch_size",
"版本": "版本",
"粤英混合": "粵英混合",
"粤语": "粵語",
"终止ASR进程": "終止ASR進程",
"终止GPT训练": "終止GPT訓練",
"终止SSL提取进程": "終止SSL提取進程",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "語音切割進程輸出信息",
"语音降噪进程输出信息": "語音降噪進程輸出信息",
"请上传3~10秒内参考音频,超过会报错!": "請上傳3~10秒內參考音頻,超過會報錯!",
"请上传参考音频": "請上傳參考音頻",
"请填入推理文本": "請填入推理文本",
"请输入有效文本": "請輸入有效文本",
"转换": "轉換",
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "選擇訓練完存放在SoVITS_weights和GPT_weights下的模型。默認的一個是底模,體驗5秒Zero Shot TTS用。",
"降噪结果输出文件夹": "降噪結果輸出文件夾",
"降噪音频文件输入文件夹": "降噪音頻文件輸入文件夾",
"需要合成的切分前文本": "需要合成的切分前文本",
"需要合成的文本": "需要合成的文本",
"需要合成的语种": "需要合成的語種",
"韩文": "韓文",
"韩英混合": "韓英混合",
"音频自动切分输入路径,可文件可文件夹": "音頻自動切分輸入路徑,可文件可文件夾",
"预训练的GPT模型路径": "預訓練的GPT模型路徑",
"预训练的SSL模型路径": "預訓練的SSL模型路徑",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR進程輸出資訊",
"GPT模型列表": "GPT模型列表",
"GPT训练进程输出信息": "GPT訓練進程輸出資訊",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 采样参数(无参考文本时不要太低。不懂就用默认):",
"GPU卡号,只能填1个整数": "GPU卡號,只能填1個整數",
"GPU卡号以-分割,每个卡号一个进程": "GPU卡號以-分割,每個卡號一個進程",
"SSL进程输出信息": "SSL進程輸出資訊",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5已開啟",
"UVR5进程输出信息": "UVR5進程輸出資訊",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:混多少比例歸一化後音頻進來",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 采样参数(无参考文本时不要太低。不懂就用默认):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size:怎麼算音量曲線,越小精度越大計算量越高(不是精度越大效果越好)",
"max:归一化后最大值多少": "max:歸一化後最大值多少",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:切完後靜音最多留多長",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹",
"人声伴奏分离批量处理, 使用UVR5模型。": "人聲伴奏分離批量處理, 使用UVR5模型。",
"人声提取激进程度": "人聲提取激進程度",
"以下文件或文件夹不存在:": "沒有這樣的檔案或文件夾:",
"以下模型不存在:": "以下模型不存在",
"伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "使用無參考文本模式時建議使用微調的GPT,聽不清參考音頻說的啥(不曉得寫啥)可以開,開啟後無視填寫的參考文本。",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "使用無參考文本模式時建議使用微調的GPT,聽不清參考音頻說的啥(不曉得寫啥)可以開,開啟後無視填寫的參考文本。",
"保存频率save_every_epoch": "保存頻率save_every_epoch",
"凑50字一切": "湊50字一切",
"凑四句一切": "湊四句一切",
"切分后文本": "切分後文本",
"切分后的子音频的输出根目录": "切分後的子音頻的輸出根目錄",
"切割使用的进程数": "切割使用的進程數",
"刷新模型路径": "刷新模型路徑",
@@ -84,9 +85,9 @@
"参考音频的语种": "參考音頻的語種",
"合成语音": "合成語音",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "合格的資料夾路徑格式舉例: E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試範例(去文件管理器地址欄拷就行了)。",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "後續將支持轉音素、手工修改音素、語音合成分步執行。",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "填切割後音頻所在目錄!讀取的音頻檔案完整路徑=該目錄-拼接-list檔案裡波形對應的檔案名(不是全路徑)。如果留空則使用.list檔案裡的絕對全路徑。",
"多语种混合": "多語種混合",
"多语种混合(粤语)": "多語種混合 (粵語)",
"实际输入的参考文本:": "實際輸入的參考文本:",
"实际输入的目标文本(切句后):": "實際輸入的目標文本(切句後):",
"实际输入的目标文本(每句):": "實際輸入的目標文本(每句):",
@@ -113,7 +114,7 @@
"按中文句号。切": "按中文句號。切",
"按标点符号切": "按標點符號切",
"按英文句号.切": "按英文句號.切",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "文本切分工具。太長的文本合成出來效果不一定好,所以太長建議先切。合成會根據文本的換行分開合成再拼起來。",
"数据类型精度": "數據類型精度",
"文本模块学习率权重": "文本模塊學習率權重",
"文本进程输出信息": "文本進程輸出資訊",
"施工中,请静候佳音": "施工中,請靜候佳音",
@@ -132,6 +133,9 @@
"模型分为三类:": "模型分為三類:",
"模型切换": "模型切換",
"每张显卡的batch_size": "每張顯卡的batch_size",
"版本": "版本",
"粤英混合": "粵英混合",
"粤语": "粵語",
"终止ASR进程": "終止ASR進程",
"终止GPT训练": "終止GPT訓練",
"终止SSL提取进程": "終止SSL提取進程",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "語音切割進程輸出資訊",
"语音降噪进程输出信息": "語音降噪進程輸出資訊",
"请上传3~10秒内参考音频,超过会报错!": "請上傳3~10秒內參考音頻,超過會報錯!",
"请上传参考音频": "請上傳參考音頻",
"请填入推理文本": "請填入推理文本",
"请输入有效文本": "請輸入有效文本",
"转换": "轉換",
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "選擇訓練完存放在SoVITS_weights和GPT_weights下的模型。默認的一個是底模,體驗5秒Zero Shot TTS用。",
"降噪结果输出文件夹": "降噪結果輸出文件夾",
"降噪音频文件输入文件夹": "降噪音頻文件輸入文件夾",
"需要合成的切分前文本": "需要合成的切分前文本",
"需要合成的文本": "需要合成的文本",
"需要合成的语种": "需要合成的語種",
"韩文": "韓文",
"韩英混合": "韓英混合",
"音频自动切分输入路径,可文件可文件夹": "音頻自動切分輸入路徑,可文件可文件夾",
"预训练的GPT模型路径": "預訓練的GPT模型路徑",
"预训练的SSL模型路径": "預訓練的SSL模型路徑",
+13 -6
View File
@@ -38,6 +38,7 @@
"ASR进程输出信息": "ASR進程輸出資訊",
"GPT模型列表": "GPT模型列表",
"GPT训练进程输出信息": "GPT訓練進程輸出資訊",
"GPT采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 采样参数(无参考文本时不要太低。不懂就用默认):",
"GPU卡号,只能填1个整数": "GPU卡號,只能填1個整數",
"GPU卡号以-分割,每个卡号一个进程": "GPU卡號以-分割,每個卡號一個進程",
"SSL进程输出信息": "SSL進程輸出資訊",
@@ -50,7 +51,6 @@
"UVR5已开启": "UVR5已開啟",
"UVR5进程输出信息": "UVR5進程輸出資訊",
"alpha_mix:混多少比例归一化后音频进来": "alpha_mix:混多少比例歸一化後音頻進來",
"gpt采样参数(无参考文本时不要太低。不懂就用默认):": "GPT 采样参数(无参考文本时不要太低。不懂就用默认):",
"hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)": "hop_size:怎麼算音量曲線,越小精度越大計算量越高(不是精度越大效果越好)",
"max:归一化后最大值多少": "max:歸一化後最大值多少",
"max_sil_kept:切完后静音最多留多长": "max_sil_kept:切完後靜音最多留多長",
@@ -68,12 +68,13 @@
"也可批量输入音频文件, 二选一, 优先读文件夹": "也可批量输入音频文件, 二选一, 优先读文件夹",
"人声伴奏分离批量处理, 使用UVR5模型。": "人聲伴奏分離批量處理, 使用UVR5模型。",
"人声提取激进程度": "人聲提取激進程度",
"以下文件或文件夹不存在:": "沒有這樣的檔案或文件夾:",
"以下模型不存在:": "#以下模型不存在",
"伴奏人声分离&去混响&去回声": "伴奏人聲分離&去混響&去回聲",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开,开启后无视填写的参考文本。": "使用無參考文本模式時建議使用微調的GPT,聽不清參考音頻說的啥(不曉得寫啥)可以開,開啟後無視填寫的參考文本。",
"使用无参考文本模式时建议使用微调的GPT,听不清参考音频说的啥(不晓得写啥)可以开。<br>开启后无视填写的参考文本。": "使用無參考文本模式時建議使用微調的GPT,聽不清參考音頻說的啥(不曉得寫啥)可以開,開啟後無視填寫的參考文本。",
"保存频率save_every_epoch": "保存頻率save_every_epoch",
"凑50字一切": "湊50字一切",
"凑四句一切": "湊四句一切",
"切分后文本": "切分後文本",
"切分后的子音频的输出根目录": "切分後的子音頻的輸出根目錄",
"切割使用的进程数": "切割使用的進程數",
"刷新模型路径": "刷新模型路徑",
@@ -84,9 +85,9 @@
"参考音频的语种": "參考音頻的語種",
"合成语音": "合成語音",
"合格的文件夹路径格式举例: E:\\codes\\py39\\vits_vc_gpu\\白鹭霜华测试样例(去文件管理器地址栏拷就行了)。": "合格的資料夾路徑格式舉例: E:\\codes\\py39\\vits_vc_gpu\\白鷺霜華測試範例(去文件管理器地址欄拷就行了)。",
"后续将支持转音素、手工修改音素、语音合成分步执行。": "後續將支持轉音素、手工修改音素、語音合成分步執行。",
"填切割后音频所在目录!读取的音频文件完整路径=该目录-拼接-list文件里波形对应的文件名(不是全路径)。如果留空则使用.list文件里的绝对全路径。": "填切割後音頻所在目錄!讀取的音頻檔案完整路徑=該目錄-拼接-list檔案裡波形對應的檔案名(不是全路徑)。如果留空則使用.list檔案裡的絕對全路徑。",
"多语种混合": "多語種混合",
"多语种混合(粤语)": "多語種混合 (粵語)",
"实际输入的参考文本:": "實際輸入的參考文本:",
"实际输入的目标文本(切句后):": "實際輸入的目標文本(切句後):",
"实际输入的目标文本(每句):": "實際輸入的目標文本(每句):",
@@ -113,7 +114,7 @@
"按中文句号。切": "按中文句號。切",
"按标点符号切": "按標點符號切",
"按英文句号.切": "按英文句號.切",
"文本切分工具。太长的文本合成出来效果不一定好,所以太长建议先切。合成会根据文本的换行分开合成再拼起来。": "文本切分工具。太長的文本合成出來效果不一定好,所以太長建議先切。合成會根據文本的換行分開合成再拼起來。",
"数据类型精度": "數據類型精度",
"文本模块学习率权重": "文本模塊學習率權重",
"文本进程输出信息": "文本進程輸出資訊",
"施工中,请静候佳音": "施工中,請靜候佳音",
@@ -132,6 +133,9 @@
"模型分为三类:": "模型分為三類:",
"模型切换": "模型切換",
"每张显卡的batch_size": "每張顯卡的batch_size",
"版本": "版本",
"粤英混合": "粵英混合",
"粤语": "粵語",
"终止ASR进程": "終止ASR進程",
"终止GPT训练": "終止GPT訓練",
"终止SSL提取进程": "終止SSL提取進程",
@@ -148,6 +152,8 @@
"语音切割进程输出信息": "語音切割進程輸出資訊",
"语音降噪进程输出信息": "語音降噪進程輸出資訊",
"请上传3~10秒内参考音频,超过会报错!": "請上傳3~10秒內參考音頻,超過會報錯!",
"请上传参考音频": "請上傳參考音頻",
"请填入推理文本": "請填入推理文本",
"请输入有效文本": "請輸入有效文本",
"转换": "轉換",
"输入待处理音频文件夹路径": "輸入待處理音頻資料夾路徑",
@@ -159,9 +165,10 @@
"选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。": "選擇訓練完存放在SoVITS_weights和GPT_weights下的模型。默認的一個是底模,體驗5秒Zero Shot TTS用。",
"降噪结果输出文件夹": "降噪結果輸出文件夾",
"降噪音频文件输入文件夹": "降噪音頻文件輸入文件夾",
"需要合成的切分前文本": "需要合成的切分前文本",
"需要合成的文本": "需要合成的文本",
"需要合成的语种": "需要合成的語種",
"韩文": "韓文",
"韩英混合": "韓英混合",
"音频自动切分输入路径,可文件可文件夹": "音頻自動切分輸入路徑,可文件可文件夾",
"预训练的GPT模型路径": "預訓練的GPT模型路徑",
"预训练的SSL模型路径": "預訓練的SSL模型路徑",
+2 -3
View File
@@ -28,6 +28,5 @@ def load_audio(file, sr):
def clean_path(path_str:str):
if path_str.endswith(('\\','/')):
return clean_path(path_str[0:-1])
if platform.system() == 'Windows':
path_str = path_str.replace('/', '\\')
return path_str.strip(" ").strip('"').strip("\n").strip('"').strip(" ").strip("\u202a")
path_str = path_str.replace('/', os.sep).replace('\\', os.sep)
return path_str.strip(" ").strip('\'').strip("\n").strip('"').strip(" ").strip("\u202a")
@@ -479,27 +479,31 @@ class BSRoformer(Module):
'b s f t c -> b (f s) t c') # merge stereo / mono into the frequency, with frequency leading dimension, for band splitting
x = rearrange(stft_repr, 'b f t c -> b t (f c)')
# print("460:", x.dtype)#fp32
x = self.band_split(x)
# axial / hierarchical attention
# print("487:",x.dtype)#fp16
for transformer_block in self.layers:
if len(transformer_block) == 3:
linear_transformer, time_transformer, freq_transformer = transformer_block
x, ft_ps = pack([x], 'b * d')
# print("494:", x.dtype)#fp16
x = linear_transformer(x)
# print("496:", x.dtype)#fp16
x, = unpack(x, ft_ps, 'b * d')
else:
time_transformer, freq_transformer = transformer_block
# print("501:", x.dtype)#fp16
x = rearrange(x, 'b t f d -> b f t d')
x, ps = pack([x], '* t d')
x = time_transformer(x)
# print("505:", x.dtype)#fp16
x, = unpack(x, ps, '* t d')
x = rearrange(x, 'b f t d -> b t f d')
x, ps = pack([x], '* f d')
@@ -508,10 +512,11 @@ class BSRoformer(Module):
x, = unpack(x, ps, '* f d')
# print("515:", x.dtype)######fp16
x = self.final_norm(x)
num_stems = len(self.mask_estimators)
# print("519:", x.dtype)#fp32
mask = torch.stack([fn(x) for fn in self.mask_estimators], dim=1)
mask = rearrange(mask, 'b n t (f c) -> b n f t c', c=2)
+13 -4
View File
@@ -1,4 +1,5 @@
# This code is modified from https://github.com/ZFTurbo/
import pdb
import librosa
from tqdm import tqdm
@@ -10,6 +11,7 @@ import torch.nn as nn
import warnings
warnings.filterwarnings("ignore")
from bs_roformer.bs_roformer import BSRoformer
class BsRoformer_Loader:
def get_model_from_config(self):
@@ -40,7 +42,7 @@ class BsRoformer_Loader:
}
from bs_roformer.bs_roformer import BSRoformer
model = BSRoformer(
**dict(config)
)
@@ -95,6 +97,8 @@ class BsRoformer_Loader:
part = nn.functional.pad(input=part, pad=(0, C - length), mode='reflect')
else:
part = nn.functional.pad(input=part, pad=(0, C - length, 0, 0), mode='constant', value=0)
if(self.is_half==True):
part=part.half()
batch_data.append(part)
batch_locations.append((i, length))
i += step
@@ -102,6 +106,7 @@ class BsRoformer_Loader:
if len(batch_data) >= batch_size or (i >= mix.shape[1]):
arr = torch.stack(batch_data, dim=0)
# print(23333333,arr.dtype)
x = model(arr)
window = window_middle
@@ -192,14 +197,18 @@ class BsRoformer_Loader:
# print("Elapsed time: {:.2f} sec".format(time.time() - start_time))
def __init__(self, model_path, device):
def __init__(self, model_path, device,is_half):
self.device = device
self.extract_instrumental=True
model = self.get_model_from_config()
state_dict = torch.load(model_path)
state_dict = torch.load(model_path,map_location="cpu")
model.load_state_dict(state_dict)
self.model = model.to(device)
self.is_half=is_half
if(is_half==False):
self.model = model.to(device)
else:
self.model = model.half().to(device)
def _path_audio_(self, input, others_root, vocal_root, format, is_hp3=False):
+4 -3
View File
@@ -17,8 +17,8 @@ from bsroformer import BsRoformer_Loader
weight_uvr5_root = "tools/uvr5/uvr5_weights"
uvr5_names = []
for name in os.listdir(weight_uvr5_root):
if name.endswith(".pth") or "onnx" in name:
uvr5_names.append(name.replace(".pth", ""))
if name.endswith(".pth") or name.endswith(".ckpt") or "onnx" in name:
uvr5_names.append(name.replace(".pth", "").replace(".ckpt", ""))
device=sys.argv[1]
is_half=eval(sys.argv[2])
@@ -37,8 +37,9 @@ def uvr(model_name, inp_root, save_root_vocal, paths, save_root_ins, agg, format
elif model_name == "Bs_Roformer" or "bs_roformer" in model_name.lower():
func = BsRoformer_Loader
pre_fun = func(
model_path = os.path.join(weight_uvr5_root, model_name + ".pth"),
model_path = os.path.join(weight_uvr5_root, model_name + ".ckpt"),
device = device,
is_half=is_half
)
else:
func = AudioPre if "DeEcho" not in model_name else AudioPreDeEcho
+228 -97
View File
@@ -1,12 +1,15 @@
import os,shutil,sys,pdb,re
import os,sys
if len(sys.argv)==1:sys.argv.append('v2')
version="v1"if sys.argv[1]=="v1" else"v2"
os.environ["version"]=version
now_dir = os.getcwd()
sys.path.insert(0, now_dir)
import json,yaml,warnings,torch
import warnings
warnings.filterwarnings("ignore")
import json,yaml,torch,pdb,re,shutil
import platform
import psutil
import signal
warnings.filterwarnings("ignore")
torch.manual_seed(233333)
tmp = os.path.join(now_dir, "TEMP")
os.makedirs(tmp, exist_ok=True)
@@ -45,18 +48,20 @@ from tools import my_utils
import traceback
import shutil
import pdb
import gradio as gr
from subprocess import Popen
import signal
from config import python_exec,infer_device,is_half,exp_root,webui_port_main,webui_port_infer_tts,webui_port_uvr5,webui_port_subfix,is_share
from tools.i18n.i18n import I18nAuto
i18n = I18nAuto()
from tools.i18n.i18n import I18nAuto, scan_language_list
language=sys.argv[-1] if sys.argv[-1] in scan_language_list() else "Auto"
os.environ["language"]=language
i18n = I18nAuto(language=language)
from scipy.io import wavfile
from tools.my_utils import load_audio
from multiprocessing import cpu_count
# os.environ['PYTORCH_ENABLE_MPS_FALLBACK'] = '1' # 当遇到mps不支持的步骤时使用cpu
import gradio.analytics as analytics
analytics.version_check = lambda:None
import gradio as gr
n_cpu=cpu_count()
ngpu = torch.cuda.device_count()
@@ -65,13 +70,16 @@ mem = []
if_gpu_ok = False
# 判断是否有能用来训练和加速推理的N卡
ok_gpu_keywords={"10","16","20","30","40","A2","A3","A4","P4","A50","500","A60","70","80","90","M4","T4","TITAN","L4","4060","H"}
set_gpu_numbers=set()
if torch.cuda.is_available() or ngpu != 0:
for i in range(ngpu):
gpu_name = torch.cuda.get_device_name(i)
if any(value in gpu_name.upper()for value in ["10","16","20","30","40","A2","A3","A4","P4","A50","500","A60","70","80","90","M4","T4","TITAN","L4","4060"]):
if any(value in gpu_name.upper()for value in ok_gpu_keywords):
# A10#A100#V100#A40#P40#M40#K80#A4500
if_gpu_ok = True # 至少有一张能用的N卡
gpu_infos.append("%s\t%s" % (i, gpu_name))
set_gpu_numbers.add(i)
mem.append(int(torch.cuda.get_device_properties(i).total_memory/ 1024/ 1024/ 1024+ 0.4))
# # 判断是否支持mps加速
# if torch.backends.mps.is_available():
@@ -85,24 +93,62 @@ if if_gpu_ok and len(gpu_infos) > 0:
else:
gpu_info = ("%s\t%s" % ("0", "CPU"))
gpu_infos.append("%s\t%s" % ("0", "CPU"))
set_gpu_numbers.add(0)
default_batch_size = int(psutil.virtual_memory().total/ 1024 / 1024 / 1024 / 2)
gpus = "-".join([i[0] for i in gpu_infos])
default_gpu_numbers=str(sorted(list(set_gpu_numbers))[0])
def fix_gpu_number(input):#将越界的number强制改到界内
try:
if(int(input)not in set_gpu_numbers):return default_gpu_numbers
except:return input
return input
def fix_gpu_numbers(inputs):
output=[]
try:
for input in inputs.split(","):output.append(str(fix_gpu_number(input)))
return ",".join(output)
except:
return inputs
pretrained_sovits_name="GPT_SoVITS/pretrained_models/s2G488k.pth"
pretrained_gpt_name="GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt"
pretrained_sovits_name=["GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s2G2333k.pth", "GPT_SoVITS/pretrained_models/s2G488k.pth"]
pretrained_gpt_name=["GPT_SoVITS/pretrained_models/gsv-v2final-pretrained/s1bert25hz-5kh-longer-epoch=12-step=369668.ckpt", "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt"]
pretrained_model_list = (pretrained_sovits_name[-int(version[-1])+2],pretrained_sovits_name[-int(version[-1])+2].replace("s2G","s2D"),pretrained_gpt_name[-int(version[-1])+2],"GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large","GPT_SoVITS/pretrained_models/chinese-hubert-base")
_=''
for i in pretrained_model_list:
if os.path.exists(i):...
else:_+=f'\n {i}'
if _:
print("warning:",i18n('以下模型不存在:')+_)
_ =[[],[]]
for i in range(2):
if os.path.exists(pretrained_gpt_name[i]):_[0].append(pretrained_gpt_name[i])
else:_[0].append("")##没有下pretrained模型的,说不定他们是想自己从零训底模呢
if os.path.exists(pretrained_sovits_name[i]):_[-1].append(pretrained_sovits_name[i])
else:_[-1].append("")
pretrained_gpt_name,pretrained_sovits_name = _
SoVITS_weight_root=["SoVITS_weights_v2","SoVITS_weights"]
GPT_weight_root=["GPT_weights_v2","GPT_weights"]
for root in SoVITS_weight_root+GPT_weight_root:
os.makedirs(root,exist_ok=True)
def get_weights_names():
SoVITS_names = [pretrained_sovits_name]
for name in os.listdir(SoVITS_weight_root):
if name.endswith(".pth"):SoVITS_names.append(name)
GPT_names = [pretrained_gpt_name]
for name in os.listdir(GPT_weight_root):
if name.endswith(".ckpt"): GPT_names.append(name)
return SoVITS_names,GPT_names
SoVITS_weight_root="SoVITS_weights"
GPT_weight_root="GPT_weights"
os.makedirs(SoVITS_weight_root,exist_ok=True)
os.makedirs(GPT_weight_root,exist_ok=True)
SoVITS_names = [name for name in pretrained_sovits_name if 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 = [name for name in pretrained_gpt_name if 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()
for path in SoVITS_weight_root+GPT_weight_root:
os.makedirs(path,exist_ok=True)
def custom_sort_key(s):
# 使用正则表达式提取字符串中的数字部分和非数字部分
@@ -181,11 +227,11 @@ def change_tts_inference(if_tts,bert_path,cnhubert_base_path,gpu_number,gpt_path
os.environ["sovits_path"]=sovits_path if "/"in sovits_path else "%s/%s"%(SoVITS_weight_root,sovits_path)
os.environ["cnhubert_base_path"]=cnhubert_base_path
os.environ["bert_path"]=bert_path
os.environ["_CUDA_VISIBLE_DEVICES"]=gpu_number
os.environ["_CUDA_VISIBLE_DEVICES"]=fix_gpu_number(gpu_number)
os.environ["is_half"]=str(is_half)
os.environ["infer_ttswebui"]=str(webui_port_infer_tts)
os.environ["is_share"]=str(is_share)
cmd = '"%s" GPT_SoVITS/inference_webui.py'%(python_exec)
cmd = '"%s" GPT_SoVITS/inference_webui.py "%s"'%(python_exec, language)
yield i18n("TTS推理进程已开启")
print(cmd)
p_tts_inference = Popen(cmd, shell=True)
@@ -195,26 +241,29 @@ def change_tts_inference(if_tts,bert_path,cnhubert_base_path,gpu_number,gpt_path
yield i18n("TTS推理进程已关闭")
from tools.asr.config import asr_dict
def open_asr(asr_inp_dir, asr_opt_dir, asr_model, asr_model_size, asr_lang):
def open_asr(asr_inp_dir, asr_opt_dir, asr_model, asr_model_size, asr_lang, asr_precision):
global p_asr
if(p_asr==None):
asr_inp_dir=my_utils.clean_path(asr_inp_dir)
asr_opt_dir=my_utils.clean_path(asr_opt_dir)
check_for_exists([asr_inp_dir])
cmd = f'"{python_exec}" tools/asr/{asr_dict[asr_model]["path"]}'
cmd += f' -i "{asr_inp_dir}"'
cmd += f' -o "{asr_opt_dir}"'
cmd += f' -s {asr_model_size}'
cmd += f' -l {asr_lang}'
cmd += " -p %s"%("float16"if is_half==True else "float32")
yield "ASR任务开启:%s"%cmd,{"__type__":"update","visible":False},{"__type__":"update","visible":True}
cmd += f" -p {asr_precision}"
output_file_name = os.path.basename(asr_inp_dir)
output_folder = asr_opt_dir or "output/asr_opt"
output_file_path = os.path.abspath(f'{output_folder}/{output_file_name}.list')
yield "ASR任务开启:%s"%cmd, {"__type__":"update","visible":False}, {"__type__":"update","visible":True}, {"__type__":"update"}, {"__type__":"update"}, {"__type__":"update"}
print(cmd)
p_asr = Popen(cmd, shell=True)
p_asr.wait()
p_asr=None
yield f"ASR任务完成, 查看终端进行下一步",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield f"ASR任务完成, 查看终端进行下一步", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}, {"__type__":"update","value":output_file_path}, {"__type__":"update","value":output_file_path}, {"__type__":"update","value":asr_inp_dir}
else:
yield "已有正在进行的ASR任务,需先终止才能开启下一次任务",{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "已有正在进行的ASR任务,需先终止才能开启下一次任务", {"__type__":"update","visible":False}, {"__type__":"update","visible":True}, {"__type__":"update"}, {"__type__":"update"}, {"__type__":"update"}
# return None
def close_asr():
@@ -222,22 +271,23 @@ def close_asr():
if(p_asr!=None):
kill_process(p_asr.pid)
p_asr=None
return "已终止ASR进程",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
return "已终止ASR进程", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
def open_denoise(denoise_inp_dir, denoise_opt_dir):
global p_denoise
if(p_denoise==None):
denoise_inp_dir=my_utils.clean_path(denoise_inp_dir)
denoise_opt_dir=my_utils.clean_path(denoise_opt_dir)
check_for_exists([denoise_inp_dir])
cmd = '"%s" tools/cmd-denoise.py -i "%s" -o "%s" -p %s'%(python_exec,denoise_inp_dir,denoise_opt_dir,"float16"if is_half==True else "float32")
yield "语音降噪任务开启:%s"%cmd,{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "语音降噪任务开启:%s"%cmd, {"__type__":"update","visible":False}, {"__type__":"update","visible":True}, {"__type__":"update"}, {"__type__":"update"}
print(cmd)
p_denoise = Popen(cmd, shell=True)
p_denoise.wait()
p_denoise=None
yield f"语音降噪任务完成, 查看终端进行下一步",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield f"语音降噪任务完成, 查看终端进行下一步", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}, {"__type__":"update","value":denoise_opt_dir}, {"__type__":"update","value":denoise_opt_dir}
else:
yield "已有正在进行的语音降噪任务,需先终止才能开启下一次任务",{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "已有正在进行的语音降噪任务,需先终止才能开启下一次任务", {"__type__":"update","visible":False}, {"__type__":"update","visible":True}, {"__type__":"update"}, {"__type__":"update"}
# return None
def close_denoise():
@@ -245,7 +295,7 @@ def close_denoise():
if(p_denoise!=None):
kill_process(p_denoise.pid)
p_denoise=None
return "已终止语音降噪进程",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
return "已终止语音降噪进程", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
p_train_SoVITS=None
def open1Ba(batch_size,total_epoch,exp_name,text_low_lr_rate,if_save_latest,if_save_every_weights,save_every_epoch,gpu_numbers1Ba,pretrained_s2G,pretrained_s2D):
@@ -256,6 +306,7 @@ def open1Ba(batch_size,total_epoch,exp_name,text_low_lr_rate,if_save_latest,if_s
data=json.loads(data)
s2_dir="%s/%s"%(exp_root,exp_name)
os.makedirs("%s/logs_s2"%(s2_dir),exist_ok=True)
check_for_exists([s2_dir],is_train=True)
if(is_half==False):
data["train"]["fp16_run"]=False
batch_size=max(1,batch_size//2)
@@ -268,38 +319,41 @@ def open1Ba(batch_size,total_epoch,exp_name,text_low_lr_rate,if_save_latest,if_s
data["train"]["if_save_every_weights"]=if_save_every_weights
data["train"]["save_every_epoch"]=save_every_epoch
data["train"]["gpu_numbers"]=gpu_numbers1Ba
data["model"]["version"]=version
data["data"]["exp_dir"]=data["s2_ckpt_dir"]=s2_dir
data["save_weight_dir"]=SoVITS_weight_root
data["save_weight_dir"]=SoVITS_weight_root[-int(version[-1])+2]
data["name"]=exp_name
data["version"]=version
tmp_config_path="%s/tmp_s2.json"%tmp
with open(tmp_config_path,"w")as f:f.write(json.dumps(data))
cmd = '"%s" GPT_SoVITS/s2_train.py --config "%s"'%(python_exec,tmp_config_path)
yield "SoVITS训练开始:%s"%cmd,{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "SoVITS训练开始:%s"%cmd, {"__type__":"update","visible":False}, {"__type__":"update","visible":True}
print(cmd)
p_train_SoVITS = Popen(cmd, shell=True)
p_train_SoVITS.wait()
p_train_SoVITS=None
yield "SoVITS训练完成",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "SoVITS训练完成", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
else:
yield "已有正在进行的SoVITS训练任务,需先终止才能开启下一次任务",{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "已有正在进行的SoVITS训练任务,需先终止才能开启下一次任务", {"__type__":"update","visible":False}, {"__type__":"update","visible":True}
def close1Ba():
global p_train_SoVITS
if(p_train_SoVITS!=None):
kill_process(p_train_SoVITS.pid)
p_train_SoVITS=None
return "已终止SoVITS训练",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
return "已终止SoVITS训练", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
p_train_GPT=None
def open1Bb(batch_size,total_epoch,exp_name,if_dpo,if_save_latest,if_save_every_weights,save_every_epoch,gpu_numbers,pretrained_s1):
global p_train_GPT
if(p_train_GPT==None):
with open("GPT_SoVITS/configs/s1longer.yaml")as f:
with open("GPT_SoVITS/configs/s1longer.yaml"if version=="v1"else "GPT_SoVITS/configs/s1longer-v2.yaml")as f:
data=f.read()
data=yaml.load(data, Loader=yaml.FullLoader)
s1_dir="%s/%s"%(exp_root,exp_name)
os.makedirs("%s/logs_s1"%(s1_dir),exist_ok=True)
check_for_exists([s1_dir],is_train=True)
if(is_half==False):
data["train"]["precision"]="32"
batch_size = max(1, batch_size // 2)
@@ -310,46 +364,48 @@ def open1Bb(batch_size,total_epoch,exp_name,if_dpo,if_save_latest,if_save_every_
data["train"]["if_save_every_weights"]=if_save_every_weights
data["train"]["if_save_latest"]=if_save_latest
data["train"]["if_dpo"]=if_dpo
data["train"]["half_weights_save_dir"]=GPT_weight_root
data["train"]["half_weights_save_dir"]=GPT_weight_root[-int(version[-1])+2]
data["train"]["exp_name"]=exp_name
data["train_semantic_path"]="%s/6-name2semantic.tsv"%s1_dir
data["train_phoneme_path"]="%s/2-name2text.txt"%s1_dir
data["output_dir"]="%s/logs_s1"%s1_dir
# data["version"]=version
os.environ["_CUDA_VISIBLE_DEVICES"]=gpu_numbers.replace("-",",")
os.environ["_CUDA_VISIBLE_DEVICES"]=fix_gpu_numbers(gpu_numbers.replace("-",","))
os.environ["hz"]="25hz"
tmp_config_path="%s/tmp_s1.yaml"%tmp
with open(tmp_config_path, "w") as f:f.write(yaml.dump(data, default_flow_style=False))
# cmd = '"%s" GPT_SoVITS/s1_train.py --config_file "%s" --train_semantic_path "%s/6-name2semantic.tsv" --train_phoneme_path "%s/2-name2text.txt" --output_dir "%s/logs_s1"'%(python_exec,tmp_config_path,s1_dir,s1_dir,s1_dir)
cmd = '"%s" GPT_SoVITS/s1_train.py --config_file "%s" '%(python_exec,tmp_config_path)
yield "GPT训练开始:%s"%cmd,{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "GPT训练开始:%s"%cmd, {"__type__":"update","visible":False}, {"__type__":"update","visible":True}
print(cmd)
p_train_GPT = Popen(cmd, shell=True)
p_train_GPT.wait()
p_train_GPT=None
yield "GPT训练完成",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "GPT训练完成", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
else:
yield "已有正在进行的GPT训练任务,需先终止才能开启下一次任务",{"__type__":"update","visible":False},{"__type__":"update","visible":True}
yield "已有正在进行的GPT训练任务,需先终止才能开启下一次任务", {"__type__":"update","visible":False}, {"__type__":"update","visible":True}
def close1Bb():
global p_train_GPT
if(p_train_GPT!=None):
kill_process(p_train_GPT.pid)
p_train_GPT=None
return "已终止GPT训练",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
return "已终止GPT训练", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
ps_slice=[]
def open_slice(inp,opt_root,threshold,min_length,min_interval,hop_size,max_sil_kept,_max,alpha,n_parts):
global ps_slice
inp = my_utils.clean_path(inp)
opt_root = my_utils.clean_path(opt_root)
check_for_exists([inp])
if(os.path.exists(inp)==False):
yield "输入路径不存在",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "输入路径不存在", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}, {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
return
if os.path.isfile(inp):n_parts=1
elif os.path.isdir(inp):pass
else:
yield "输入路径存在但既不是文件也不是文件夹",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "输入路径存在但既不是文件也不是文件夹", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}, {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
return
if (ps_slice == []):
for i_part in range(n_parts):
@@ -357,13 +413,13 @@ def open_slice(inp,opt_root,threshold,min_length,min_interval,hop_size,max_sil_k
print(cmd)
p = Popen(cmd, shell=True)
ps_slice.append(p)
yield "切割执行中", {"__type__": "update", "visible": False}, {"__type__": "update", "visible": True}
yield "切割执行中", {"__type__": "update", "visible": False}, {"__type__": "update", "visible": True}, {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
for p in ps_slice:
p.wait()
ps_slice=[]
yield "切割结束",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "切割结束", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}, {"__type__": "update", "value":opt_root}, {"__type__": "update", "value":opt_root}, {"__type__": "update", "value":opt_root}
else:
yield "已有正在进行的切割任务,需先终止才能开启下一次任务", {"__type__": "update", "visible": False}, {"__type__": "update", "visible": True}
yield "已有正在进行的切割任务,需先终止才能开启下一次任务", {"__type__": "update", "visible": False}, {"__type__": "update", "visible": True}, {"__type__": "update"}, {"__type__": "update"}, {"__type__": "update"}
def close_slice():
global ps_slice
@@ -381,6 +437,7 @@ def open1a(inp_text,inp_wav_dir,exp_name,gpu_numbers,bert_pretrained_dir):
global ps1a
inp_text = my_utils.clean_path(inp_text)
inp_wav_dir = my_utils.clean_path(inp_wav_dir)
check_for_exists([inp_text,inp_wav_dir], is_dataset_processing=True)
if (ps1a == []):
opt_dir="%s/%s"%(exp_root,exp_name)
config={
@@ -397,7 +454,7 @@ def open1a(inp_text,inp_wav_dir,exp_name,gpu_numbers,bert_pretrained_dir):
{
"i_part": str(i_part),
"all_parts": str(all_parts),
"_CUDA_VISIBLE_DEVICES": gpu_names[i_part],
"_CUDA_VISIBLE_DEVICES": fix_gpu_number(gpu_names[i_part]),
"is_half": str(is_half)
}
)
@@ -442,6 +499,7 @@ def open1b(inp_text,inp_wav_dir,exp_name,gpu_numbers,ssl_pretrained_dir):
global ps1b
inp_text = my_utils.clean_path(inp_text)
inp_wav_dir = my_utils.clean_path(inp_wav_dir)
check_for_exists([inp_text,inp_wav_dir], is_dataset_processing=True)
if (ps1b == []):
config={
"inp_text":inp_text,
@@ -458,7 +516,7 @@ def open1b(inp_text,inp_wav_dir,exp_name,gpu_numbers,ssl_pretrained_dir):
{
"i_part": str(i_part),
"all_parts": str(all_parts),
"_CUDA_VISIBLE_DEVICES": gpu_names[i_part],
"_CUDA_VISIBLE_DEVICES": fix_gpu_number(gpu_names[i_part]),
}
)
os.environ.update(config)
@@ -470,7 +528,7 @@ def open1b(inp_text,inp_wav_dir,exp_name,gpu_numbers,ssl_pretrained_dir):
for p in ps1b:
p.wait()
ps1b=[]
yield "SSL提取进程结束",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "SSL提取进程结束", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
else:
yield "已有正在进行的SSL提取任务,需先终止才能开启下一次任务", {"__type__": "update", "visible": False}, {"__type__": "update", "visible": True}
@@ -489,6 +547,7 @@ ps1c=[]
def open1c(inp_text,exp_name,gpu_numbers,pretrained_s2G_path):
global ps1c
inp_text = my_utils.clean_path(inp_text)
check_for_exists([inp_text,''], is_dataset_processing=True)
if (ps1c == []):
opt_dir="%s/%s"%(exp_root,exp_name)
config={
@@ -506,7 +565,7 @@ def open1c(inp_text,exp_name,gpu_numbers,pretrained_s2G_path):
{
"i_part": str(i_part),
"all_parts": str(all_parts),
"_CUDA_VISIBLE_DEVICES": gpu_names[i_part],
"_CUDA_VISIBLE_DEVICES": fix_gpu_number(gpu_names[i_part]),
}
)
os.environ.update(config)
@@ -527,7 +586,7 @@ def open1c(inp_text,exp_name,gpu_numbers,pretrained_s2G_path):
with open(path_semantic, "w", encoding="utf8") as f:
f.write("\n".join(opt) + "\n")
ps1c=[]
yield "语义token提取进程结束",{"__type__":"update","visible":True},{"__type__":"update","visible":False}
yield "语义token提取进程结束", {"__type__":"update","visible":True}, {"__type__":"update","visible":False}
else:
yield "已有正在进行的语义token提取任务,需先终止才能开启下一次任务", {"__type__": "update", "visible": False}, {"__type__": "update", "visible": True}
@@ -547,6 +606,7 @@ def open1abc(inp_text,inp_wav_dir,exp_name,gpu_numbers1a,gpu_numbers1Ba,gpu_numb
global ps1abc
inp_text = my_utils.clean_path(inp_text)
inp_wav_dir = my_utils.clean_path(inp_wav_dir)
check_for_exists([inp_text,inp_wav_dir])
if (ps1abc == []):
opt_dir="%s/%s"%(exp_root,exp_name)
try:
@@ -568,7 +628,7 @@ def open1abc(inp_text,inp_wav_dir,exp_name,gpu_numbers1a,gpu_numbers1Ba,gpu_numb
{
"i_part": str(i_part),
"all_parts": str(all_parts),
"_CUDA_VISIBLE_DEVICES": gpu_names[i_part],
"_CUDA_VISIBLE_DEVICES": fix_gpu_number(gpu_names[i_part]),
}
)
os.environ.update(config)
@@ -605,7 +665,7 @@ def open1abc(inp_text,inp_wav_dir,exp_name,gpu_numbers1a,gpu_numbers1Ba,gpu_numb
{
"i_part": str(i_part),
"all_parts": str(all_parts),
"_CUDA_VISIBLE_DEVICES": gpu_names[i_part],
"_CUDA_VISIBLE_DEVICES": fix_gpu_number(gpu_names[i_part]),
}
)
os.environ.update(config)
@@ -634,7 +694,7 @@ def open1abc(inp_text,inp_wav_dir,exp_name,gpu_numbers1a,gpu_numbers1Ba,gpu_numb
{
"i_part": str(i_part),
"all_parts": str(all_parts),
"_CUDA_VISIBLE_DEVICES": gpu_names[i_part],
"_CUDA_VISIBLE_DEVICES": fix_gpu_number(gpu_names[i_part]),
}
)
os.environ.update(config)
@@ -674,6 +734,47 @@ def close1abc():
ps1abc=[]
return "已终止所有一键三连进程", {"__type__": "update", "visible": True}, {"__type__": "update", "visible": False}
def switch_version(version_):
os.environ['version']=version_
global version
version = version_
if pretrained_sovits_name[-int(version[-1])+2] !='' and pretrained_gpt_name[-int(version[-1])+2] !='':...
else:
gr.Warning(i18n(f'未下载{version.upper()}模型'))
return {'__type__':'update', 'value':pretrained_sovits_name[-int(version[-1])+2]}, {'__type__':'update', 'value':pretrained_sovits_name[-int(version[-1])+2].replace("s2G","s2D")}, {'__type__':'update', 'value':pretrained_gpt_name[-int(version[-1])+2]}, {'__type__':'update', 'value':pretrained_gpt_name[-int(version[-1])+2]}, {'__type__':'update', 'value':pretrained_sovits_name[-int(version[-1])+2]}
def check_for_exists(file_list=None,is_train=False,is_dataset_processing=False):
missing_files=[]
if is_train == True and file_list:
file_list.append(os.path.join(file_list[0],'2-name2text.txt'))
file_list.append(os.path.join(file_list[0],'3-bert'))
file_list.append(os.path.join(file_list[0],'4-cnhubert'))
file_list.append(os.path.join(file_list[0],'5-wav32k'))
file_list.append(os.path.join(file_list[0],'6-name2semantic.tsv'))
for file in file_list:
if os.path.exists(file):pass
else:missing_files.append(file)
if missing_files:
if is_train:
for missing_file in missing_files:
if missing_file != '':
gr.Warning(missing_file)
gr.Warning(i18n('以下文件或文件夹不存在:'))
else:
for missing_file in missing_files:
if missing_file != '':
gr.Warning(missing_file)
if file_list[-1]==[''] and is_dataset_processing:
pass
else:
gr.Warning(i18n('以下文件或文件夹不存在:'))
if os.path.exists('GPT_SoVITS/text/G2PWModel'):...
else:
cmd = '"%s" GPT_SoVITS/download.py'%python_exec
p = Popen(cmd, shell=True)
p.wait()
with gr.Blocks(title="GPT-SoVITS WebUI") as app:
gr.Markdown(
value=
@@ -692,33 +793,37 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
uvr5_info = gr.Textbox(label=i18n("UVR5进程输出信息"))
gr.Markdown(value=i18n("0b-语音切分工具"))
with gr.Row():
with gr.Row():
slice_inp_path=gr.Textbox(label=i18n("音频自动切分输入路径,可文件可文件夹"),value="")
slice_opt_root=gr.Textbox(label=i18n("切分后的子音频的输出根目录"),value="output/slicer_opt")
threshold=gr.Textbox(label=i18n("threshold:音量小于这个值视作静音的备选切割点"),value="-34")
min_length=gr.Textbox(label=i18n("min_length:每段最小多长,如果第一段太短一直和后面段连起来直到超过这个值"),value="4000")
min_interval=gr.Textbox(label=i18n("min_interval:最短切割间隔"),value="300")
hop_size=gr.Textbox(label=i18n("hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)"),value="10")
max_sil_kept=gr.Textbox(label=i18n("max_sil_kept:切完后静音最多留多长"),value="500")
with gr.Row():
open_slicer_button=gr.Button(i18n("开启语音切割"), variant="primary",visible=True)
close_slicer_button=gr.Button(i18n("终止语音切割"), variant="primary",visible=False)
_max=gr.Slider(minimum=0,maximum=1,step=0.05,label=i18n("max:归一化后最大值多少"),value=0.9,interactive=True)
alpha=gr.Slider(minimum=0,maximum=1,step=0.05,label=i18n("alpha_mix:混多少比例归一化后音频进来"),value=0.25,interactive=True)
n_process=gr.Slider(minimum=1,maximum=n_cpu,step=1,label=i18n("切割使用的进程数"),value=4,interactive=True)
slicer_info = gr.Textbox(label=i18n("语音切割进程输出信息"))
with gr.Column(scale=3):
with gr.Row():
slice_inp_path=gr.Textbox(label=i18n("音频自动切分输入路径,可文件可文件夹"),value="")
slice_opt_root=gr.Textbox(label=i18n("切分后的子音频的输出根目录"),value="output/slicer_opt")
with gr.Row():
threshold=gr.Textbox(label=i18n("threshold:音量小于这个值视作静音的备选切割点"),value="-34")
min_length=gr.Textbox(label=i18n("min_length:每段最小多长,如果第一段太短一直和后面段连起来直到超过这个值"),value="4000")
min_interval=gr.Textbox(label=i18n("min_interval:最短切割间隔"),value="300")
hop_size=gr.Textbox(label=i18n("hop_size:怎么算音量曲线,越小精度越大计算量越高(不是精度越大效果越好)"),value="10")
max_sil_kept=gr.Textbox(label=i18n("max_sil_kept:切完后静音最多留多长"),value="500")
with gr.Row():
_max=gr.Slider(minimum=0,maximum=1,step=0.05,label=i18n("max:归一化后最大值多少"),value=0.9,interactive=True)
alpha=gr.Slider(minimum=0,maximum=1,step=0.05,label=i18n("alpha_mix:混多少比例归一化后音频进来"),value=0.25,interactive=True)
n_process=gr.Slider(minimum=1,maximum=n_cpu,step=1,label=i18n("切割使用的进程数"),value=4,interactive=True)
with gr.Row():
slicer_info = gr.Textbox(label=i18n("语音切割进程输出信息"))
open_slicer_button=gr.Button(i18n("开启语音切割"), variant="primary",visible=True)
close_slicer_button=gr.Button(i18n("终止语音切割"), variant="primary",visible=False)
gr.Markdown(value=i18n("0bb-语音降噪工具"))
with gr.Row():
with gr.Column(scale=3):
with gr.Row():
denoise_input_dir=gr.Textbox(label=i18n("降噪音频文件输入文件夹"),value="")
denoise_output_dir=gr.Textbox(label=i18n("降噪结果输出文件夹"),value="output/denoise_opt")
with gr.Row():
denoise_info = gr.Textbox(label=i18n("语音降噪进程输出信息"))
open_denoise_button = gr.Button(i18n("开启语音降噪"), variant="primary",visible=True)
close_denoise_button = gr.Button(i18n("终止语音降噪进程"), variant="primary",visible=False)
denoise_input_dir=gr.Textbox(label=i18n("降噪音频文件输入文件夹"),value="")
denoise_output_dir=gr.Textbox(label=i18n("降噪结果输出文件夹"),value="output/denoise_opt")
denoise_info = gr.Textbox(label=i18n("语音降噪进程输出信息"))
gr.Markdown(value=i18n("0c-中文批量离线ASR工具"))
with gr.Row():
open_asr_button = gr.Button(i18n("开启离线批量ASR"), variant="primary",visible=True)
close_asr_button = gr.Button(i18n("终止ASR进程"), variant="primary",visible=False)
with gr.Column():
with gr.Column(scale=3):
with gr.Row():
asr_inp_dir = gr.Textbox(
label=i18n("输入文件夹路径"),
@@ -745,21 +850,43 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
)
asr_lang = gr.Dropdown(
label = i18n("ASR 语言设置"),
choices = ["zh"],
choices = ["zh","yue"],
interactive = True,
value="zh"
)
asr_precision = gr.Dropdown(
label = i18n("数据类型精度"),
choices = ["float32"],
interactive = True,
value="float32"
)
with gr.Row():
asr_info = gr.Textbox(label=i18n("ASR进程输出信息"))
asr_info = gr.Textbox(label=i18n("ASR进程输出信息"))
open_asr_button = gr.Button(i18n("开启离线批量ASR"), variant="primary",visible=True)
close_asr_button = gr.Button(i18n("终止ASR进程"), variant="primary",visible=False)
def change_lang_choices(key): #根据选择的模型修改可选的语言
# return gr.Dropdown(choices=asr_dict[key]['lang'])
return {"__type__": "update", "choices": asr_dict[key]['lang'],"value":asr_dict[key]['lang'][0]}
def change_size_choices(key): # 根据选择的模型修改可选的模型尺寸
# return gr.Dropdown(choices=asr_dict[key]['size'])
return {"__type__": "update", "choices": asr_dict[key]['size']}
return {"__type__": "update", "choices": asr_dict[key]['size'],"value":asr_dict[key]['size'][-1]}
def change_precision_choices(key): #根据选择的模型修改可选的语言
if key =="Faster Whisper (多语种)":
if default_batch_size <= 4:
precision = 'int8'
elif is_half:
precision = 'float16'
else:
precision = 'float32'
else:
precision = 'float32'
# return gr.Dropdown(choices=asr_dict[key]['precision'])
return {"__type__": "update", "choices": asr_dict[key]['precision'],"value":precision}
asr_model.change(change_lang_choices, [asr_model], [asr_lang])
asr_model.change(change_size_choices, [asr_model], [asr_size])
asr_model.change(change_precision_choices, [asr_model], [asr_precision])
gr.Markdown(value=i18n("0d-语音文本校对标注工具"))
with gr.Row():
@@ -772,20 +899,15 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
label_info = gr.Textbox(label=i18n("打标工具进程输出信息"))
if_label.change(change_label, [if_label,path_list], [label_info])
if_uvr5.change(change_uvr5, [if_uvr5], [uvr5_info])
open_asr_button.click(open_asr, [asr_inp_dir, asr_opt_dir, asr_model, asr_size, asr_lang], [asr_info,open_asr_button,close_asr_button])
close_asr_button.click(close_asr, [], [asr_info,open_asr_button,close_asr_button])
open_slicer_button.click(open_slice, [slice_inp_path,slice_opt_root,threshold,min_length,min_interval,hop_size,max_sil_kept,_max,alpha,n_process], [slicer_info,open_slicer_button,close_slicer_button])
close_slicer_button.click(close_slice, [], [slicer_info,open_slicer_button,close_slicer_button])
open_denoise_button.click(open_denoise, [denoise_input_dir,denoise_output_dir], [denoise_info,open_denoise_button,close_denoise_button])
close_denoise_button.click(close_denoise, [], [denoise_info,open_denoise_button,close_denoise_button])
with gr.TabItem(i18n("1-GPT-SoVITS-TTS")):
with gr.Row():
exp_name = gr.Textbox(label=i18n("*实验/模型名"), value="xxx", interactive=True)
gpu_info = gr.Textbox(label=i18n("显卡信息"), value=gpu_info, visible=True, interactive=False)
pretrained_s2G = gr.Textbox(label=i18n("预训练的SoVITS-G模型路径"), value="GPT_SoVITS/pretrained_models/s2G488k.pth", interactive=True)
pretrained_s2D = gr.Textbox(label=i18n("预训练的SoVITS-D模型路径"), value="GPT_SoVITS/pretrained_models/s2D488k.pth", interactive=True)
pretrained_s1 = gr.Textbox(label=i18n("预训练的GPT模型路径"), value="GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt", interactive=True)
version_checkbox = gr.Radio(label=i18n("版本"),value=version,choices=['v1','v2'])
pretrained_s2G = gr.Textbox(label=i18n("预训练的SoVITS-G模型路径"), value=pretrained_sovits_name[-int(version[-1])+2], interactive=True)
pretrained_s2D = gr.Textbox(label=i18n("预训练的SoVITS-D模型路径"), value=pretrained_sovits_name[-int(version[-1])+2].replace("s2G","s2D"), interactive=True)
pretrained_s1 = gr.Textbox(label=i18n("预训练的GPT模型路径"), value=pretrained_gpt_name[-int(version[-1])+2], interactive=True)
with gr.TabItem(i18n("1A-训练集格式化工具")):
gr.Markdown(value=i18n("输出logs/实验名目录下应有23456开头的文件和文件夹"))
with gr.Row():
@@ -821,6 +943,14 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
button1abc_open = gr.Button(i18n("开启一键三连"), variant="primary",visible=True)
button1abc_close = gr.Button(i18n("终止一键三连"), variant="primary",visible=False)
info1abc=gr.Textbox(label=i18n("一键三连进程输出信息"))
open_asr_button.click(open_asr, [asr_inp_dir, asr_opt_dir, asr_model, asr_size, asr_lang, asr_precision], [asr_info,open_asr_button,close_asr_button,path_list,inp_text,inp_wav_dir])
close_asr_button.click(close_asr, [], [asr_info,open_asr_button,close_asr_button])
open_slicer_button.click(open_slice, [slice_inp_path,slice_opt_root,threshold,min_length,min_interval,hop_size,max_sil_kept,_max,alpha,n_process], [slicer_info,open_slicer_button,close_slicer_button,asr_inp_dir,denoise_input_dir,inp_wav_dir])
close_slicer_button.click(close_slice, [], [slicer_info,open_slicer_button,close_slicer_button])
open_denoise_button.click(open_denoise, [denoise_input_dir,denoise_output_dir], [denoise_info,open_denoise_button,close_denoise_button,asr_inp_dir,inp_wav_dir])
close_denoise_button.click(close_denoise, [], [denoise_info,open_denoise_button,close_denoise_button])
button1a_open.click(open1a, [inp_text,inp_wav_dir,exp_name,gpu_numbers1a,bert_pretrained_dir], [info1a,button1a_open,button1a_close])
button1a_close.click(close1a, [], [info1a,button1a_open,button1a_close])
button1b_open.click(open1b, [inp_text,inp_wav_dir,exp_name,gpu_numbers1Ba,cnhubert_base_dir], [info1b,button1b_open,button1b_close])
@@ -863,8 +993,8 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
with gr.TabItem(i18n("1C-推理")):
gr.Markdown(value=i18n("选择训练完存放在SoVITS_weights和GPT_weights下的模型。默认的一个是底模,体验5秒Zero Shot TTS用。"))
with gr.Row():
GPT_dropdown = gr.Dropdown(label=i18n("*GPT模型列表"), choices=sorted(GPT_names,key=custom_sort_key),value=pretrained_gpt_name,interactive=True)
SoVITS_dropdown = gr.Dropdown(label=i18n("*SoVITS模型列表"), choices=sorted(SoVITS_names,key=custom_sort_key),value=pretrained_sovits_name,interactive=True)
GPT_dropdown = gr.Dropdown(label=i18n("*GPT模型列表"), choices=sorted(GPT_names,key=custom_sort_key),value=pretrained_gpt_name[0],interactive=True)
SoVITS_dropdown = gr.Dropdown(label=i18n("*SoVITS模型列表"), choices=sorted(SoVITS_names,key=custom_sort_key),value=pretrained_sovits_name[0],interactive=True)
gpu_number_1C=gr.Textbox(label=i18n("GPU卡号,只能填1个整数"), value=gpus, interactive=True)
refresh_button = gr.Button(i18n("刷新模型路径"), variant="primary")
refresh_button.click(fn=change_choices,inputs=[],outputs=[SoVITS_dropdown,GPT_dropdown])
@@ -872,6 +1002,7 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
if_tts = gr.Checkbox(label=i18n("是否开启TTS推理WebUI"), show_label=True)
tts_info = gr.Textbox(label=i18n("TTS推理WebUI进程输出信息"))
if_tts.change(change_tts_inference, [if_tts,bert_pretrained_dir,cnhubert_base_dir,gpu_number_1C,GPT_dropdown,SoVITS_dropdown], [tts_info])
version_checkbox.change(switch_version,[version_checkbox],[pretrained_s2G,pretrained_s2D,pretrained_s1,GPT_dropdown,SoVITS_dropdown])
with gr.TabItem(i18n("2-GPT-SoVITS-变声")):gr.Markdown(value=i18n("施工中,请静候佳音"))
app.queue(concurrency_count=511, max_size=1022).launch(
server_name="0.0.0.0",
@@ -879,4 +1010,4 @@ with gr.Blocks(title="GPT-SoVITS WebUI") as app:
share=is_share,
server_port=webui_port_main,
quiet=True,
)
)