GSVI_Test1 / Inference /src /Character_Manager.py
XTer
Automated commit from batch script
5bbd2a7
import gradio as gr
import os, json
# 在开头加入路径
import os, sys
now_dir = os.getcwd()
sys.path.append(now_dir)
# sys.path.append(os.path.join(now_dir, "tools"))
global state
state = { 'models_path': r"trained",
'character_list': [],
'edited_character_path': '',
'edited_character_name': '',
'ckpt_file_found': [],
'pth_file_found': [],
'wav_file_found': [],
}
global infer_config
infer_config = {
}
# 取得模型文件夹路径
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "config.json")
if os.path.exists(config_path):
with open(config_path, 'r', encoding='utf-8') as f:
config = json.load(f)
state["models_path"] = config.get("models_path", "trained")
locale_language = str(config.get("locale", "auto"))
locale_language = None if locale_language.lower() == "auto" else locale_language
from tools.i18n.i18n import I18nAuto
i18n = I18nAuto(locale_language ,os.path.join(os.path.dirname(os.path.dirname(__file__)), "i18n/locale"))
# 微软提供的SSML情感表
emotional_styles = [
"default",
"advertisement_upbeat", "affectionate", "angry", "assistant", "calm", "chat", "cheerful",
"customerservice", "depressed", "disgruntled", "documentary-narration", "embarrassed",
"empathetic", "envious", "excited", "fearful", "friendly", "gentle", "hopeful", "lyrical",
"narration-professional", "narration-relaxed", "newscast", "newscast-casual", "newscast-formal",
"poetry-reading", "sad", "serious", "shouting", "sports_commentary", "sports_commentary_excited",
"whispering", "terrified", "unfriendly"
]
language_list = ["auto", "zh", "en", "ja", "all_zh", "all_ja"]
translated_language_list = [i18n(language) for language in language_list]
language_dict = dict(zip(translated_language_list, language_list))
translated_language_dict = dict(zip(language_list, translated_language_list))
translated_language_dict.update(dict(zip(language_list, language_list)))
translated_language_dict.update(dict(zip(translated_language_list, translated_language_list)))
translated_language_dict["多语种混合"] = i18n("auto")
# 预先建立相当数量的情感选择框
all_emotion_num=len(emotional_styles)
def generate_info_bar():
current_character_textbox = gr.Textbox(value=state['edited_character_name'], label=i18n("当前人物"), interactive=False)
version_textbox = gr.Textbox(value=infer_config['version'], label=i18n("版本"), interactive=True)
gpt_model_dropdown = gr.Dropdown(choices=state['ckpt_file_found'], label=i18n("GPT模型路径"), interactive=True, value=infer_config['gpt_path'], allow_custom_value=True)
sovits_model_dropdown = gr.Dropdown(choices=state['pth_file_found'], label=i18n("Sovits模型路径"), interactive=True, value=infer_config['sovits_path'], allow_custom_value=True)
column_items = [current_character_textbox, version_textbox, gpt_model_dropdown, sovits_model_dropdown]
index = 0
for item in infer_config['emotion_list']:
emotion, details = item
index += 1
column_items.append(gr.Number(index, visible=True, scale=1))
column_items.append(gr.Dropdown(choices=translated_language_list, value=translated_language_dict[details['prompt_language']], visible=True, interactive=True, scale=3, label=i18n("提示语言")))
column_items.append(gr.Dropdown(choices=emotional_styles, value=emotion, visible=True, interactive=True, scale=3, allow_custom_value=True, label=i18n("情感风格")))
column_items.append(gr.Dropdown(choices=state["wav_file_found"], visible=True, value=details['ref_wav_path'], scale=8, allow_custom_value=True, label=i18n("参考音频路径")))
column_items.append(gr.Textbox(value=details['prompt_text'], visible=True, scale=8, interactive=True, label=i18n("提示文本")))
column_items.append(gr.Audio(os.path.join(state["edited_character_path"], details['ref_wav_path']), visible=True, scale=8, label=i18n("音频预览")))
for i in range(all_emotion_num - index):
column_items.append(gr.Number(i, visible=False))
column_items.append(gr.Dropdown(visible=False))
column_items.append(gr.Dropdown(visible=False))
column_items.append(gr.Dropdown(visible=False))
column_items.append(gr.Textbox(visible=False))
column_items.append(gr.Audio(None, visible=False))
return column_items
def load_json_to_state(data):
infer_config['version'] = data.get('version','')
emotional_list = data.get('emotion_list',{})
for emotion, details in emotional_list.items():
infer_config['emotion_list'].append([emotion,details])
infer_config['gpt_path'] = data['gpt_path']
infer_config['sovits_path'] = data['sovits_path']
return generate_info_bar()
def split_file_name(file_name):
try :
base_name=os.path.basename(file_name)
except:
base_name=file_name
final_name = os.path.splitext(base_name)[0]
return final_name
def clear_infer_config():
global infer_config
infer_config = {
'version': '1.0.1',
'gpt_path': '',
'sovits_path': '',
'emotion_list': [],
}
clear_infer_config()
def read_json_from_file(character_dropdown,models_path ):
state['edited_character_name'] = character_dropdown
state['models_path']=models_path
state['edited_character_path'] = os.path.join(state['models_path'], state['edited_character_name'])
state['ckpt_file_found'], state['pth_file_found'], state['wav_file_found'] = scan_files(state['edited_character_path'])
print(i18n("当前人物变更为: ")+state['edited_character_name'])
clear_infer_config()
json_path = os.path.join(state['edited_character_path'], "infer_config.json")
# 从json文件中读取数据
with open(json_path, "r", encoding='utf-8') as f:
data = json.load(f)
return load_json_to_state(data)
def save_json():
if infer_config['gpt_path'] == '' or infer_config['gpt_path'] is None:
gr.Error(i18n("缺失某些项,保存失败!"))
raise Exception(i18n("缺失某些项,保存失败!"))
json_path = os.path.join(state['edited_character_path'], "infer_config.json")
data = {
'version': infer_config['version'],
'gpt_path': infer_config['gpt_path'],
'sovits_path': infer_config['sovits_path'],
i18n("简介"): i18n(r"这是一个配置文件适用于https://github.com/X-T-E-R/TTS-for-GPT-soVITS,是一个简单好用的前后端项目"),
'emotion_list': {}
}
for item in infer_config['emotion_list']:
data['emotion_list'][item[0]] = item[1]
try:
# 将state中的数据保存到json文件中
with open(json_path, "w", encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
gr.Info(i18n("保存成功!"))
except:
gr.Error(i18n("文件打开失败,保存失败!"))
raise Exception(i18n("保存失败!"))
def scan_files(character_path):
ckpt_file_found = []
pth_file_found = []
wav_file_found = []
# 扫描3种文件
for dirpath, dirnames, filenames in os.walk(character_path):
for file in filenames:
# 构建文件的完整路径
full_path = os.path.join(dirpath, file)
rev_path = os.path.relpath(full_path, character_path)
print(full_path)
# 根据文件扩展名和变量是否已赋值来更新变量
if file.lower().endswith(".ckpt"):
ckpt_file_found.append(rev_path)
elif file.lower().endswith(".pth"):
pth_file_found.append(rev_path)
elif file.lower().endswith(".wav"):
wav_file_found.append(rev_path)
return ckpt_file_found, pth_file_found, wav_file_found
def auto_generate_json(character_dropdown, models_path):
# 将选中人物设定为当前人物
state['edited_character_name'] = character_dropdown
state['models_path'] = models_path
state['edited_character_path'] = os.path.join(state['models_path'], state['edited_character_name'])
print(i18n(f"当前人物变更为: {state['edited_character_name']}"))
clear_infer_config()
character_path = state['edited_character_path']
ckpt_file_found, pth_file_found, wav_file_found = scan_files(character_path)
if len(ckpt_file_found) == 0 or len(pth_file_found) == 0:
gr.Error(i18n("找不到模型文件!请把有效文件放置在文件夹下!!!"))
raise Exception(i18n("找不到模型文件!请把有效文件放置在文件夹下!!!"))
else:
state['ckpt_file_found'] = ckpt_file_found
state['pth_file_found'] = pth_file_found
state['wav_file_found'] = wav_file_found
gpt_path = ckpt_file_found[0]
sovits_path = pth_file_found[0]
infer_config['gpt_path'] = gpt_path
infer_config['sovits_path'] = sovits_path
if len(wav_file_found) == 0:
return generate_info_bar()
else:
return add_emotion()
def scan_subfolder(models_path):
subfolders = [os.path.basename(f.path) for f in os.scandir(models_path) if f.is_dir()]
state['models_path'] = models_path
state['character_list'] = subfolders
print(i18n("扫描模型文件夹:")+models_path)
print(i18n(f"找到的角色列表:") + str(subfolders))
gr.Info(i18n(f"找到的角色列表:") + str(subfolders))
d2 = gr.Dropdown(subfolders)
return d2
def add_emotion():
unused_emotional_style = ''
for style in emotional_styles:
style_in_list = False
for item in infer_config['emotion_list']:
if style == item[0]:
style_in_list = True
break
if not style_in_list:
unused_emotional_style = style
break
ref_wav_path = state['wav_file_found'][0]
infer_config['emotion_list'].append([f'{unused_emotional_style}', {
'ref_wav_path':ref_wav_path,'prompt_text':split_file_name(ref_wav_path),'prompt_language':'auto'}])
return generate_info_bar()
def change_pt_files(version_textbox, sovits_model_dropdown, gpt_model_dropdown):
infer_config['version'] = version_textbox
infer_config['sovits_path'] = sovits_model_dropdown
infer_config['gpt_path'] = gpt_model_dropdown
pass
def change_parameters(index, wav_path, emotion_list, prompt_language, prompt_text = ""):
# Convert index to integer in case it's passed as a string
index = int(index)
if prompt_text=="" or prompt_text is None:
prompt_text = split_file_name(wav_path)
infer_config['emotion_list'][index-1][0]=emotion_list
infer_config['emotion_list'][index-1][1]['ref_wav_path'] = wav_path
infer_config['emotion_list'][index-1][1]['prompt_text'] = prompt_text
infer_config['emotion_list'][index-1][1]['prompt_language'] = language_dict[prompt_language]
return gr.Dropdown(value=wav_path), gr.Dropdown(value=emotion_list), gr.Dropdown(value=prompt_language), gr.Textbox(value=prompt_text), gr.Audio(os.path.join(state["edited_character_path"],wav_path))
with gr.Blocks() as app:
with gr.Row() as status_bar:
# 创建模型文件夹路径的输入框
models_path = gr.Textbox(value=state["models_path"], label=i18n("模型文件夹路径"), scale=3)
# 创建扫描按钮并设置点击事件
scan_button = gr.Button(i18n("扫描"), scale=1, variant="primary")
# 创建角色列表的下拉菜单,初始为空
character_dropdown = gr.Dropdown([], label=i18n("选择角色"), scale=3)
# 创建从json中读取按钮并设置点击事件
read_info_from_json_button = gr.Button(i18n("从json中读取"), size="lg", scale=2, variant="secondary")
# 创建自动生成json的按钮并设置点击事件
auto_generate_info_button = gr.Button(i18n("自动生成info"), size="lg", scale=2, variant="primary")
scan_button.click(scan_subfolder, inputs=[models_path], outputs=[character_dropdown])
gr.HTML(i18n("""<p>这是模型管理界面,为了实现对多段参考音频分配情感设计,如果您只有一段可不使用这个界面</p><p>若有疑问或需要进一步了解,可参考文档:<a href="https://www.yuque.com/xter/zibxlp/hme8bw2r28vad3le">点击查看详细文档</a>。</p>"""))
gr.Markdown(i18n("请修改后点击下方按钮进行保存"))
# 创建保存json的按钮并设置点击事件
with gr.Row() as submit_bar:
save_json_button = gr.Button(i18n("保存json\n(可能不会有完成提示,没报错就是成功)"), scale=2, variant="primary")
save_json_button.click(save_json)
# 模型信息
with gr.Row():
with gr.Column(scale=1):
current_character_textbox = gr.Textbox(value=state['edited_character_name'], label=i18n("当前人物"), interactive=False)
version_textbox = gr.Textbox(value=infer_config['version'], label=i18n("版本"))
gpt_model_dropdown = gr.Dropdown(choices=state['ckpt_file_found'], label=i18n("GPT模型路径"))
sovits_model_dropdown = gr.Dropdown(choices=state['pth_file_found'], label=i18n("Sovits模型路径"))
version_textbox.blur(change_pt_files, inputs=[version_textbox, sovits_model_dropdown, gpt_model_dropdown], outputs=None)
gpt_model_dropdown.input(change_pt_files, inputs=[version_textbox, sovits_model_dropdown, gpt_model_dropdown], outputs=None)
sovits_model_dropdown.input(change_pt_files, inputs=[version_textbox, sovits_model_dropdown, gpt_model_dropdown], outputs=None)
column_items = [current_character_textbox, version_textbox, gpt_model_dropdown, sovits_model_dropdown]
with gr.Column(scale=3):
add_emotion_button = gr.Button(i18n("添加情感"), size="lg", scale=2, variant="primary")
for index in range(all_emotion_num):
with gr.Row() as emotion_row:
row_index = gr.Number(visible=False)
emotional_list = gr.Dropdown(visible=False)
prompt_language = gr.Dropdown(visible=False)
wav_path = gr.Dropdown(visible=False)
prompt_text = gr.Textbox(visible=False)
audio_preview = gr.Audio(visible=False, type="filepath")
emotional_list.input(change_parameters, inputs=[row_index, wav_path, emotional_list, prompt_language, prompt_text], outputs=[wav_path, emotional_list, prompt_language, prompt_text, audio_preview])
prompt_language.input(change_parameters, inputs=[row_index, wav_path, emotional_list, prompt_language, prompt_text], outputs=[wav_path, emotional_list, prompt_language, prompt_text, audio_preview])
wav_path.input(change_parameters, inputs=[row_index, wav_path, emotional_list, prompt_language], outputs=[wav_path, emotional_list, prompt_language, prompt_text, audio_preview])
prompt_text.input(change_parameters, inputs=[row_index, wav_path, emotional_list, prompt_language, prompt_text], outputs=[wav_path, emotional_list, prompt_language, prompt_text, audio_preview])
column_items.append(row_index)
column_items.append(prompt_language)
column_items.append(emotional_list)
column_items.append(wav_path)
column_items.append(prompt_text)
column_items.append(audio_preview)
add_emotion_button.click(add_emotion, outputs=column_items)
read_info_from_json_button.click(read_json_from_file, inputs=[character_dropdown,models_path] , outputs=column_items)
auto_generate_info_button.click(auto_generate_json, inputs=[character_dropdown,models_path], outputs=column_items)
app.launch(server_port=9868, show_error=True,debug=True, inbrowser=True)