File size: 7,471 Bytes
24437ee 88ea7f6 24437ee 88ea7f6 24437ee 88ea7f6 24437ee 88ea7f6 24437ee 88ea7f6 24437ee 88ea7f6 24437ee 88ea7f6 24437ee 88ea7f6 24437ee |
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 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
"""
Genie TTS 依赖安装模块
负责处理Genie TTS包及其依赖的安装和管理
"""
import subprocess
import sys
import logging
logger = logging.getLogger(__name__)
def install_pyaudio_alternative():
"""尝试安装PyAudio的替代方案或创建mock模块"""
try:
# 首先尝试正常安装PyAudio
subprocess.check_call([
sys.executable, "-m", "pip", "install", "pyaudio"
], timeout=120)
logger.info("✓ PyAudio 安装成功")
return True
except Exception as e:
logger.warning(f"PyAudio 安装失败: {e}")
# 如果PyAudio安装失败,创建一个mock模块
try:
import os
import site
# 获取site-packages路径
site_packages = site.getsitepackages()[0]
pyaudio_mock_path = os.path.join(site_packages, "pyaudio.py")
# 创建mock pyaudio模块
mock_pyaudio_code = '''"""
Mock PyAudio module for environments without audio support
"""
class PyAudioError(Exception):
pass
class Stream:
def __init__(self, *args, **kwargs):
raise PyAudioError("音频流在此环境中不可用")
def read(self, *args, **kwargs):
raise PyAudioError("音频读取在此环境中不可用")
def write(self, *args, **kwargs):
raise PyAudioError("音频写入在此环境中不可用")
def start_stream(self):
pass
def stop_stream(self):
pass
def close(self):
pass
class PyAudio:
paInt16 = 8
paFloat32 = 1
def __init__(self):
logger.warning("使用Mock PyAudio - 音频功能不可用")
def open(self, *args, **kwargs):
return Stream()
def get_device_count(self):
return 0
def get_device_info_by_index(self, index):
return {"name": "Mock Device", "maxInputChannels": 0, "maxOutputChannels": 0}
def terminate(self):
pass
# 导出主要类和常量
__all__ = ['PyAudio', 'Stream', 'PyAudioError']
'''
with open(pyaudio_mock_path, 'w', encoding='utf-8') as f:
f.write(mock_pyaudio_code)
logger.info("✓ 创建 PyAudio mock 模块成功")
return True
except Exception as mock_error:
logger.error(f"创建 PyAudio mock 模块失败: {mock_error}")
return False
def install_genie_tts():
"""尝试安装genie-tts包,处理Hugging Face Spaces的限制"""
try:
import genie_tts
logger.info("genie-tts已安装")
return True, None
except ImportError:
logger.info("正在尝试安装genie-tts...")
try:
# 首先确保关键依赖已安装
critical_deps = [
"onnxruntime>=1.16.0", # 最关键:没有它TTS完全无法工作
"numpy>=1.21.0", # 基础依赖
"soundfile>=0.12.0", # 音频处理
"huggingface-hub>=0.17.0", # 模型下载
"scipy>=1.9.0", # 科学计算
"pyyaml>=6.0", # 配置文件解析
"rich>=12.0.0" # 终端输出美化
]
logger.info("正在安装关键依赖...")
for dep in critical_deps:
try:
subprocess.check_call([
sys.executable, "-m", "pip", "install", dep, "--upgrade"
], timeout=180)
logger.info(f"✓ 成功安装: {dep}")
except Exception as e:
logger.error(f"✗ 关键依赖安装失败: {dep} - {e}")
return False, f"关键依赖 {dep} 安装失败: {str(e)}"
# 处理PyAudio依赖
logger.info("正在处理PyAudio依赖...")
pyaudio_success = install_pyaudio_alternative()
if not pyaudio_success:
logger.warning("PyAudio处理失败,但将继续安装...")
# 尝试安装可选的日语处理依赖
try:
subprocess.check_call([
sys.executable, "-m", "pip", "install", "pyopenjtalk"
], timeout=120)
logger.info("✓ 成功安装 pyopenjtalk")
except Exception as e:
logger.warning(f"⚠ pyopenjtalk 安装失败: {e}")
# 尝试安装可选的音频重采样依赖
try:
subprocess.check_call([
sys.executable, "-m", "pip", "install", "soxr"
], timeout=120)
logger.info("✓ 成功安装 soxr")
except Exception as e:
logger.warning(f"⚠ soxr 安装失败: {e}")
# 最后安装genie-tts主包
logger.info("正在安装 genie-tts 主包...")
subprocess.check_call([
sys.executable, "-m", "pip", "install",
"genie-tts", "--upgrade"
], timeout=300)
# 验证安装
import genie_tts
logger.info("✅ genie-tts安装成功")
return True, "安装成功,但某些音频功能可能不可用(PyAudio限制)"
except subprocess.TimeoutExpired:
error_msg = "安装超时:Hugging Face Spaces 环境可能不支持某些依赖"
logger.error(error_msg)
return False, error_msg
except Exception as e:
error_msg = str(e)
# 如果仍然是PyAudio相关错误,提供更详细的解决建议
if "pyaudio" in error_msg.lower():
error_msg = (
"PyAudio依赖问题:即使创建了mock模块,genie-tts仍无法正常导入。"
"建议解决方案:\n"
"1. 在本地环境运行(安装了音频驱动)\n"
"2. 使用替代的TTS库(如 pyttsx3 或 espeak)\n"
"3. 联系Hugging Face支持团队关于音频依赖问题"
)
logger.error(error_msg)
return False, error_msg
else:
logger.error(f"安装genie-tts失败: {error_msg}")
return False, error_msg
def setup_genie_import():
"""设置Genie TTS的导入,返回模块和错误信息"""
install_success, install_error = install_genie_tts()
if install_success:
try:
import genie_tts as genie
logger.info("Genie TTS导入成功")
return genie, install_error # 返回警告信息(如果有)
except ImportError as e:
error_msg = f"导入失败: {str(e)}"
# 如果导入仍然失败,提供备用方案的建议
if "pyaudio" in error_msg.lower():
error_msg += (
"\n\n建议的备用方案:\n"
"1. 使用在线TTS服务(Google TTS, Azure Speech等)\n"
"2. 在本地环境部署Genie TTS\n"
"3. 使用其他兼容Hugging Face Spaces的TTS模型"
)
logger.error(error_msg)
return None, error_msg
else:
return None, install_error |