from datetime import datetime import gradio as gr import json, os import requests import numpy as np from string import Template import wave, io # 在开头加入路径 import os, sys now_dir = os.getcwd() sys.path.insert(0, now_dir) import logging logging.getLogger("markdown_it").setLevel(logging.ERROR) logging.getLogger("urllib3").setLevel(logging.ERROR) logging.getLogger("httpcore").setLevel(logging.ERROR) 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) from Synthesizers.base import Base_TTS_Synthesizer, Base_TTS_Task, get_wave_header_chunk from src.common_config_manager import app_config, __version__ frontend_version = __version__ def load_character_emotions(character_name, characters_and_emotions): emotion_options = ["default"] emotion_options = characters_and_emotions.get(character_name, ["default"]) return gr.Dropdown(emotion_options, value="default") synthesizer_name = app_config.synthesizer from importlib import import_module import tools.i18n.i18n as i18n_module # 设置国际化支持 i18n = i18n_module.I18nAuto(language=app_config.locale, locale_path=f"Synthesizers/{synthesizer_name}/configs/i18n/locale") # 动态导入合成器模块, 此处可写成 from Synthesizers.xxx import TTS_Synthesizer, TTS_Task synthesizer_module = import_module(f"Synthesizers.{synthesizer_name}") TTS_Synthesizer = synthesizer_module.TTS_Synthesizer TTS_Task = synthesizer_module.TTS_Task # 创建合成器实例 tts_synthesizer:Base_TTS_Synthesizer = TTS_Synthesizer(debug_mode=True) import soundfile as sf all_gradio_components = {} from time import time as ttime def get_audio(*data, streaming=False): data = dict(zip([key for key in all_gradio_components.keys()], data)) data["stream"] = streaming if data.get("text") in ["", None]: gr.Warning(i18n("文本不能为空")) return None, None try: task: Base_TTS_Task= tts_synthesizer.params_parser(data) t2 = ttime() if not streaming: if synthesizer_name == "remote": save_path = tts_synthesizer.generate(task, return_type="filepath") yield save_path else: gen = tts_synthesizer.generate(task, return_type="numpy") yield next(gen) else: gen = tts_synthesizer.generate(task, return_type="numpy") sample_rate = 32000 if task.sample_rate in [None, 0] else task.sample_rate yield get_wave_header_chunk(sample_rate=sample_rate) for chunk in gen: yield chunk except Exception as e: gr.Warning(f"Error: {e}") from functools import partial get_streaming_audio = partial(get_audio, streaming=True) def stopAudioPlay(): return global characters_and_emotions_dict characters_and_emotions_dict = {} def get_characters_and_emotions(): global characters_and_emotions_dict # 直接检查字典是否为空,如果不是,直接返回,避免重复获取 if characters_and_emotions_dict == {}: characters_and_emotions_dict = tts_synthesizer.get_characters() print(characters_and_emotions_dict) return characters_and_emotions_dict def change_character_list( character="", emotion="default" ): characters_and_emotions = {} try: characters_and_emotions = get_characters_and_emotions() character_names = [i for i in characters_and_emotions] if len(character_names) != 0: if character in character_names: character_name_value = character else: character_name_value = character_names[0] else: character_name_value = "" emotions = characters_and_emotions.get(character_name_value, ["default"]) emotion_value = emotion except: character_names = [] character_name_value = "" emotions = ["default"] emotion_value = "default" characters_and_emotions = {} return ( gr.Dropdown(character_names, value=character_name_value, label=i18n("选择角色")), gr.Dropdown(emotions, value=emotion_value, label=i18n("情感列表"), interactive=True), characters_and_emotions, ) def cut_sentence_multilang(text, max_length=30): if max_length == -1: return text, "" # 初始化计数器 word_count = 0 in_word = False for index, char in enumerate(text): if char.isspace(): # 如果当前字符是空格 in_word = False elif char.isascii() and not in_word: # 如果是ASCII字符(英文)并且不在单词内 word_count += 1 # 新的英文单词 in_word = True elif not char.isascii(): # 如果字符非英文 word_count += 1 # 每个非英文字符单独计为一个字 if word_count > max_length: return text[:index], text[index:] return text, "" default_text = i18n("我是一个粉刷匠,粉刷本领强。我要把那新房子,刷得更漂亮。刷了房顶又刷墙,刷子像飞一样。哎呀我的小鼻子,变呀变了样。") information = "" try: with open("Information.md", "r", encoding="utf-8") as f: information = f.read() except: pass try: max_text_length = app_config.max_text_length except: max_text_length = -1 from webuis.builders.gradio_builder import GradioTabBuilder ref_settings = tts_synthesizer.ui_config.get("ref_settings", []) basic_settings = tts_synthesizer.ui_config.get("basic_settings", []) advanced_settings = tts_synthesizer.ui_config.get("advanced_settings", []) url_setting = tts_synthesizer.ui_config.get("url_settings", []) tts_task_example : Base_TTS_Task = TTS_Task() params_config = tts_task_example.params_config has_character_param = True if "character" in params_config else False with gr.Blocks() as app: gr.Markdown(information) with gr.Row(): max_text_length_tip = "" if max_text_length == -1 else f"( "+i18n("最大允许长度")+ f" : {max_text_length} ) " text = gr.Textbox( value=default_text, label=i18n("输入文本")+max_text_length_tip, interactive=True, lines=8 ) text.blur(lambda x: gr.update(value=cut_sentence_multilang(x,max_length=max_text_length)[0]), [text], [text]) all_gradio_components["text"] = text with gr.Row(): with gr.Column(scale=2): with gr.Tabs(): with gr.Tab(label=i18n("角色选项"), visible=has_character_param): with gr.Group(): ( character, emotion, characters_and_emotions_, ) = change_character_list() characters_and_emotions = gr.State(characters_and_emotions_) scan_character_list = gr.Button( i18n("扫描人物列表"), variant="secondary" ) all_gradio_components["character"] = character all_gradio_components["emotion"] = emotion character.change( load_character_emotions, inputs=[character, characters_and_emotions], outputs=[emotion], ) scan_character_list.click( change_character_list, inputs=[character, emotion], outputs=[ character, emotion, characters_and_emotions, ], ) if len(ref_settings) > 0: with gr.Tab(label=i18n("参考设置")): ref_settings_tab = GradioTabBuilder( ref_settings, params_config ) ref_settings_components = ref_settings_tab.build() all_gradio_components.update(ref_settings_components) with gr.Column(scale=2): with gr.Tabs(): if len(basic_settings) > 0: with gr.Tab(label=i18n("基础选项")): basic_settings_tab = GradioTabBuilder( basic_settings, params_config ) basic_settings_components = basic_settings_tab.build() all_gradio_components.update(basic_settings_components) with gr.Column(scale=2): with gr.Tabs(): if len(advanced_settings) > 0: with gr.Tab(label=i18n("高级选项")): advanced_settings_tab = GradioTabBuilder( advanced_settings, params_config ) advanced_settings_components = advanced_settings_tab.build() all_gradio_components.update(advanced_settings_components) if len(url_setting) > 0: with gr.Tab(label=i18n("URL设置")): url_setting_tab = GradioTabBuilder(url_setting, params_config) url_setting_components = url_setting_tab.build() all_gradio_components.update(url_setting_components) with gr.Tabs(): with gr.Tab(label=i18n("请求完整音频")): with gr.Row(): get_full_audio_button = gr.Button(i18n("生成音频"), variant="primary") full_audio = gr.Audio( None, label=i18n("音频输出"), type="filepath", streaming=False ) get_full_audio_button.click(lambda: gr.update(interactive=False), None, [get_full_audio_button]).then( get_audio, inputs=[value for key, value in all_gradio_components.items()], outputs=[full_audio], ).then(lambda: gr.update(interactive=True), None, [get_full_audio_button]) with gr.Tab(label=i18n("流式音频")): with gr.Row(): get_streaming_audio_button = gr.Button(i18n("生成流式音频"), variant="primary") streaming_audio = gr.Audio( None, label=i18n("音频输出"), type="filepath", streaming=True, autoplay=True ) get_streaming_audio_button.click(lambda: gr.update(interactive=False), None, [get_streaming_audio_button]).then( get_streaming_audio, inputs=[value for key, value in all_gradio_components.items()], outputs=[streaming_audio], ).then(lambda: gr.update(interactive=True), None, [get_streaming_audio_button]) gr.HTML("
") gr.HTML( f"""

