feat(indextts2, webui): 完善 IndexTTS2 支持,新增参考音频选择与预览功能

修改内容包括:
- 修正缺失参考音频的错误提示文本
- 更新示例配置文件,新增参考音频来源配置项并将 IndexTTS2 设为默认TTS引擎
- 更新语音服务模块的注释与文档字符串
- 新增多语言适配文案,支持新UI的所有提示内容
- 重构 IndexTTS2 设置页面:支持从资源目录选择音频、上传本地音频、预览音频效果
- 调整TTS引擎选项的排序与默认选中项
This commit is contained in:
viccy 2026-06-05 23:52:31 +08:00
parent 0bd001ce33
commit 5b2487e879
6 changed files with 290 additions and 46 deletions

View File

@ -71,7 +71,7 @@ def _normalize_indextts2_reference_audio(params: VideoClipParams) -> None:
logger.info(f"IndexTTS2 使用配置中的参考音频: {configured_ref}") logger.info(f"IndexTTS2 使用配置中的参考音频: {configured_ref}")
return return
raise ValueError("IndexTTS2 参考音频不存在,请在音频设置中上传或填写有效的参考音频路径") raise ValueError("IndexTTS2 参考音频不存在,请在音频设置中上传或选择有效的参考音频")
def start_export_jianying_draft(task_id: str, params: VideoClipParams): def start_export_jianying_draft(task_id: str, params: VideoClipParams):

View File

