feat(gpu): #1978 AI数字人口型同步接入MuseTalk GPU Worker(业务侧集成) #1991

Merged
xiaoxia merged 1 commits from feat/gpu-lipsync-integration into develop 2026-09-19 22:43:58 +08:00
Owner

背景

PR #1979 已合入 GPU Worker 基础设施层(4个接口+Worker脚本),PR #1990 已做超时/心跳/重试收敛。本 PR 把 GpuLipsyncService 真正接到 AI 数字人 lipsync 业务主流程里,对前端/用户透明。

逻辑

在 LipsyncService._submit_audio_direct 签名提交 MediaKit 之前判断:

if USE_GPU_LIPSYNC and has_available_worker():
    try GPU(create_task → wait_for_result):
        done → job.status=completed, output_video_url=签名后的结果URL,直接返回
        timeout/failed/exception → 继续走 MediaKit(兜底,对用户透明)
else:
    走现有 MediaKit 云端 lipsync
  • 开关控制:USE_GPU_LIPSYNC env,默认 false(production默认false,待staging稳定后再开);staging默认true方便联调
  • Worker可用性检测:gpu_workers.last_heartbeat_at 在 GPU_WORKER_STALE_SECONDS(默认300s)内视为在线
  • 超时:GPU_LIPSYNC_WAIT_TIMEOUT(默认1200s),超过自动回退MediaKit
  • 轮询间隔:GPU_LIPSYNC_POLL_INTERVAL(默认5s)
  • 失败兜底:Worker上报failed / 重试耗尽 / 任何异常,都catch后回退MediaKit
  • 前端无感知:不改接口字段,job.status正常走completed/submitted/failed流转

GpuLipsyncService新增

  • has_available_worker():5分钟内有心跳的Worker存在
  • wait_for_result(task_id, timeout, poll_interval):同步轮询DB等终态,期间顺手回收超时任务;超时返回None

配置

项 默认 说明
USE_GPU_LIPSYNC false 业务侧GPU开关
GPU_LIPSYNC_POLL_INTERVAL 5.0 轮询间隔秒
GPU_LIPSYNC_WAIT_TIMEOUT 1200 等待总超时秒
GPU_WORKER_STALE_SECONDS 300 Worker心跳新鲜度窗口

staging默认开USE_GPU_LIPSYNC=true;production默认false(等staging跑稳手动开)。

测试

  • tests/unit/test_lipsync_gpu_integration.py 新增9个用例:
    • 开关关不调用GPU
    • 无Worker回退MediaKit
    • GPU成功→job直接completed,不调MediaKit
    • GPU超时回退
    • GPU终态failed回退
    • GPU异常回退
    • has_available_worker 三种场景(无worker/fresh/stale)
  • 全量GPU相关 30 个测试全绿(含前两个PR的11+10)

联调说明

  1. PR合入后staging watchtower自动部署(USE_GPU_LIPSYNC=true已生效)
  2. RTX2060上按deploy/gpu_worker/README.md部署Worker脚本,.env配staging API+Token
  3. 前端正常走数字人创建流程即可——后端在submit阶段会自动检测Worker在线并走MuseTalk本地推理
  4. Worker离线/失败时自动回退MediaKit云端,用户无感知
  5. staging验证稳定后,把production的USE_GPU_LIPSYNC改成true即可灰度生产
