From 6f36abae9cc18f8d04ec78bd11c95e7768c1fa20 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Fri, 11 Sep 2026 11:22:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(worker):=20=E6=B3=A8=E5=86=8C=20ai=5Favatar?= =?UTF-8?q?=5Frender=20Celery=20=E4=BB=BB=E5=8A=A1=E5=88=B0=20Worker?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E5=A4=8D=20AI=E6=95=B0=E5=AD=97=E4=BA=BA?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E5=8D=A1=200%=20(#1846)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: xiaoxia Co-committed-by: xiaoxia --- apps/worker/worker_app/celery_app.py | 2 + .../worker_app/tasks/ai_avatar_render.py | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 apps/worker/worker_app/tasks/ai_avatar_render.py diff --git a/apps/worker/worker_app/celery_app.py b/apps/worker/worker_app/celery_app.py index c5dc8fd71..77a2218a4 100755 --- a/apps/worker/worker_app/celery_app.py +++ b/apps/worker/worker_app/celery_app.py @@ -34,6 +34,8 @@ celery_app.conf.imports = ( "worker_app.tasks.tts_synthesis", "worker_app.tasks.batch_download", "worker_app.tasks.duplication_check", + # #1798 AI 数字人渲染:必须在 Worker 实例上注册同名任务,否则消息无人消费(渲染卡 0%) + "worker_app.tasks.ai_avatar_render", "worker_app.tasks._startup", "apps.worker.video_processing.dedup", "worker_app.tasks.cleanup", diff --git a/apps/worker/worker_app/tasks/ai_avatar_render.py b/apps/worker/worker_app/tasks/ai_avatar_render.py new file mode 100644 index 000000000..977564dd6 --- /dev/null +++ b/apps/worker/worker_app/tasks/ai_avatar_render.py @@ -0,0 +1,48 @@ +"""AI 数字人渲染任务 — Worker 侧 Celery 任务注册. + +#1798 渲染进度卡在 0% 的根因:渲染任务定义在 API 侧(`app.tasks.ai_avatar_render`), +装饰在 API 自己的 Celery 实例(`xiaoxia-saas-api`)上;而 Worker 用的是 +`worker_app.celery_app` 实例,`conf.imports` 从未导入该任务,Worker 的任务 +注册表里没有 `ai_avatar_render.execute`,消息被路由到默认 `celery` 队列后 +无人消费,任务永远停在 0%。 + +修复:在 Worker 侧用 `worker_app.celery_app` 注册同名任务,直接调用与 API +服务一致的 `AiAvatarRenderService.execute_render` 核心管线(业务逻辑在 +`apps.api.app.services`,worker 镜像已复制 `apps/api/app`)。任务名保持 +`ai_avatar_render.execute`,与 API 生产端 `.delay()` 的消息路由一致;未在 +task_routes 显式配置,走默认 `celery` 队列,由 transcode worker 消费。 +""" + +from __future__ import annotations + +import logging + +from worker_app.celery_app import celery_app +from worker_app.db import SessionLocal + +logger = logging.getLogger(__name__) + + +@celery_app.task(bind=True, name="ai_avatar_render.execute", max_retries=2) +def execute_ai_avatar_render(self, job_id: str) -> dict: + """执行 AI 数字人渲染管线(Worker 侧入口). + + 进度由 service 直接写入 DB(AiAvatarRenderJob.progress: + 0→5→20→40→80→90→95→100),API 通过轮询 progress 字段展示。 + """ + logger.info("开始执行渲染任务: %s", job_id) + self.update_state(state="PROCESSING", meta={"progress": 0, "job_id": job_id}) + + session = SessionLocal() + try: + from app.services.ai_avatar_render_service import AiAvatarRenderService + + service = AiAvatarRenderService(session) + service.execute_render(job_id) + return {"status": "completed", "job_id": job_id} + except Exception as exc: + logger.exception("渲染任务执行异常 [%s]: %s", job_id, exc) + self.update_state(state="FAILED", meta={"progress": 0, "error": str(exc)}) + raise + finally: + session.close()