@ -2236,7 +2236,7 @@ def indextts2_tts(text: str, voice_name: str, voice_file: str, speed: float = 1.
Args: Args:
text: 要转换的文本 text: 要转换的文本
voice_name: 参考音频路径格式indextts2:path/to/audio.wav voice_name: 参考音频文件格式indextts2:path/to/audio.wav
voice_file: 输出音频文件路径 voice_file: 输出音频文件路径
speed: 语音速度此引擎暂不支持速度调节 speed: 语音速度此引擎暂不支持速度调节
@ -2253,7 +2253,7 @@ def indextts2_tts(text: str, voice_name: str, voice_file: str, speed: float = 1.
num_beams = config.indextts2.get("num_beams", 3) num_beams = config.indextts2.get("num_beams", 3)
repetition_penalty = config.indextts2.get("repetition_penalty", 10.0) repetition_penalty = config.indextts2.get("repetition_penalty", 10.0)
# 解析参考音频路径 # 解析参考音频文件
reference_audio_path = parse_indextts2_voice(voice_name) reference_audio_path = parse_indextts2_voice(voice_name)
if not reference_audio_path or not os.path.exists(reference_audio_path): if not reference_audio_path or not os.path.exists(reference_audio_path):

View File

@ -120,7 +120,8 @@
# 默认 API 地址(本地部署) # 默认 API 地址(本地部署)
api_url = "http://127.0.0.1:8081/tts" api_url = "http://127.0.0.1:8081/tts"
# 默认参考音频路径(可选) # 默认参考音频(可选)
reference_audio_source = "resource"
# reference_audio = "/path/to/reference_audio.wav" # reference_audio = "/path/to/reference_audio.wav"
# 推理模式:普通推理 / 快速推理 # 推理模式:普通推理 / 快速推理
@ -151,8 +152,8 @@
silence_duration = 0.125 silence_duration = 0.125
[ui] [ui]
# TTS引擎选择 (edge_tts, azure_speech, soulvoice, tencent_tts, tts_qwen, doubaotts) # TTS引擎选择 (indextts2, edge_tts, qwen3_tts, tencent_tts, doubaotts, azure_speech)
tts_engine = "edge_tts" tts_engine = "indextts2"
# Edge TTS 配置 # Edge TTS 配置
edge_voice_name = "zh-CN-XiaoyiNeural-Female" edge_voice_name = "zh-CN-XiaoyiNeural-Female"

View File

@ -1,5 +1,6 @@
import streamlit as st import streamlit as st
import os import os
import shutil
from uuid import uuid4 from uuid import uuid4
from app.config import config from app.config import config
from app.services import voice from app.services import voice
@ -8,6 +9,35 @@ from app.utils import utils
from webui.utils.cache import get_songs_cache from webui.utils.cache import get_songs_cache
INDEXTTS2_REFERENCE_AUDIO_SOURCE_DIR = "/Users/viccy/Downloads/tts-mp3-clone/mp3"
INDEXTTS2_REFERENCE_AUDIO_COPY_SUBDIR = "indextts2_refs"
INDEXTTS2_REFERENCE_AUDIO_MAP = [
("yingshijieshuo-zh-male.mp3", "影视解说", "Film Narration"),
("maikeashe-zh-male.mp3", "麦克阿瑟", "Macintosh"),
("dong-yuhui-zh-male.mp3", "董宇辉", "Dong Yuhui"),
("fangzhenren-ad-fake-news-zh-male.mp3", "仿真人", "Realistic Human"),
("fengyin-jilupian-jieshuo-zh-male.mp3", "风吟纪录片解说", "Fengyin Documentary Narration"),
("guwo-dianying-jieshuo-zh-male.mp3", "顾我电影解说", "Guwo Film Narration"),
("jia-xiaojun-final-zh-male.mp3", "贾小军", "Jia Xiaojun"),
("junshi-zh-male.mp3", "军事解说", "Military Narration"),
("qi-tongwei-v2-zh-male.mp3", "祁同伟", "Qi Tongwei"),
("saima-niang-mambo-oye-zh-female.mp3", "赛马娘曼波欧耶版", "Uma Musume Mambo Oye Version"),
("shejian-shangde-zhongguo-zh-male.mp3", "舌尖上的中国", "A Bite of China"),
("xiaoming-jianmo-zh-male.mp3", "小明剑魔", "Xiaoming Sword Demon"),
("xin-youxi-jieshuo-zh-male.mp3", "新游戏解说", "New Game Narration"),
("xinzhong-zhicheng-zh-male.mp3", "心中之城", "City in the Heart"),
("alex-chikna-en-male.mp3", "亚历克斯", "Alex Chikna"),
("alle-en-unknown.mp3", "艾莉", "ALLE"),
("calm-normal-en-unknown.mp3", "沉稳男声", "Calm Normal"),
("donald-j-trump-noise-reduction-en-male.mp3", "唐纳德·特朗普", "Donald J. Trump"),
("elite-en-unknown.mp3", "精英男声", "ELITE"),
("horror-en-unknown.mp3", "惊悚男声", "Horror"),
("meiqu-kelong-en-unknown.mp3", "美式男声", "US Clone"),
("sarah-en-female.mp3", "莎拉", "Sarah"),
]
INDEXTTS2_REFERENCE_AUDIO_EXTENSIONS = (".mp3", ".wav", ".flac", ".m4a", ".aac", ".ogg")
def get_soulvoice_voices(): def get_soulvoice_voices():
"""获取 SoulVoice 语音列表""" """获取 SoulVoice 语音列表"""
# 检查是否配置了 SoulVoice API key # 检查是否配置了 SoulVoice API key
@ -22,12 +52,12 @@ def get_soulvoice_voices():
def get_tts_engine_options(tr=lambda key: key): def get_tts_engine_options(tr=lambda key: key):
"""获取TTS引擎选项""" """获取TTS引擎选项"""
return { return {
"indextts2": "IndexTTS2",
"edge_tts": "Edge TTS", "edge_tts": "Edge TTS",
"azure_speech": "Azure Speech Services",
"tencent_tts": tr("Tencent Cloud TTS"),
"qwen3_tts": tr("Tongyi Qwen3 TTS"), "qwen3_tts": tr("Tongyi Qwen3 TTS"),
"indextts2": tr("IndexTTS2 Voice Clone"), "tencent_tts": tr("Tencent Cloud TTS"),
"doubaotts": tr("Doubao TTS") "doubaotts": tr("Doubao TTS"),
"azure_speech": "Azure Speech Services"
} }
@ -59,9 +89,9 @@ def get_tts_engine_descriptions(tr=lambda key: key):
"registration": "https://dashscope.aliyuncs.com/" "registration": "https://dashscope.aliyuncs.com/"
}, },
"indextts2": { "indextts2": {
"title": tr("IndexTTS2 Voice Clone"), "title": "IndexTTS2",
"features": tr("IndexTTS2 features"), "features": tr("IndexTTS2 features"),
"use_case": tr("IndexTTS2 download link"), "use_case": tr("IndexTTS2 use case"),
"registration": None "registration": None
}, },
"doubaotts": { "doubaotts": {
@ -73,6 +103,143 @@ def get_tts_engine_descriptions(tr=lambda key: key):
} }
def infer_indextts2_reference_audio_language(filename):
"""根据文件名推断参考音频语言"""
lower_filename = filename.lower()
if "-zh-" in lower_filename:
return "zh"
if "-en-" in lower_filename:
return "en"
return "unknown"
def get_indextts2_reference_audio_options():
"""获取本地 IndexTTS2 参考音频选项"""
options = []
mapped_files = set()
for filename, zh_name, en_name in INDEXTTS2_REFERENCE_AUDIO_MAP:
audio_path = os.path.join(INDEXTTS2_REFERENCE_AUDIO_SOURCE_DIR, filename)
if os.path.isfile(audio_path):
options.append({
"filename": filename,
"path": audio_path,
"zh": zh_name,
"en": en_name,
"language": infer_indextts2_reference_audio_language(filename),
})
mapped_files.add(filename)
if os.path.isdir(INDEXTTS2_REFERENCE_AUDIO_SOURCE_DIR):
for filename in sorted(os.listdir(INDEXTTS2_REFERENCE_AUDIO_SOURCE_DIR)):
if filename in mapped_files:
continue
if not filename.lower().endswith(INDEXTTS2_REFERENCE_AUDIO_EXTENSIONS):
continue
audio_path = os.path.join(INDEXTTS2_REFERENCE_AUDIO_SOURCE_DIR, filename)
if not os.path.isfile(audio_path):
continue
fallback_name = os.path.splitext(filename)[0]
options.append({
"filename": filename,
"path": audio_path,
"zh": fallback_name,
"en": fallback_name,
"language": infer_indextts2_reference_audio_language(filename),
})
return options
def format_indextts2_reference_audio_option(option):
"""格式化 IndexTTS2 参考音频下拉显示名"""
zh_name = option.get("zh", "")
en_name = option.get("en", "")
language = option.get("language", "unknown")
ui_language = str(st.session_state.get("ui_language", "zh-CN")).lower()
if ui_language.startswith("en"):
display_name = en_name or zh_name or option.get("filename", "")
language_labels = {
"zh": "Chinese",
"en": "English",
}
else:
display_name = zh_name or en_name or option.get("filename", "")
language_labels = {
"zh": "中文",
"en": "英文",
}
language_label = language_labels.get(language)
if not language_label:
return display_name
return f"{display_name} ({language_label})"
def get_indextts2_reference_audio_index(options, saved_reference_audio):
"""根据已保存的参考音频文件匹配下拉选项索引"""
if not options:
return 0
saved_filename = os.path.basename(saved_reference_audio or "")
for index, option in enumerate(options):
if option["filename"] == saved_filename:
return index
return 0
def copy_indextts2_reference_audio(source_path):
"""复制一份参考音频到项目存储目录,并返回复制后的路径"""
if not source_path or not os.path.isfile(source_path):
return ""
target_dir = utils.storage_dir(INDEXTTS2_REFERENCE_AUDIO_COPY_SUBDIR, create=True)
target_path = os.path.join(target_dir, os.path.basename(source_path))
if os.path.abspath(source_path) == os.path.abspath(target_path):
return target_path
should_copy = True
if os.path.exists(target_path):
should_copy = os.path.getsize(source_path) != os.path.getsize(target_path)
if should_copy:
shutil.copy2(source_path, target_path)
return target_path
def get_audio_mime_type(audio_path):
"""根据音频文件扩展名返回 MIME 类型"""
extension = os.path.splitext(audio_path or "")[1].lower()
if extension == ".wav":
return "audio/wav"
if extension == ".ogg":
return "audio/ogg"
if extension == ".m4a":
return "audio/mp4"
if extension == ".aac":
return "audio/aac"
return "audio/mp3"
def render_reference_audio_preview_button(reference_audio, key, tr):
"""渲染参考音频试听按钮"""
can_preview = bool(reference_audio and os.path.isfile(reference_audio))
if st.button(
" ",
key=key,
icon=":material/play_arrow:",
help=tr("Preview Reference Audio Help"),
disabled=not can_preview,
use_container_width=True,
):
st.session_state["indextts2_reference_audio_preview_path"] = reference_audio
def is_valid_azure_voice_name(voice_name: str) -> bool: def is_valid_azure_voice_name(voice_name: str) -> bool:
"""检查是否为有效的Azure音色名称格式""" """检查是否为有效的Azure音色名称格式"""
if not voice_name or not isinstance(voice_name, str): if not voice_name or not isinstance(voice_name, str):
@ -109,11 +276,11 @@ def render_tts_settings(tr):
engine_descriptions = get_tts_engine_descriptions(tr) engine_descriptions = get_tts_engine_descriptions(tr)
# 获取保存的TTS引擎设置 # 获取保存的TTS引擎设置
saved_tts_engine = config.ui.get("tts_engine", "edge_tts") saved_tts_engine = config.ui.get("tts_engine", "indextts2")
# 确保保存的引擎在可用选项中 # 确保保存的引擎在可用选项中
if saved_tts_engine not in engine_options: if saved_tts_engine not in engine_options:
saved_tts_engine = "edge_tts" saved_tts_engine = "indextts2"
# TTS引擎选择下拉框 # TTS引擎选择下拉框
selected_engine = st.selectbox( selected_engine = st.selectbox(
@ -566,8 +733,6 @@ def render_qwen3_tts_settings(tr):
def render_indextts2_tts_settings(tr): def render_indextts2_tts_settings(tr):
"""渲染 IndexTTS2 TTS 设置""" """渲染 IndexTTS2 TTS 设置"""
import os
# API 地址配置 # API 地址配置
api_url = st.text_input( api_url = st.text_input(
tr("API URL"), tr("API URL"),
@ -575,29 +740,90 @@ def render_indextts2_tts_settings(tr):
help=tr("IndexTTS2 API URL Help") help=tr("IndexTTS2 API URL Help")
) )
# 参考音频文件路径 saved_reference_audio = config.indextts2.get("reference_audio", "")
reference_audio = st.text_input( reference_audio_source_options = {
tr("Reference Audio Path"), tr("Select from Resource Directory"): "resource",
value=config.indextts2.get("reference_audio", ""), tr("Upload Reference Audio"): "upload",
help=tr("Reference Audio Path Help") }
reference_audio_source_labels = list(reference_audio_source_options.keys())
saved_reference_audio_source = config.indextts2.get("reference_audio_source", "resource")
if saved_reference_audio_source not in reference_audio_source_options.values():
saved_reference_audio_source = "resource"
default_reference_audio_source_label = next(
label
for label, source_value in reference_audio_source_options.items()
if source_value == saved_reference_audio_source
) )
# 文件上传功能 st.markdown(f"**{tr('Reference Audio Path')}**")
uploaded_file = st.file_uploader( reference_audio_source_label = st.pills(
tr("Upload Reference Audio File"), tr("Reference Audio Source"),
type=["wav", "mp3"], options=reference_audio_source_labels,
help=tr("Upload Reference Audio Help") selection_mode="single",
default=default_reference_audio_source_label,
key="indextts2_reference_audio_source_selection",
help=tr("Reference Audio Source Help"),
label_visibility="collapsed",
width="stretch",
) )
if not reference_audio_source_label:
reference_audio_source_label = default_reference_audio_source_label
reference_audio_source = reference_audio_source_options[reference_audio_source_label]
if uploaded_file is not None: reference_audio = saved_reference_audio
# 保存上传的文件 reference_audio_options = get_indextts2_reference_audio_options()
import tempfile if reference_audio_source == "resource" and reference_audio_options:
temp_dir = tempfile.gettempdir() selected_audio_index = get_indextts2_reference_audio_index(reference_audio_options, saved_reference_audio)
audio_path = os.path.join(temp_dir, f"indextts2_ref_{uploaded_file.name}") select_col, preview_col = st.columns([5, 1])
with open(audio_path, "wb") as f: with select_col:
f.write(uploaded_file.getbuffer()) selected_audio_option = reference_audio_options[st.selectbox(
reference_audio = audio_path tr("Reference Audio Path"),
st.success(tr("Audio uploaded").format(path=audio_path)) options=range(len(reference_audio_options)),
index=selected_audio_index,
format_func=lambda x: format_indextts2_reference_audio_option(reference_audio_options[x]),
help=tr("Reference Audio Path Help"),
label_visibility="collapsed"
)]
reference_audio = copy_indextts2_reference_audio(selected_audio_option["path"])
with preview_col:
render_reference_audio_preview_button(
reference_audio,
"indextts2_resource_reference_audio_preview",
tr,
)
elif reference_audio_source == "resource":
st.warning(tr("No Reference Audio Resources Found"))
if reference_audio_source == "upload":
if saved_reference_audio_source != "upload":
reference_audio = ""
upload_col, preview_col = st.columns([5, 1])
with upload_col:
uploaded_file = st.file_uploader(
tr("Upload Reference Audio File"),
type=["wav", "mp3"],
help=tr("Upload Reference Audio Help"),
label_visibility="collapsed"
)
if uploaded_file is not None:
target_dir = utils.storage_dir(INDEXTTS2_REFERENCE_AUDIO_COPY_SUBDIR, create=True)
audio_path = os.path.join(target_dir, f"uploaded_{uploaded_file.name}")
with open(audio_path, "wb") as f:
f.write(uploaded_file.getbuffer())
reference_audio = audio_path
st.success(tr("Audio uploaded").format(path=audio_path))
with preview_col:
render_reference_audio_preview_button(
reference_audio,
"indextts2_upload_reference_audio_preview",
tr,
)
preview_audio_path = st.session_state.get("indextts2_reference_audio_preview_path", "")
if preview_audio_path == reference_audio and os.path.isfile(preview_audio_path):
with open(preview_audio_path, "rb") as audio_file:
st.audio(audio_file.read(), format=get_audio_mime_type(preview_audio_path))
# 推理模式 # 推理模式
infer_mode_options = [ infer_mode_options = [
@ -676,6 +902,7 @@ def render_indextts2_tts_settings(tr):
# 保存配置 # 保存配置
config.indextts2["api_url"] = api_url config.indextts2["api_url"] = api_url
config.indextts2["reference_audio_source"] = reference_audio_source
config.indextts2["reference_audio"] = reference_audio config.indextts2["reference_audio"] = reference_audio
config.indextts2["infer_mode"] = infer_mode config.indextts2["infer_mode"] = infer_mode
config.indextts2["temperature"] = temperature config.indextts2["temperature"] = temperature
@ -1175,5 +1402,5 @@ def get_audio_params():
'bgm_type': st.session_state.get('bgm_type', 'random'), 'bgm_type': st.session_state.get('bgm_type', 'random'),
'bgm_file': st.session_state.get('bgm_file', ''), 'bgm_file': st.session_state.get('bgm_file', ''),
'bgm_volume': st.session_state.get('bgm_volume', AudioVolumeDefaults.BGM_VOLUME), 'bgm_volume': st.session_state.get('bgm_volume', AudioVolumeDefaults.BGM_VOLUME),
'tts_engine': st.session_state.get('tts_engine', "edge_tts"), 'tts_engine': st.session_state.get('tts_engine', "indextts2"),
} }

View File

@ -235,7 +235,8 @@
"Tencent Cloud TTS use case": "Personal and enterprise users who need stable Chinese speech synthesis", "Tencent Cloud TTS use case": "Personal and enterprise users who need stable Chinese speech synthesis",
"Tongyi Qwen3 TTS features": "Alibaba Cloud Tongyi Qwen speech synthesis with high-quality voices and multiple voice options.", "Tongyi Qwen3 TTS features": "Alibaba Cloud Tongyi Qwen speech synthesis with high-quality voices and multiple voice options.",
"High-quality Chinese speech synthesis use case": "Users who need high-quality Chinese speech synthesis", "High-quality Chinese speech synthesis use case": "Users who need high-quality Chinese speech synthesis",
"IndexTTS2 features": "Zero-shot voice cloning. Upload a reference audio file to synthesize speech with a matching voice. Requires local or private deployment.", "IndexTTS2 features": "A locally or privately deployed voice-cloning engine. Choose a resource audio file or upload a reference audio file, then synthesize narration in that voice.",
"IndexTTS2 use case": "Best for fixed narrator voices, character dubbing, or generating multiple videos with the same voice. Start the IndexTTS2 API service before use. Deployment package: https://pan.quark.cn/s/0767c9bcefd5",
"IndexTTS2 download link": "Download link: https://pan.quark.cn/s/0767c9bcefd5", "IndexTTS2 download link": "Download link: https://pan.quark.cn/s/0767c9bcefd5",
"Doubao TTS features": "Volcengine Doubao speech synthesis with multiple voices and emotions, plus fast access in mainland China.", "Doubao TTS features": "Volcengine Doubao speech synthesis with multiple voices and emotions, plus fast access in mainland China.",
"Select TTS Engine": "Select TTS Engine", "Select TTS Engine": "Select TTS Engine",
@ -387,9 +388,16 @@
"Select Qwen3 TTS Voice": "Select a Qwen3 TTS voice", "Select Qwen3 TTS Voice": "Select a Qwen3 TTS voice",
"API URL": "API URL", "API URL": "API URL",
"IndexTTS2 API URL Help": "IndexTTS2 API service URL", "IndexTTS2 API URL Help": "IndexTTS2 API service URL",
"Reference Audio Path": "Reference Audio Path", "Reference Audio Source": "Reference Audio Source",
"Reference Audio Path Help": "Reference audio file path for voice cloning (WAV format, 3-10 seconds recommended)", "Reference Audio Source Help": "Choose a reference audio from the resource directory or upload a new one.",
"Upload Reference Audio File": "Or Upload Reference Audio File", "Select from Resource Directory": "Select from Resource Directory",
"Upload Reference Audio": "Upload Reference Audio",
"Reference Audio Path": "Reference Audio",
"Reference Audio Path Help": "Choose the reference audio for voice cloning (WAV/MP3, 3-10 seconds recommended)",
"No Reference Audio Resources Found": "No reference audio resources found. Please upload a reference audio file.",
"Preview Reference Audio": "Preview",
"Preview Reference Audio Help": "Play the selected reference audio.",
"Upload Reference Audio File": "Upload Reference Audio File",
"Upload Reference Audio Help": "Upload a clear audio clip for voice cloning", "Upload Reference Audio Help": "Upload a clear audio clip for voice cloning",
"Audio uploaded": "✅ Audio uploaded: {path}", "Audio uploaded": "✅ Audio uploaded: {path}",
"Inference Mode": "Inference Mode", "Inference Mode": "Inference Mode",

View File

@ -216,7 +216,8 @@
"Tencent Cloud TTS use case": "个人和企业用户,需要稳定的中文语音合成", "Tencent Cloud TTS use case": "个人和企业用户,需要稳定的中文语音合成",
"Tongyi Qwen3 TTS features": "阿里云通义千问语音合成,音质优秀,支持多种音色", "Tongyi Qwen3 TTS features": "阿里云通义千问语音合成,音质优秀,支持多种音色",
"High-quality Chinese speech synthesis use case": "需要高质量中文语音合成的用户", "High-quality Chinese speech synthesis use case": "需要高质量中文语音合成的用户",
"IndexTTS2 features": "零样本语音克隆,上传参考音频即可合成相同音色的语音,需要本地或私有部署", "IndexTTS2 features": "本地/私有部署的语音克隆引擎。选择资源目录音频或上传参考音频后,可按该音色合成旁白。",
"IndexTTS2 use case": "适合需要固定旁白音色、角色配音或批量生成同一音色视频的场景。使用前请先启动 IndexTTS2 API 服务部署包下载https://pan.quark.cn/s/0767c9bcefd5",
"IndexTTS2 download link": "下载地址https://pan.quark.cn/s/0767c9bcefd5", "IndexTTS2 download link": "下载地址https://pan.quark.cn/s/0767c9bcefd5",
"Doubao TTS features": "火山引擎豆包语音合成,支持多种音色和情感,国内访问速度快", "Doubao TTS features": "火山引擎豆包语音合成,支持多种音色和情感,国内访问速度快",
"Select TTS Engine": "选择 TTS 引擎", "Select TTS Engine": "选择 TTS 引擎",
@ -369,9 +370,16 @@
"Select Qwen3 TTS Voice": "选择 Qwen3 TTS 音色", "Select Qwen3 TTS Voice": "选择 Qwen3 TTS 音色",
"API URL": "API 地址", "API URL": "API 地址",
"IndexTTS2 API URL Help": "IndexTTS2 API 服务地址", "IndexTTS2 API URL Help": "IndexTTS2 API 服务地址",
"Reference Audio Path": "参考音频路径", "Reference Audio Source": "参考音频来源",
"Reference Audio Path Help": "用于语音克隆的参考音频文件路径WAV 格式,建议 3-10 秒)", "Reference Audio Source Help": "选择从资源目录选择参考音频,或上传新的参考音频",
"Upload Reference Audio File": "或上传参考音频文件", "Select from Resource Directory": "从资源目录选择",
"Upload Reference Audio": "上传参考音频",
"Reference Audio Path": "参考音频",
"Reference Audio Path Help": "选择用于语音克隆的参考音频WAV/MP3 格式,建议 3-10 秒)",
"No Reference Audio Resources Found": "未找到资源目录中的参考音频,请上传参考音频文件",
"Preview Reference Audio": "试听",
"Preview Reference Audio Help": "播放当前参考音频",
"Upload Reference Audio File": "上传参考音频文件",
"Upload Reference Audio Help": "上传一段清晰的音频用于语音克隆", "Upload Reference Audio Help": "上传一段清晰的音频用于语音克隆",
"Audio uploaded": "✅ 音频已上传: {path}", "Audio uploaded": "✅ 音频已上传: {path}",
"Inference Mode": "推理模式", "Inference Mode": "推理模式",