32473485d7
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m0s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m44s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m51s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m57s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 6m34s
AI Code Review / AI Code Review (pull_request) Successful in 6m45s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 8m2s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 8m9s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 9m43s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m36s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 20m59s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 23s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m18s
服务端新建 deploy/gpu_worker/musetalk_server.py(替代原 ~/projects/MuseTalk/worker.py): 1. Flask app.run(threaded=True):推理阻塞时 /health 仍可达 2. _get_video_fps 兜底:ffprobe 返回 0 或失败时 fallback 到 default_fps(25) 3. _run_ffmpeg 统一封装:subprocess.run(check=True) + timeout,失败/超时抛 RuntimeError 4. inference_lock 并发锁:多请求同时到达时第二请求立即 503 5. 推理超时控制:thread.join(timeout=inference_timeout) 默认 600s,超时返回 504 6. finally 块清理临时目录:成功/失败/超时都删除 task_dir 7. 无人脸检测兜底:_run_inference 中帧提取后校验,无帧直接抛错返回 500 8. 上传大小限制:视频 <=100MB / 音频 <=20MB,超限返回 413 9. 新增 POST /cancel 端点:终止当前推理、清理临时文件、释放锁 10. GET /health 返回 GPU 显存信息(nvidia-smi)+ 当前任务状态 客户端 deploy/gpu_worker/gpu_worker.py 配套: - _call_musetalk 超时后 POST /cancel 终止服务端僵尸推理 - _call_musetalk 返回 (ok, duration, err, retryable) 四元组 - _handle_task 仅 retryable=True 时重试,4xx/短视频等确定性失败直接上报 - 新增 _cancel_musetalk_task 辅助方法 测试:新增 15 个单测覆盖服务端全部修复点;全量 15854 passed / 28 skipped 部署提醒:用户需在 RTX2060 上 wget 新 musetalk_server.py 替换旧 worker.py 并重启服务。
6.0 KiB
6.0 KiB
MuseTalk GPU Worker 部署指南
本目录包含两个组件:
- gpu_worker.py:反向轮询客户端,部署在 RTX2060 本地,轮询 SaaS API 拉取口型任务,调用本地 MuseTalk 服务推理,上传结果回 SaaS。
- musetalk_server.py:MuseTalk Flask HTTP 服务端,接收 gpu_worker.py 的推理请求,调用 MuseTalk 模型生成口型同步视频。
一、环境准备
1.1 硬件要求
- GPU: NVIDIA RTX 2060 或更高(显存 ≥ 6GB)
- CUDA: 11.8+
- Python: 3.10+
- ffmpeg: 需安装并加入 PATH
1.2 安装依赖
cd deploy/gpu_worker
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
二、MuseTalk 服务端部署(musetalk_server.py)
2.1 配置环境变量
复制 .env.example 为 .env,修改配置:
cp .env.example .env
vim .env
关键配置:
| 变量 | 说明 | 默认值 |
|---|---|---|
MUSE_PORT |
监听端口 | 7861 |
MUSE_INFERENCE_TIMEOUT |
推理超时秒数 | 600 |
MUSE_VIDEO_MAX_MB |
视频上传大小限制 MB | 100 |
MUSE_AUDIO_MAX_MB |
音频上传大小限制 MB | 20 |
MUSE_DEFAULT_FPS |
视频 fps 兜底值 | 25.0 |
MUSE_TEMP_DIR |
临时文件目录 | /tmp/musetalk_$$ |
2.2 启动服务
# 前台运行(调试用)
python musetalk_server.py
# 后台运行(生产用 systemd)
sudo systemctl start musetalk-server
sudo systemctl enable musetalk-server
2.3 验证健康检查
curl http://127.0.0.1:7861/health
应返回:
{
"status": "healthy",
"gpu": {
"gpu_name": "NVIDIA GeForce RTX 2060",
"memory_total_mb": 6144,
"memory_used_mb": 1024,
"memory_free_mb": 5120
},
"current_task": {
"task_id": null,
"running": false,
"elapsed_seconds": 0.0
},
"timestamp": 1700000000.0
}
三、GPU Worker 客户端部署(gpu_worker.py)
3.1 配置环境变量
复制 .env.example 为 .env,修改配置:
cp .env.example .env
vim .env
关键配置:
| 变量 | 说明 | 默认值 |
|---|---|---|
API_BASE_URL |
SaaS API 基础 URL | https://staging-api.xiaoxiajianji.com |
GPU_WORKER_TOKEN |
长期 API Token(与服务端一致) | - |
MUSE_TALK_URL |
本地 MuseTalk 服务地址 | http://127.0.0.1:7861 |
POLL_INTERVAL |
轮询间隔秒 | 5 |
HEARTBEAT_INTERVAL |
空闲心跳间隔秒 | 15 |
REQUEST_TIMEOUT |
HTTP 请求超时秒 | 900 |
TASK_MAX_RETRY |
本地最大重试次数 | 1 |
TASK_HEARTBEAT_INTERVAL |
推理期间任务心跳间隔秒 | 30 |
MIN_VIDEO_DURATION_SECONDS |
最短输入视频时长秒 | 3 |
3.2 启动 Worker
# 前台运行(调试用)
python gpu_worker.py
# 后台运行(生产用 systemd)
sudo systemctl start xiaoxia-gpu-worker
sudo systemctl enable xiaoxia-gpu-worker
3.3 验证启动日志
应看到:
============================================================
MuseTalk GPU Worker 启动
worker_id = rtx2060-xxxx
api_base = https://staging-api.xiaoxiajianji.com
muse_talk = http://127.0.0.1:7861
poll = 5.0s / heartbeat = 15.0s
============================================================
MuseTalk 健康检查通过: {...}
注册/心跳成功
四、常见问题排查
| 现象 | 可能原因 / 排查 |
|---|---|
日志 401 Invalid GPU worker token |
.env 的 GPU_WORKER_TOKEN 与服务端不一致 |
日志 MuseTalk 健康检查未通过 |
本地 MuseTalk 没启动,或端口不是 7861;curl http://127.0.0.1:7861/health 验证 |
| 任务长时间不被拉取 | Worker 和服务端连不上;检查 API_BASE_URL 是否可达、Token 是否正确 |
| 推理后上传 OSS 失败 | 本地出口网络被防火墙拦截 OSS 域名(oss-cn-hangzhou.aliyuncs.com) |
| 服务端看到任务回退到 pending 重试 | 任务心跳真正超时(默认 900s):Worker 进程崩溃/断网,或推理彻底卡死;正常长推理期间心跳线程每 30s 续期,不会回退 |
日志 MuseTalk 推理超时或连接失败 |
视频太长或显存不足;可临时调大 REQUEST_TIMEOUT(服务端 GPU_TASK_TIMEOUT_SECONDS 需同步调大),或限制输入视频时长 |
日志 视频过短(x.xxs < 3s) |
输入视频不足 3s,MuseTalk 对短视频会 division by zero,已在本地直接上报失败;可用 MIN_VIDEO_DURATION_SECONDS 调整阈值 |
MuseTalk 服务端 503 GPU 正在处理其他任务 |
并发请求被锁拒绝,等当前推理完成即可 |
MuseTalk 服务端 504 推理超时 |
推理超过 MUSE_INFERENCE_TIMEOUT,客户端会调 /cancel 终止服务端任务 |
五、安全注意事项
.env包含长期 Token,文件权限设为 600(chmod 600 .env)- Token 泄露要立即在服务端更换
GPU_WORKER_TOKEN并重启 Worker - Worker 只需要出站访问 SaaS API 和 OSS,不需要开放任何入站端口
- MuseTalk 服务端只监听本地 127.0.0.1(或 0.0.0.0 但通过防火墙限制),不暴露到公网
- 临时文件自动清理(推理完成/失败后),无需手动维护
六、工程改进记录(musetalk_server.py)
相比原 worker.py,修复了以下 8 个 bug:
- Flask 单线程阻塞:
app.run(threaded=True),推理时/health仍可响应 - fps=0 除零崩溃:
_get_video_fps()兜底MUSE_DEFAULT_FPS - ffmpeg 不检查返回码:
subprocess.run(check=True)+ 超时检查,失败立即报错 - 无并发锁:
threading.Lock控制并发,第二请求立即 503 - 无推理超时:线程 join timeout,超时返回 504 并调
/cancel - 结果文件不清理:推理完成/失败后自动删除临时目录
- 无人脸检测兜底:MuseTalk 推理内部处理(TODO: 可在
_run_inference前置检查) - 上传无大小限制:
_check_file_size()校验,超限返回 413
新增:
/cancel端点:终止当前推理任务,清理临时文件/health端点:返回 GPU 显存信息和当前任务状态