1. 背景与痛点
在 WSL2 (Windows Subsystem for Linux) 环境下开发 AI 项目时,我们经常会遇到一个棘手的网络问题:为了下载 HuggingFace 模型,我们通常会配置全局代理(如 Clash),但这会导致本地进程间的通信(127.0.0.1)也被代理拦截,从而引发 502 Bad Gateway 错误。
本文将分享如何将 IndexTTS 封装为 API 服务,并成功集成到 VideoLingo 中,同时彻底解决 WSL2 下的代理冲突问题。
2. 核心集成方案
我们的目标是让 VideoLingo 能够通过 HTTP 请求调用 IndexTTS 的语音合成功能。
2.1 IndexTTS API 服务端配置
在 /root/index-tts/ 目录下创建 api_server.py。
关键点:
- 使用 FastAPI 框架。
- 确保路径正确指向 IndexTTS 的根目录。
- 监听一个冷门端口(如
9999)以避开常用端口冲突。
import os
import sys
import torch
import uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
# 路径配置:确保能找到 IndexTTS 源码
INDEX_TTS_ROOT = "/root/index-tts"
if INDEX_TTS_ROOT not in sys.path:
sys.path.append(INDEX_TTS_ROOT)
from indextts.infer_v2 import IndexTTS2
app = FastAPI()
class TTSRequest(BaseModel):
text: str
spk_audio_path: str
output_path: str
emo_audio_path: Optional[str] = None
tts_model = None
def get_model():
global tts_model
if tts_model is None:
print(">>> [API] 正在加载模型 (首次调用需联网下载组件)...")
tts_model = IndexTTS2(
cfg_path=os.path.join(INDEX_TTS_ROOT, "checkpoints/config.yaml"),
model_dir=os.path.join(INDEX_TTS_ROOT, "checkpoints"),
use_fp16=torch.cuda.is_available(),
device="cuda" if torch.cuda.is_available() else "cpu"
)
print(">>> [API] 模型加载成功!")
return tts_model
@app.post("/tts")
async def generate_tts(request: TTSRequest):
print(f"\n>>> [API] 收到请求: {request.text[:20]}...")
try:
model = get_model()
os.makedirs(os.path.dirname(request.output_path), exist_ok=True)
# IndexTTS2.infer 是生成器,必须迭代才能触发保存
inference_gen = model.infer(
spk_audio_prompt=request.spk_audio_path,
text=request.text,
output_path=request.output_path,
emo_audio_prompt=request.emo_audio_path,
verbose=False
)
for _ in inference_gen: pass
print(f">>> [API] 合成成功: {request.output_path}")
return {"status": "success", "audio_path": request.output_path}
except Exception as e:
print(f">>> [API] 错误: {e}")
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
uvicorn.run(app, host="127.0.0.1", port=9999)
2.2 VideoLingo 调用端配置
修改 /root/VideoLingo/core/tts_backend/custom_tts.py。
关键点:
- 强制禁用代理:通过
proxies={"http": None, "https": None}确保请求直连本地 API,不经过 Clash。
import requests
import os
def custom_tts(text, save_path):
API_URL = "http://127.0.0.1:9999/tts"
# 默认音色路径
DEFAULT_SPK = "/root/index-tts/examples/voice_01.wav"
payload = {
"text": text,
"spk_audio_path": DEFAULT_SPK,
"output_path": os.path.abspath(save_path)
}
try:
print(f"[Client] 正在发送请求 (强制直连 API)...")
# 核心修复:强制跳过系统代理
response = requests.post(
API_URL,
json=payload,
timeout=600,
proxies={"http": None, "https": None}
)
if response.status_code == 200:
print(f"[Client] 成功生成配音!")
else:
raise Exception(f"API 错误: {response.text}")
except Exception as e:
print(f"[Client] 调用失败: {e}")
raise e
if __name__ == "__main__":
# 连通性测试
custom_tts("测试配音,正在加载模型并合成。", "test.wav")
3. 运行与跑通
第一步:启动 API 服务
为了让 API 既能连上本地,又能通过代理下载模型,启动时需指定 no_proxy:
cd /root/index-tts
export no_proxy=localhost,127.0.0.1 && uv run python api_server.py
第二步:运行连通性测试
在另一个终端运行:
cd /root/VideoLingo/core/tts_backend/
python3 custom_tts.py
第三步:连通性测试之端口占用清除
# 查看哪个进程在使用9999端口
sudo lsof -i :9999
# 或者使用 netstat
sudo netstat -tlnp | grep :9999
# 找到PID后,停止该进程
pkill -f "api_server.py"
第四步:修复500 Internal Server Error错误
主要是参考音频没给,改下请求端的默认音频即可
4. 经验总结
- 代理冲突:WSL2 下的
502 Bad Gateway通常是代理拦截了本地回环地址。在代码中显式设置proxies={...}是最稳妥的解决办法。 - 模型加载:IndexTTS 首次调用会下载
w2v-bert-2.0等组件,请确保服务端启动时代理配置正确(使用no_proxy排除本地地址)。 - 生成器机制:IndexTTS 的推理函数是生成器,调用时必须完整迭代才能完成文件保存。
5. 进阶操作:后台启动与音色切换
为了让集成方案更具实用性,以下是两个必备的进阶操作。
5.1 API 服务后台静默启动
在实际使用中,我们不希望 API 服务占用一个终端窗口。可以使用 nohup 命令让服务在后台持续运行,并将日志记录到文件中。
后台启动命令:
cd /root/index-tts
export no_proxy=localhost,127.0.0.1
nohup uv run python api_server.py > tts_api.log 2>&1 &
相关管理操作:
- 查看运行日志:
tail -f tts_api.log(实时查看合成进度和报错)。 - 查看服务进程:
ps -ef | grep api_server.py。 - 关闭后台服务:
fuser -k 9999/tcp(强制关闭占用 9999 端口的进程)。
5.2 快速切换配音音色
IndexTTS 的核心优势是音色克隆。要更换 VideoLingo 的配音音色,您无需修改 API 服务端,只需修改调用端 custom_tts.py 中的一个路径即可。
操作步骤:
- 将您喜欢的
.wav格式参考音频放入/root/index-tts/examples/目录下(例如my_voice.wav)。 - 修改
/root/VideoLingo/core/tts_backend/custom_tts.py中的DEFAULT_SPK变量:
def custom_tts(text, save_path):
# --- 修改这里即可更换音色 ---
DEFAULT_SPK = "/root/index-tts/examples/my_voice.wav"
# --------------------------
# ... 其余代码保持不变 ...
提示:IndexTTS 对参考音频的要求不高,通常 5-10 秒清晰的干声(无背景音乐)即可达到非常好的克隆效果。
希望这篇指南能帮助你在 WSL2 环境下顺利集成 IndexTTS!