mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-09 00:09:55 +00:00
Add speed control and cleanup the code
This commit is contained in:
+171
-129
@@ -1,4 +1,4 @@
|
||||
import os
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import logging
|
||||
@@ -26,10 +26,10 @@ from tools.i18n.i18n import I18nAuto
|
||||
# Additional Imports and GPU Info
|
||||
import pdb
|
||||
|
||||
# Display environment variables and GPU info
|
||||
print("Env vars:")
|
||||
print(os.environ)
|
||||
|
||||
|
||||
def print_gpu_info():
|
||||
print('========================================')
|
||||
print('Python interpreter', sys.executable)
|
||||
@@ -60,6 +60,9 @@ dict_language = {
|
||||
"automatic": "auto",
|
||||
}
|
||||
|
||||
# Define punctuation set
|
||||
punctuation = set(['!', '?', '…', ',', '.', '-'," "])
|
||||
|
||||
# Define default paths for pretrained models
|
||||
pretrained_gpt_path = "GPT_SoVITS/pretrained_models/s1bert25hz-2kh-longer-epoch=68e-step=50232.ckpt"
|
||||
pretrained_sovits_path = "GPT_SoVITS/pretrained_models/s2G488k.pth"
|
||||
@@ -91,7 +94,7 @@ cnhubert.cnhubert_base_path = cnhubert_base_path
|
||||
loaded_gpt_path = None
|
||||
loaded_sovits_path = None
|
||||
|
||||
# Example: Get BERT feature
|
||||
# Function to get BERT feature
|
||||
def get_bert_feature(text, word2ph):
|
||||
global tokenizer, bert_model
|
||||
if not "tokenizer" in globals() or not "bert_model" in globals():
|
||||
@@ -115,6 +118,7 @@ def get_bert_feature(text, word2ph):
|
||||
phone_level_feature = torch.cat(phone_level_feature, dim=0)
|
||||
return phone_level_feature.T
|
||||
|
||||
# Class to convert dictionary to attributes recursively
|
||||
class DictToAttrRecursive(dict):
|
||||
def __init__(self, input_dict):
|
||||
super().__init__(input_dict)
|
||||
@@ -142,6 +146,7 @@ class DictToAttrRecursive(dict):
|
||||
except KeyError:
|
||||
raise AttributeError(f"Attribute {item} not found")
|
||||
|
||||
# Function to change SoVITS weights
|
||||
def change_sovits_weights(sovits_path):
|
||||
global vq_model, hps
|
||||
dict_s2 = torch.load(sovits_path, map_location="cpu")
|
||||
@@ -165,6 +170,7 @@ def change_sovits_weights(sovits_path):
|
||||
with open("./sweight.txt", "w", encoding="utf-8") as f:
|
||||
f.write(sovits_path)
|
||||
|
||||
# Function to change GPT weights
|
||||
def change_gpt_weights(gpt_path):
|
||||
global hz, max_sec, t2s_model, config
|
||||
hz = 50
|
||||
@@ -182,11 +188,11 @@ def change_gpt_weights(gpt_path):
|
||||
with open("./gweight.txt", "w", encoding="utf-8") as f:
|
||||
f.write(gpt_path)
|
||||
|
||||
# Function to get spectrogram
|
||||
def get_spepc(hps, filename):
|
||||
audio = load_audio(filename, int(hps.data.sampling_rate))
|
||||
audio = torch.FloatTensor(audio)
|
||||
audio_norm = audio
|
||||
audio_norm = audio_norm.unsqueeze(0)
|
||||
audio_norm = audio.unsqueeze(0)
|
||||
spec = spectrogram_torch(
|
||||
audio_norm,
|
||||
hps.data.filter_length,
|
||||
@@ -197,14 +203,15 @@ def get_spepc(hps, filename):
|
||||
)
|
||||
return spec
|
||||
|
||||
# Function to clean text
|
||||
def clean_text_inf(text, language):
|
||||
phones, word2ph, norm_text = clean_text(text, language)
|
||||
print(f'Phonemes for "{text}":\n{phones}')
|
||||
phones = cleaned_text_to_sequence(phones)
|
||||
return phones, word2ph, norm_text
|
||||
|
||||
dtype = torch.float16 if is_half else torch.float32
|
||||
|
||||
# Function to get BERT inference
|
||||
def get_bert_inf(phones, word2ph, norm_text, language):
|
||||
language = language.replace("all_", "")
|
||||
if language == "zh":
|
||||
@@ -214,20 +221,20 @@ def get_bert_inf(phones, word2ph, norm_text, language):
|
||||
(1024, len(phones)),
|
||||
dtype=torch.float16 if is_half else torch.float32,
|
||||
).to(device)
|
||||
|
||||
return bert
|
||||
|
||||
splits = {",", "。", "?", "!", ",", ".", "?", "!", "~", ":", ":", "—", "…", }
|
||||
# Splitting functions for text slicing
|
||||
splits = {",", "。", "?", "!", ",", ".", "?", "!", "~", ":", ":", "—", "…"}
|
||||
|
||||
# Function to get the first segment of text before punctuation
|
||||
def get_first(text):
|
||||
pattern = "[" + "".join(re.escape(sep) for sep in splits) + "]"
|
||||
text = re.split(pattern, text)[0].strip()
|
||||
return text
|
||||
|
||||
# Function to get phones and BERT embeddings
|
||||
def get_phones_and_bert(text, language):
|
||||
phones = None
|
||||
bert = None
|
||||
norm_text = None
|
||||
|
||||
if language in {"en", "all_zh", "all_ja"}:
|
||||
language = language.replace("all_", "")
|
||||
if language == "en":
|
||||
@@ -237,10 +244,17 @@ def get_phones_and_bert(text, language):
|
||||
formattext = text
|
||||
while " " in formattext:
|
||||
formattext = formattext.replace(" ", " ")
|
||||
phones, word2ph, norm_text = clean_text_inf(formattext, language)
|
||||
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")
|
||||
else:
|
||||
phones, word2ph, norm_text = clean_text_inf(formattext, language)
|
||||
|
||||
bert = get_bert_feature(norm_text, word2ph).to(device)
|
||||
else:
|
||||
phones, word2ph, norm_text = clean_text_inf(formattext, language)
|
||||
bert = torch.zeros(
|
||||
(1024, len(phones)),
|
||||
dtype=torch.float16 if is_half else torch.float32,
|
||||
@@ -279,11 +293,10 @@ def get_phones_and_bert(text, language):
|
||||
bert = torch.cat(bert_list, dim=1)
|
||||
phones = sum(phones_list, [])
|
||||
norm_text = ''.join(norm_text_list)
|
||||
else:
|
||||
raise ValueError(f"Unsupported language: {language}")
|
||||
|
||||
|
||||
return phones, bert.to(dtype), norm_text
|
||||
|
||||
# Function to merge short texts
|
||||
def merge_short_text_in_array(texts, threshold):
|
||||
if len(texts) < 2:
|
||||
return texts
|
||||
@@ -307,134 +320,135 @@ if is_half:
|
||||
else:
|
||||
ssl_model = ssl_model.to(device)
|
||||
|
||||
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):
|
||||
t0 = ttime()
|
||||
cache = {}
|
||||
|
||||
# Main function for TTS synthesis
|
||||
def get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut="No slice", top_k=20, top_p=0.6, temperature=0.6, ref_free=False, speed=1.0, if_freeze=False):
|
||||
global cache
|
||||
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 "."
|
||||
print(f"Reference text: {prompt_text}")
|
||||
phones1,bert1,norm_text1=get_phones_and_bert(prompt_text, prompt_language)
|
||||
if prompt_text[-1] not in splits:
|
||||
prompt_text += "。" if prompt_language != "en" else "."
|
||||
print("Actual reference text:", prompt_text)
|
||||
|
||||
text = text.strip("\n")
|
||||
if (text[0] not in splits and len(get_first(text)) < 4): text = "。" + text if text_language != "en" else "." + text
|
||||
if text[0] not in splits and len(get_first(text)) < 4:
|
||||
text = "。" + text if text_language != "en" else "." + text
|
||||
|
||||
print(f"Full text: {text}")
|
||||
zero_wav = np.zeros(
|
||||
int(hps.data.sampling_rate * 0.3),
|
||||
dtype=np.float16 if is_half == True else np.float32,
|
||||
)
|
||||
with torch.no_grad():
|
||||
wav16k, sr = librosa.load(ref_wav_path, sr=16000)
|
||||
if (wav16k.shape[0] > 160000 or wav16k.shape[0] < 48000):
|
||||
raise OSError("参考音频在3~10秒范围外,请更换!")
|
||||
wav16k = torch.from_numpy(wav16k)
|
||||
zero_wav_torch = torch.from_numpy(zero_wav)
|
||||
if is_half == True:
|
||||
wav16k = wav16k.half().to(device)
|
||||
zero_wav_torch = zero_wav_torch.half().to(device)
|
||||
else:
|
||||
wav16k = wav16k.to(device)
|
||||
zero_wav_torch = zero_wav_torch.to(device)
|
||||
wav16k = torch.cat([wav16k, zero_wav_torch])
|
||||
ssl_content = ssl_model.model(wav16k.unsqueeze(0))[
|
||||
"last_hidden_state"
|
||||
].transpose(
|
||||
1, 2
|
||||
) # .float()
|
||||
codes = vq_model.extract_latent(ssl_content)
|
||||
print("Actual target text:", text)
|
||||
zero_wav = np.zeros(int(hps.data.sampling_rate * 0.3), dtype=np.float16 if is_half else np.float32)
|
||||
|
||||
prompt_semantic = codes[0, 0]
|
||||
t1 = ttime()
|
||||
|
||||
if (how_to_cut == "Slice once every 4 sentences"):
|
||||
if not ref_free:
|
||||
with torch.no_grad():
|
||||
wav16k, sr = librosa.load(ref_wav_path, sr=16000)
|
||||
if wav16k.shape[0] > 160000 or wav16k.shape[0] < 48000:
|
||||
raise OSError("Reference audio must be within 3~10 seconds.")
|
||||
wav16k = torch.from_numpy(wav16k)
|
||||
zero_wav_torch = torch.from_numpy(zero_wav)
|
||||
wav16k = wav16k.half().to(device) if is_half else wav16k.to(device)
|
||||
zero_wav_torch = zero_wav_torch.half().to(device) if is_half else zero_wav_torch.to(device)
|
||||
wav16k = torch.cat([wav16k, zero_wav_torch])
|
||||
ssl_content = ssl_model.model(wav16k.unsqueeze(0))["last_hidden_state"].transpose(1, 2)
|
||||
codes = vq_model.extract_latent(ssl_content)
|
||||
prompt_semantic = codes[0, 0]
|
||||
prompt = prompt_semantic.unsqueeze(0).to(device)
|
||||
|
||||
t2 = ttime()
|
||||
|
||||
# Slice the text based on the provided method
|
||||
if how_to_cut == "Slice once every 4 sentences":
|
||||
text = cut1(text)
|
||||
elif (how_to_cut == "Cut per 50 characters"):
|
||||
elif how_to_cut == "Cut per 50 characters":
|
||||
text = cut2(text)
|
||||
elif (how_to_cut == "Slice by Chinese punct"):
|
||||
elif how_to_cut == "Slice by Chinese punct":
|
||||
text = cut3(text)
|
||||
elif (how_to_cut == "Slice by English punct"):
|
||||
elif how_to_cut == "Slice by English punct":
|
||||
text = cut4(text)
|
||||
elif (how_to_cut == "Slice by every punct"):
|
||||
elif how_to_cut == "Slice by every punct":
|
||||
text = cut5(text)
|
||||
|
||||
while "\n\n" in text:
|
||||
text = text.replace("\n\n", "\n")
|
||||
print(f"Text after slicing:\n{text}")
|
||||
|
||||
print("Actual target text (after slicing):", text)
|
||||
texts = text.split("\n")
|
||||
texts = process_text(texts) # Filter out invalid text entries
|
||||
texts = merge_short_text_in_array(texts, 5)
|
||||
audio_opt = []
|
||||
|
||||
t2 = ttime()
|
||||
t3, t4, t5 = 0, 0, 0
|
||||
|
||||
for text in texts:
|
||||
# 解决输入目标文本的空行导致报错的问题
|
||||
t3s = ttime()
|
||||
if (len(text.strip()) == 0):
|
||||
|
||||
if not ref_free:
|
||||
phones1, bert1, norm_text1 = get_phones_and_bert(prompt_text, prompt_language)
|
||||
|
||||
t3_start = ttime()
|
||||
|
||||
for i_text, text in enumerate(texts):
|
||||
if len(text.strip()) == 0:
|
||||
continue
|
||||
if (text[-1] not in splits): text += "。" if text_language != "en" else "."
|
||||
print(f"Text being generated: {text}")
|
||||
phones2,bert2,norm_text2=get_phones_and_bert(text, text_language)
|
||||
print(f"Text after frontend processing: {norm_text2}")
|
||||
if text[-1] not in splits:
|
||||
text += "。" if text_language != "en" else "."
|
||||
print("Actual target text (per sentence):", text)
|
||||
phones2, bert2, norm_text2 = get_phones_and_bert(text, text_language)
|
||||
print("Processed text (per sentence):", norm_text2)
|
||||
|
||||
if not ref_free:
|
||||
bert = torch.cat([bert1, bert2], 1)
|
||||
all_phoneme_ids = torch.LongTensor(phones1+phones2).to(device).unsqueeze(0)
|
||||
all_phoneme_ids = torch.LongTensor(phones1 + phones2).to(device).unsqueeze(0)
|
||||
else:
|
||||
bert = bert2
|
||||
all_phoneme_ids = torch.LongTensor(phones2).to(device).unsqueeze(0)
|
||||
|
||||
bert = bert.to(device).unsqueeze(0)
|
||||
all_phoneme_len = torch.tensor([all_phoneme_ids.shape[-1]]).to(device)
|
||||
prompt = prompt_semantic.unsqueeze(0).to(device)
|
||||
t3e = ttime()
|
||||
t3 += t3e - t3s
|
||||
with torch.no_grad():
|
||||
# pred_semantic = t2s_model.model.infer(
|
||||
pred_semantic, idx = t2s_model.model.infer_panel(
|
||||
all_phoneme_ids,
|
||||
all_phoneme_len,
|
||||
None if ref_free else prompt,
|
||||
bert,
|
||||
# prompt_phone_len=ph_offset,
|
||||
top_k=top_k,
|
||||
top_p=top_p,
|
||||
temperature=temperature,
|
||||
early_stop_num=hz * max_sec,
|
||||
)
|
||||
t4e = ttime()
|
||||
t4 += t4e - t3e
|
||||
# print(pred_semantic.shape,idx)
|
||||
pred_semantic = pred_semantic[:, -idx:].unsqueeze(
|
||||
0
|
||||
) # .unsqueeze(0)#mq要多unsqueeze一次
|
||||
refer = get_spepc(hps, ref_wav_path) # .to(device)
|
||||
if is_half == True:
|
||||
refer = refer.half().to(device)
|
||||
|
||||
if i_text in cache and if_freeze:
|
||||
pred_semantic = cache[i_text]
|
||||
else:
|
||||
refer = refer.to(device)
|
||||
# audio = vq_model.decode(pred_semantic, all_phoneme_ids, refer).detach().cpu().numpy()[0, 0]
|
||||
audio = (
|
||||
vq_model.decode(
|
||||
pred_semantic, torch.LongTensor(phones2).to(device).unsqueeze(0), refer
|
||||
)
|
||||
.detach()
|
||||
.cpu()
|
||||
.numpy()[0, 0]
|
||||
) ###试试重建不带上prompt部分
|
||||
max_audio=np.abs(audio).max()#简单防止16bit爆音
|
||||
if max_audio>1:audio/=max_audio
|
||||
with torch.no_grad():
|
||||
pred_semantic, idx = t2s_model.model.infer_panel(
|
||||
all_phoneme_ids,
|
||||
all_phoneme_len,
|
||||
None if ref_free else prompt,
|
||||
bert,
|
||||
top_k=top_k,
|
||||
top_p=top_p,
|
||||
temperature=temperature,
|
||||
early_stop_num=hz * max_sec,
|
||||
)
|
||||
pred_semantic = pred_semantic[:, -idx:].unsqueeze(0)
|
||||
cache[i_text] = pred_semantic
|
||||
|
||||
refer = get_spepc(hps, ref_wav_path).to(device)
|
||||
if is_half:
|
||||
refer = refer.half().to(device)
|
||||
audio = vq_model.decode(pred_semantic, torch.LongTensor(phones2).to(device).unsqueeze(0), refer, speed=speed).detach().cpu().numpy()[0, 0]
|
||||
max_audio = np.abs(audio).max()
|
||||
if max_audio > 1:
|
||||
audio /= max_audio
|
||||
audio_opt.append(audio)
|
||||
audio_opt.append(zero_wav)
|
||||
t5e = ttime()
|
||||
t5 += t5e - t4e
|
||||
return (
|
||||
(t1-t0, t2-t1, t3, t4, t5),
|
||||
hps.data.sampling_rate,
|
||||
(np.concatenate(audio_opt, 0) * 32768).astype(np.int16)
|
||||
)
|
||||
|
||||
t3_end = ttime()
|
||||
|
||||
t4_start = ttime()
|
||||
|
||||
# Concatenate audio options
|
||||
concatenated_audio = np.concatenate(audio_opt, 0) * 32768
|
||||
|
||||
t4_end = ttime()
|
||||
|
||||
print("%.3f\t%.3f\t%.3f\t%.3f" % (t1 - t0, t2 - t1, t3_end - t3_start, t4_end - t4_start))
|
||||
return (t1 - t0, t2 - t1, t3_end - t3_start, t4_end - t4_start, t4_end - t4_start), hps.data.sampling_rate, concatenated_audio.astype(np.int16)
|
||||
|
||||
# Function to split text based on punctuation
|
||||
def split(todo_text):
|
||||
todo_text = todo_text.replace("……", "。").replace("——", ",")
|
||||
if todo_text[-1] not in splits:
|
||||
@@ -444,7 +458,7 @@ def split(todo_text):
|
||||
todo_texts = []
|
||||
while 1:
|
||||
if i_split_head >= len_text:
|
||||
break
|
||||
break # There will always be punctuation at the end, so just exit, the last segment was already added last time
|
||||
if todo_text[i_split_head] in splits:
|
||||
i_split_head += 1
|
||||
todo_texts.append(todo_text[i_split_tail:i_split_head])
|
||||
@@ -453,6 +467,7 @@ def split(todo_text):
|
||||
i_split_head += 1
|
||||
return todo_texts
|
||||
|
||||
# Functions to cut text in various ways
|
||||
def cut1(inp):
|
||||
inp = inp.strip("\n")
|
||||
inps = split(inp)
|
||||
@@ -464,6 +479,7 @@ def cut1(inp):
|
||||
opts.append("".join(inps[split_idx[idx]: split_idx[idx + 1]]))
|
||||
else:
|
||||
opts = [inp]
|
||||
opts = [item for item in opts if not set(item).issubset(punctuation)]
|
||||
return "\n".join(opts)
|
||||
|
||||
def cut2(inp):
|
||||
@@ -486,27 +502,57 @@ def cut2(inp):
|
||||
if len(opts) > 1 and len(opts[-1]) < 50:
|
||||
opts[-2] = opts[-2] + opts[-1]
|
||||
opts = opts[:-1]
|
||||
opts = [item for item in opts if not set(item).issubset(punctuation)]
|
||||
return "\n".join(opts)
|
||||
|
||||
def cut3(inp):
|
||||
inp = inp.strip("\n")
|
||||
return "\n".join(["%s" % item for item in inp.strip("。").split("。")])
|
||||
opts = ["%s" % item for item in inp.strip("。").split("。")]
|
||||
opts = [item for item in opts if not set(item).issubset(punctuation)]
|
||||
return "\n".join(opts)
|
||||
|
||||
def cut4(inp):
|
||||
inp = inp.strip("\n")
|
||||
return "\n".join(["%s" % item for item in inp.strip(".").split(".")])
|
||||
opts = ["%s" % item for item in inp.strip(".").split(".")]
|
||||
opts = [item for item in opts if not set(item).issubset(punctuation)]
|
||||
return "\n".join(opts)
|
||||
|
||||
# Contributed by https://github.com/AI-Hobbyist/GPT-SoVITS/blob/main/GPT_SoVITS/inference_webui.py
|
||||
def cut5(inp):
|
||||
inp = inp.strip("\n")
|
||||
punds = r'[,.;?!、,。?!;:…]'
|
||||
items = re.split(f'({punds})', inp)
|
||||
mergeitems = ["".join(group) for group in zip(items[::2], items[1::2])]
|
||||
if len(items) % 2 == 1:
|
||||
mergeitems.append(items[-1])
|
||||
opt = "\n".join(mergeitems)
|
||||
return opt
|
||||
punds = {',', '.', ';', '?', '!', '、', ',', '。', '?', '!', ';', ':', '…'}
|
||||
mergeitems = []
|
||||
items = []
|
||||
|
||||
def gptsovits_inference(gpt_model_path, sovits_model_path, ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut="No slice", top_k=20, top_p=0.6, temperature=0.6, ref_free=False):
|
||||
for i, char in enumerate(inp):
|
||||
if char in punds:
|
||||
if char == '.' and i > 0 and i < len(inp) - 1 and inp[i - 1].isdigit() and inp[i + 1].isdigit():
|
||||
items.append(char)
|
||||
else:
|
||||
items.append(char)
|
||||
mergeitems.append("".join(items))
|
||||
items = []
|
||||
else:
|
||||
items.append(char)
|
||||
|
||||
if items:
|
||||
mergeitems.append("".join(items))
|
||||
|
||||
opt = [item for item in mergeitems if not set(item).issubset(punds)]
|
||||
return "\n".join(opt)
|
||||
|
||||
# Function to process and filter text entries
|
||||
def process_text(texts):
|
||||
_text = []
|
||||
if all(text in [None, " ", "\n", ""] for text in texts):
|
||||
raise ValueError(i18n("Please enter valid text"))
|
||||
for text in texts:
|
||||
if text not in [None, " ", "", "\n"]:
|
||||
_text.append(text)
|
||||
return _text
|
||||
|
||||
# Main function for inference
|
||||
def gptsovits_inference(gpt_model_path, sovits_model_path, ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut="No slice", top_k=20, top_p=0.6, temperature=0.6, ref_free=False, speed=1.0):
|
||||
global loaded_gpt_path, loaded_sovits_path
|
||||
if not os.path.exists(ref_wav_path):
|
||||
print("You must input a reference audio path!")
|
||||
@@ -532,18 +578,12 @@ def gptsovits_inference(gpt_model_path, sovits_model_path, ref_wav_path, prompt_
|
||||
break
|
||||
output_count += 1
|
||||
|
||||
times, sr, audio_data = get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut, top_k, top_p, temperature, ref_free)
|
||||
times, sr, audio_data = get_tts_wav(ref_wav_path, prompt_text, prompt_language, text, text_language, how_to_cut, top_k, top_p, temperature, ref_free, speed)
|
||||
|
||||
sf.write(
|
||||
current_output_path,
|
||||
audio_data,
|
||||
sr,
|
||||
format="wav"
|
||||
)
|
||||
sf.write(current_output_path, audio_data, sr, format="wav")
|
||||
print("Times:\nref_audio: {:.2f}s text: {:.2f}s phonemes & bert: {:.2f}s gpt: {:.2f}s sovits: {:.2f}s".format(*times))
|
||||
return current_output_path
|
||||
|
||||
|
||||
# Command-line interface
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="GPT-SoVITS TTS Inference CLI")
|
||||
@@ -560,6 +600,7 @@ def main():
|
||||
parser.add_argument("--top_k", type=int, default=20, help="Top K sampling")
|
||||
parser.add_argument("--top_p", type=float, default=0.6, help="Top P sampling")
|
||||
parser.add_argument("--temperature", type=float, default=0.6, help="Sampling temperature")
|
||||
parser.add_argument("--speed", type=float, default=1.0, help="Speed of the synthesized speech")
|
||||
parser.add_argument("--output_path", type=str, default="output", help="Path to save the output wav file")
|
||||
|
||||
args = parser.parse_args()
|
||||
@@ -593,7 +634,8 @@ def main():
|
||||
top_k=args.top_k,
|
||||
top_p=args.top_p,
|
||||
temperature=args.temperature,
|
||||
ref_free=False
|
||||
ref_free=False,
|
||||
speed=args.speed
|
||||
)
|
||||
|
||||
if gptsovits_output_audio_path:
|
||||
|
||||
Reference in New Issue
Block a user