Spaces:
Runtime error
Runtime error
File size: 6,509 Bytes
2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 1e245b2 37c0b74 1e245b2 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 2c31869 37c0b74 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
import json
import logging
import os
import sys
import time
import argparse
import requests
from urllib.parse import urlparse
import warnings
# --- 抑制警告信息 ---
warnings.filterwarnings("ignore", category=FutureWarning)
warnings.filterwarnings("ignore", category=UserWarning)
# --- 设置系统路径 ---
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)
sys.path.append(os.path.join(current_dir, "indextts"))
# --- 导入本地模块 ---
from indextts.infer_v2 import IndexTTS2
from tools.download_files import download_model_from_huggingface
def download_file(url, save_dir="temp_audio"):
"""
从 URL 下载文件,或者如果路径是本地文件则直接返回路径。
"""
os.makedirs(save_dir, exist_ok=True)
try:
result = urlparse(url)
is_url = all([result.scheme, result.netloc])
except ValueError:
is_url = False
if not is_url:
if os.path.exists(url):
print(f"使用本地文件: {url}")
return url
else:
raise FileNotFoundError(f"本地文件未找到: {url}")
filename = os.path.basename(result.path)
if not filename:
filename = f"audio_{int(time.time())}.wav"
save_path = os.path.join(save_dir, filename)
print(f"正在从 {url} 下载音频到 {save_path}...")
try:
response = requests.get(url, stream=True, timeout=30)
response.raise_for_status()
with open(save_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
print("下载完成。")
return save_path
except requests.exceptions.RequestException as e:
print(f"下载文件时出错: {e}")
raise
def main():
"""
运行命令行文本转语音应用的主函数。
"""
parser = argparse.ArgumentParser(
description="IndexTTS: 命令行文本转语音应用",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument("--prompt", type=str, required=True, help="需要合成的文本。")
parser.add_argument("--input_audio", type=str, required=True, help="音色参考音频的 URL 或本地路径 (.wav)。")
parser.add_argument("--setting", type=int, choices=[1, 2, 3, 4], required=True,
help="情感控制方法:\n"
"1: 与音色参考音频相同。\n"
"2: 使用单独的情感参考音频。\n"
"3: 使用情感向量。\n"
"4: 使用文本描述来控制情感。")
parser.add_argument("--emo_audio", type=str, help="情感参考音频的 URL 或本地路径 (setting 2 必需)。")
parser.add_argument("--emo_weight", type=float, default=0.8, help="情感权重 (setting 2, 默认: 0.8)。")
parser.add_argument("--emo_vectors", type=float, nargs=8,
metavar=('喜', '怒', '哀', '惧', '厌恶', '低落', '惊喜', '平静'),
help="八个情感向量值,用空格分隔 (setting 3 必需)。")
parser.add_argument("--emo_text", type=str, help="情感描述文本,例如 '高兴', '伤心' (setting 4 必需)。")
parser.add_argument("--output_path", type=str, default=None, help="保存输出音频的路径。如果未提供,将使用默认名称。")
parser.add_argument("--model_dir", type=str, default="checkpoints", help="模型检查点目录。")
parser.add_argument("--is_fp16", action="store_true", default=False, help="启用 fp16 推理。")
parser.add_argument("--verbose", action="store_true", default=False, help="启用详细日志记录。")
args = parser.parse_args()
print("正在检查模型文件...")
download_model_from_huggingface(
os.path.join(current_dir, "checkpoints"),
os.path.join(current_dir, "checkpoints", "hf_cache")
)
print("正在加载 IndexTTS 模型...")
tts = IndexTTS2(
model_dir=args.model_dir,
cfg_path=os.path.join(args.model_dir, "config.yaml"),
is_fp16=args.is_fp16,
use_cuda_kernel=False
)
print("模型加载成功。")
# --- 主要修改 1 ---
# 确保名为 "output" 的文件夹存在
os.makedirs("output", exist_ok=True)
# --- 主要修改 2 ---
# 如果用户没有通过 --output_path 指定路径,则默认使用 'output/output.wav'
output_path = args.output_path or os.path.join("output", "output.wav")
prompt_audio_path = download_file(args.input_audio)
emo_audio_prompt = None
emo_alpha = 1.0
emo_vector = None
use_emo_text = False
emo_text_val = ""
emo_control_method = args.setting - 1
if emo_control_method == 0:
print("使用音色参考音频中的情感。")
pass
elif emo_control_method == 1:
print("使用独立的情感参考音频。")
if not args.emo_audio:
parser.error("--emo_audio 参数在 setting 2 中是必需的。")
emo_audio_prompt = download_file(args.emo_audio)
emo_alpha = args.emo_weight
print(f"情感参考: {emo_audio_prompt}, 权重: {emo_alpha}")
elif emo_control_method == 2:
print("使用情感向量进行控制。")
if not args.emo_vectors:
parser.error("--emo_vectors 参数在 setting 3 中是必需的。")
vec_sum = sum(args.emo_vectors)
if vec_sum > 1.5:
raise ValueError(f"情感向量的总和不能超过1.5。当前总和: {vec_sum}")
emo_vector = args.emo_vectors
print(f"情感向量: {emo_vector}")
elif emo_control_method == 3:
print("使用文本描述来控制情感。")
if not args.emo_text:
parser.error("--emo_text 参数在 setting 4 中是必需的。")
use_emo_text = True
emo_text_val = args.emo_text
print(f"情感文本: '{emo_text_val}'")
print("\n开始 TTS 推理...")
tts.infer(
spk_audio_prompt=prompt_audio_path,
text=args.prompt,
output_path=output_path,
emo_audio_prompt=emo_audio_prompt,
emo_alpha=emo_alpha,
emo_vector=emo_vector,
use_emo_text=use_emo_text,
emo_text=emo_text_val,
verbose=args.verbose,
)
print(f"\n✨ 推理完成!音频已保存至: {output_path}")
if __name__ == "__main__":
main()
|