fix(gpu): #1970 重写 MuseTalk 服务端 + 客户端超时取消,修复 8 项工程 bug #1992

Merged
xiaoxia merged 1 commits from fix/1970-musetalk-server-rewrite into develop 2026-09-19 20:05:14 +08:00
Owner

背景

GPU Worker 端到端链路已通,但 MuseTalk 推理环节存在多个工程 bug:Flask 单线程阻塞、fps=0 除零崩溃、ffmpeg 失败不检查、无并发锁导致 OOM、无推理超时、临时文件不清理、无人脸不报错、上传无大小限制。用户已在 RTX2060 定位根因。

修改

服务端(新建 deploy/gpu_worker/musetalk_server.py)

  1. Flask 单线程阻塞app.run(threaded=True) 让推理期间 /health 仍可达
  2. fps=0 除零_get_video_fps() 兜底到 default_fps=25
  3. ffmpeg 不检查返回码_run_ffmpeg() 封装 subprocess.run(check=True) + timeout,失败抛 RuntimeError
  4. 无并发锁threading.Lock() 非阻塞获取,第二请求立即 503
  5. 无推理超时thread.join(timeout=inference_timeout) 默认 600s,超时返回 504
  6. 结果文件不清理finally 块清理 task_dir
  7. 无人脸不报错 → 帧提取后校验,无帧抛 RuntimeError 返回 500
  8. 上传无大小限制 → 视频 ≤100MB / 音频 ≤20MB,超限返回 413
  9. 新增 POST /cancel → 终止当前推理、清理临时文件、释放锁
  10. /health 增加 GPU 显存信息 → nvidia-smi 获取 GPU 名称/总量/已用/可用

客户端(deploy/gpu_worker/gpu_worker.py 配套)

  • _call_musetalk 超时后 POST /cancel 终止服务端僵尸推理
  • 返回四元组 (ok, duration, err, retryable),仅瞬时错误(连接失败/超时/5xx)重试
  • TASK_MAX_RETRY 2→1,4xx/短视频等确定性失败直接上报

测试

  • 新增 15 个服务端单测(spec_from_file_location 加载独立脚本)
  • 全量 15854 passed / 28 skipped

部署提醒

  • 服务端随 develop 自动部署
  • 用户需在 RTX2060 上替换 musetalk_server.py 并重启(或 wget 新文件)
  • 旧 .env 若显式写了 REQUEST_TIMEOUT/TASK_MAX_RETRY 需改为 900/1

已知

Staging E2E 近期持续失败(登录 429 限流),属预存环境问题,与本次代码无关。

## 背景 GPU Worker 端到端链路已通,但 MuseTalk 推理环节存在多个工程 bug:Flask 单线程阻塞、fps=0 除零崩溃、ffmpeg 失败不检查、无并发锁导致 OOM、无推理超时、临时文件不清理、无人脸不报错、上传无大小限制。用户已在 RTX2060 定位根因。 ## 修改 ### 服务端(新建 deploy/gpu_worker/musetalk_server.py) 1. **Flask 单线程阻塞** → `app.run(threaded=True)` 让推理期间 /health 仍可达 2. **fps=0 除零** → `_get_video_fps()` 兜底到 `default_fps=25` 3. **ffmpeg 不检查返回码** → `_run_ffmpeg()` 封装 `subprocess.run(check=True)` + timeout,失败抛 RuntimeError 4. **无并发锁** → `threading.Lock()` 非阻塞获取,第二请求立即 503 5. **无推理超时** → `thread.join(timeout=inference_timeout)` 默认 600s,超时返回 504 6. **结果文件不清理** → `finally` 块清理 task_dir 7. **无人脸不报错** → 帧提取后校验,无帧抛 RuntimeError 返回 500 8. **上传无大小限制** → 视频 ≤100MB / 音频 ≤20MB,超限返回 413 9. **新增 POST /cancel** → 终止当前推理、清理临时文件、释放锁 10. **/health 增加 GPU 显存信息** → nvidia-smi 获取 GPU 名称/总量/已用/可用 ### 客户端(deploy/gpu_worker/gpu_worker.py 配套) - `_call_musetalk` 超时后 POST `/cancel` 终止服务端僵尸推理 - 返回四元组 `(ok, duration, err, retryable)`,仅瞬时错误(连接失败/超时/5xx)重试 - `TASK_MAX_RETRY` 2→1,4xx/短视频等确定性失败直接上报 ### 测试 - 新增 15 个服务端单测(spec_from_file_location 加载独立脚本) - 全量 15854 passed / 28 skipped ### 部署提醒 - 服务端随 develop 自动部署 - **用户需在 RTX2060 上替换 musetalk_server.py 并重启**(或 wget 新文件) - 旧 .env 若显式写了 REQUEST_TIMEOUT/TASK_MAX_RETRY 需改为 900/1 ## 已知 Staging E2E 近期持续失败(登录 429 限流),属预存环境问题,与本次代码无关。

🚀 预览环境已部署

项目 详情
PR号 #1992
预览链接 https://pr-1992.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1992 | | 预览链接 | [https://pr-1992.preview.xiaoxiajianji.com](https://pr-1992.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia added 1 commit 2026-09-19 19:39:52 +08:00
fix(gpu): #1970 重写 MuseTalk 服务端 + 客户端超时取消,修复 8 项工程 bug
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
32473485d7
服务端新建 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 并重启服务。
xiaoxia force-pushed fix/1970-musetalk-server-rewrite from 67a80c6895 to 32473485d7 2026-09-19 19:39:52 +08:00 Compare
xiaoxia merged commit 2e2d1cd73e into develop 2026-09-19 20:05:14 +08:00

🗑️ 预览环境已清理

PR #1992 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #1992 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.