{i18n("这是GSVI。")}{i18n(",当前版本:")}{frontend_version} {i18n("项目开源地址:")} Github

{i18n("若有疑问或需要进一步了解,可参考文档:")}{i18n("点击查看详细文档")}

""" ) # 以下是事件绑定 # app.load( # change_character_list, # inputs=[character, emotion], # outputs=[ # character, # emotion, # characters_and_emotions, # ] # ) if app_config.also_enable_api == True: import uvicorn from pure_api import tts, character_list, set_tts_synthesizer from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from src.api_utils import get_gradio_frp, get_localhost_ipv4_address set_tts_synthesizer(tts_synthesizer) fastapi_app:FastAPI = app.app fastapi_app.add_api_route("/tts", tts, methods=["POST", "GET"]) fastapi_app.add_api_route("/character_list", character_list, methods=["GET"]) fastapi_app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) local_link = f"http://127.0.0.1:{app_config.server_port}" link = local_link if app_config.is_share: share_url = get_gradio_frp(app_config.server_name, app_config.server_port, app.share_token) print("This share link expires in 72 hours.") print(f"Share URL: {share_url}") link = share_url if app_config.inbrowser: import webbrowser webbrowser.open(link) ipv4_address = get_localhost_ipv4_address(app_config.server_name) ipv4_link = f"http://{ipv4_address}:{app_config.server_port}" print(f"INFO: Local Network URL: {ipv4_link}") fastapi_app = gr.mount_gradio_app(fastapi_app, app, path="/") uvicorn.run(fastapi_app, host=app_config.server_name, port=app_config.server_port) else: app.queue().launch(share=app_config.is_share, inbrowser=app_config.inbrowser, server_name=app_config.server_name, server_port=app_config.server_port)