## 背景 PR #1979 已合入 GPU Worker 基础设施层(4个接口+Worker脚本),PR #1990 已做超时/心跳/重试收敛。本 PR 把 GpuLipsyncService 真正接到 AI 数字人 **lipsync 业务主流程**里,对前端/用户透明。 ## 逻辑 在 `LipsyncService._submit_audio_direct` 签名提交 MediaKit **之前**判断: ``` if USE_GPU_LIPSYNC and has_available_worker(): try GPU(create_task → wait_for_result): done → job.status=completed, output_video_url=签名后的结果URL,直接返回 timeout/failed/exception → 继续走 MediaKit(兜底,对用户透明) else: 走现有 MediaKit 云端 lipsync ``` - **开关控制**:`USE_GPU_LIPSYNC` env,默认 `false`(production默认false,待staging稳定后再开);staging默认true方便联调 - **Worker可用性检测**:`gpu_workers.last_heartbeat_at` 在 `GPU_WORKER_STALE_SECONDS`(默认300s)内视为在线 - **超时**:`GPU_LIPSYNC_WAIT_TIMEOUT`(默认1200s),超过自动回退MediaKit - **轮询间隔**:`GPU_LIPSYNC_POLL_INTERVAL`(默认5s) - **失败兜底**:Worker上报failed / 重试耗尽 / 任何异常,都catch后回退MediaKit - **前端无感知**:不改接口字段,job.status正常走completed/submitted/failed流转 ## GpuLipsyncService新增 - `has_available_worker()`:5分钟内有心跳的Worker存在 - `wait_for_result(task_id, timeout, poll_interval)`:同步轮询DB等终态,期间顺手回收超时任务;超时返回None ## 配置 | 项 | 默认 | 说明 | |---|---|---| | USE_GPU_LIPSYNC | false | 业务侧GPU开关 | | GPU_LIPSYNC_POLL_INTERVAL | 5.0 | 轮询间隔秒 | | GPU_LIPSYNC_WAIT_TIMEOUT | 1200 | 等待总超时秒 | | GPU_WORKER_STALE_SECONDS | 300 | Worker心跳新鲜度窗口 | staging默认开USE_GPU_LIPSYNC=true;production默认false(等staging跑稳手动开)。 ## 测试 - tests/unit/test_lipsync_gpu_integration.py 新增9个用例: - 开关关不调用GPU - 无Worker回退MediaKit - GPU成功→job直接completed,不调MediaKit - GPU超时回退 - GPU终态failed回退 - GPU异常回退 - has_available_worker 三种场景(无worker/fresh/stale) - 全量GPU相关 30 个测试全绿(含前两个PR的11+10) ## 联调说明 1. PR合入后staging watchtower自动部署(USE_GPU_LIPSYNC=true已生效) 2. RTX2060上按deploy/gpu_worker/README.md部署Worker脚本,.env配staging API+Token 3. 前端正常走数字人创建流程即可——后端在submit阶段会自动检测Worker在线并走MuseTalk本地推理 4. Worker离线/失败时自动回退MediaKit云端,用户无感知 5. staging验证稳定后,把production的USE_GPU_LIPSYNC改成true即可灰度生产
xiaoxia added 1 commit 2026-09-19 16:04:14 +08:00
feat(gpu): #1978 AI数字人口型同步接入MuseTalk GPU Worker
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 1s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web 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 1m38s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 2m31s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m31s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m55s
AI Code Review / AI Code Review (pull_request) Successful in 6m27s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 13m8s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m34s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m15s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m25s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 2m30s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m48s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 6m22s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 26s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 1m42s
565148e66c
业务侧(LipsyncService)集成 GpuLipsyncService:
- 新增开关 USE_GPU_LIPSYNC(env,默认false;staging默认true方便联调,生产默认false待稳定后开)
- _submit_audio_direct 在签名提交 MediaKit 前判断:
  * 开关关闭 → 直接走现有 MediaKit 云端 lipsync
  * 开关开但无可用 Worker(last_heartbeat_at 超5分钟窗口) → 回退 MediaKit
  * 开关开+Worker可用 → 创建GPU任务→同步轮询等待结果
- GPU路径成功:直接标记 job.status=completed、output_video_url=签名后的结果URL
- GPU超时(默认1200s)/终态failed/异常 → 全部回退 MediaKit,对用户透明
- 轮询间隔默认5s,可配 GPU_LIPSYNC_POLL_INTERVAL
- Worker心跳新鲜度窗口可配 GPU_WORKER_STALE_SECONDS(默认300s)

GpuLipsyncService新增方法:
- has_available_worker():判断5分钟内有心跳的Worker存在
- wait_for_result(task_id, timeout, poll_interval):同步轮询DB等待终态,
  期间顺手 _recover_timed_out_tasks;超时返回None让调用方兜底

env/CI配置:
- .env.example 新增4个配置项注释
- deploy/configs/.env.staging USE_GPU_LIPSYNC=true(联调)
- deploy/configs/.env.production USE_GPU_LIPSYNC=false(暂不开)

单元测试:tests/unit/test_lipsync_gpu_integration.py 9个用例覆盖:
- 开关关不调用GPU、无Worker回退、GPU成功completed、超时回退、
  failed回退、异常回退、has_available_worker三种场景
- 全部 30个GPU相关测试全绿(含此前11+10个)

🚀 预览环境已部署

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

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

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

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

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #1991 | | 预览链接 | [https://pr-1991.preview.xiaoxiajianji.com](https://pr-1991.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia merged commit 112f0eb277 into develop 2026-09-19 22:43:58 +08:00

🗑️ 预览环境已清理

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

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

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