diff --git a/apps/api/app/api/routes/edit_plans.py b/apps/api/app/api/routes/edit_plans.py old mode 100644 new mode 100755 index a830cd193..227af0e67 --- a/apps/api/app/api/routes/edit_plans.py +++ b/apps/api/app/api/routes/edit_plans.py @@ -108,6 +108,10 @@ class EditPlanGenerationStatusResponse(BaseModel): plan_id: str plan_status: str generation_task_id: Optional[str] = None + generation_task_status: Optional[str] = None + progress: float = 0.0 + video_url: str = "" + error_message: str = "" clips: List[ClipStatusItem] diff --git a/apps/api/app/api/routes/edit_plans_generation.py b/apps/api/app/api/routes/edit_plans_generation.py old mode 100644 new mode 100755 index 7d7e37039..23829f179 --- a/apps/api/app/api/routes/edit_plans_generation.py +++ b/apps/api/app/api/routes/edit_plans_generation.py @@ -183,9 +183,7 @@ def _auto_fallback_auto_material_mode( def _check_queue_limits(gen_task_repo, user_id: str) -> None: """队列限流预检查""" try: - has_count = hasattr(gen_task_repo, "count_pending_by_user") and hasattr( - gen_task_repo, "count_pending_total" - ) + has_count = hasattr(gen_task_repo, "count_pending_by_user") and hasattr(gen_task_repo, "count_pending_total") if has_count: user_pending = gen_task_repo.count_pending_by_user(user_id) global_pending = gen_task_repo.count_pending_total() @@ -333,10 +331,25 @@ def get_generation_status( for c in clips ] + # 从 plan.config 中取渲染结果 URL + video_url = (plan.config or {}).get("rendered_url", "") + # 从 gen_status 中取进度、错误信息、任务状态 + progress = gen_status.get("progress", 0.0) + error_message = gen_status.get("error_message", "") + gen_task_status = gen_status.get("generation_task_status") + # 如果计划已完成但进度还是0,补100 + plan_status_val = plan.status.value if hasattr(plan.status, "value") else plan.status + if plan_status_val == "completed" and progress < 100: + progress = 100.0 + return EditPlanGenerationStatusResponse( plan_id=plan_id, - plan_status=plan.status.value if hasattr(plan.status, "value") else plan.status, + plan_status=plan_status_val, generation_task_id=gen_status["generation_task_id"], + generation_task_status=gen_task_status, + progress=progress, + video_url=video_url, + error_message=error_message, clips=clip_items, ) diff --git a/apps/api/app/services/edit_plan_service.py b/apps/api/app/services/edit_plan_service.py index 6ff73b7a6..3b178de09 100755 --- a/apps/api/app/services/edit_plan_service.py +++ b/apps/api/app/services/edit_plan_service.py @@ -431,6 +431,8 @@ class EditPlanService: "clips": List[EditPlanClip], "generation_task_id": Optional[str], "generation_task_status": Optional[str], + "progress": float, + "error_message": str, } Raises: @@ -442,17 +444,23 @@ class EditPlanService: # 从 plan.config 中获取 generation_task_id generation_task_id = plan.config.get("generation_task_id") generation_task_status = None + progress = 0.0 + error_message = "" if generation_task_id: task = self._generation_task_repo.get(generation_task_id) if task: generation_task_status = task.status.value if hasattr(task.status, "value") else task.status + progress = getattr(task, "progress", 0.0) or 0.0 + error_message = getattr(task, "error_message", "") or "" return { "plan": plan, "clips": clips, "generation_task_id": generation_task_id, "generation_task_status": generation_task_status, + "progress": progress, + "error_message": error_message, } def can_generate(self, plan_id: str) -> tuple[bool, str]: diff --git a/apps/worker/worker_app/tasks/compose_video.py b/apps/worker/worker_app/tasks/compose_video.py index 4509d5e02..66cd4b844 100755 --- a/apps/worker/worker_app/tasks/compose_video.py +++ b/apps/worker/worker_app/tasks/compose_video.py @@ -63,6 +63,18 @@ def compose_video(self, job_id: str, **kwargs): resolver = get_render_engine_resolver() user_id = job.created_by_user_id or None engine = resolver.get_engine(user_id=user_id) + # 灰度期间打印详细 flag 配置,便于排查 + config = resolver.get_config_snapshot() + logger.info( + "compose_video 引擎选择: job_id=%s engine=%s user_id=%s enabled=%s percentage=%s whitelist=%d default=%s", + job_id, + engine, + user_id, + config.get("enabled"), + config.get("percentage"), + len(config.get("whitelist", [])), + config.get("default_engine"), + ) if engine == "unified": return _compose_with_unified_engine(self, job_service, job, plan_id, db) diff --git a/apps/worker/worker_app/tasks/edit_plan_generation.py b/apps/worker/worker_app/tasks/edit_plan_generation.py index 9b422ab57..cfef30096 100755 --- a/apps/worker/worker_app/tasks/edit_plan_generation.py +++ b/apps/worker/worker_app/tasks/edit_plan_generation.py @@ -77,9 +77,21 @@ def _resolve_render_engine(user_id: str) -> str: from video_processing.render_engine_resolver import get_render_engine_resolver resolver = get_render_engine_resolver() - return resolver.get_engine(user_id=user_id) + engine = resolver.get_engine(user_id=user_id) + # 灰度期间打印详细 flag 配置,便于排查 + config = resolver.get_config_snapshot() + logger.info( + "edit_plan 引擎选择: user_id=%s engine=%s enabled=%s percentage=%s whitelist=%d default=%s", + user_id, + engine, + config.get("enabled"), + config.get("percentage"), + len(config.get("whitelist", [])), + config.get("default_engine"), + ) + return engine except Exception as exc: - logger.warning("获取渲染引擎配置失败,fallback 到 legacy: %s", exc) + logger.warning("获取渲染引擎配置失败,fallback 到 legacy: %s", exc, exc_info=True) return "legacy" diff --git a/apps/worker/worker_app/tasks/generation.py b/apps/worker/worker_app/tasks/generation.py index 6af97259a..9d475c463 100755 --- a/apps/worker/worker_app/tasks/generation.py +++ b/apps/worker/worker_app/tasks/generation.py @@ -787,10 +787,23 @@ def _resolve_render_engine(user_id: str) -> str: from video_processing.render_engine_resolver import get_render_engine_resolver resolver = get_render_engine_resolver() - return resolver.get_engine(user_id=user_id) + engine = resolver.get_engine(user_id=user_id) + # 灰度期间打印详细 flag 配置,便于排查 + config = resolver.get_config_snapshot() + logger.info( + "[渲染引擎] flag 解析: user_id=%s engine=%s enabled=%s percentage=%s whitelist=%d default=%s", + user_id, + engine, + config.get("enabled"), + config.get("percentage"), + len(config.get("whitelist", [])), + config.get("default_engine"), + ) + return engine except Exception as exc: - logger.warning("获取渲染引擎配置失败,fallback 到 unified: %s", exc) - return ENGINE_UNIFIED + # 异常时 fallback 到 legacy(保守策略,与 edit_plan_generation 一致) + logger.warning("获取渲染引擎配置失败,fallback 到 legacy: %s", exc, exc_info=True) + return ENGINE_LEGACY # ── 旧引擎渲染(FFmpeg filter_complex) ──────────────────────────────────────── diff --git a/tests/unit/test_edit_plan_generation_api.py b/tests/unit/test_edit_plan_generation_api.py old mode 100644 new mode 100755 index 85a1b3e03..add7d042b --- a/tests/unit/test_edit_plan_generation_api.py +++ b/tests/unit/test_edit_plan_generation_api.py @@ -665,7 +665,16 @@ class TestResponseSchema: resp = client.get(f"/api/v1/edit-plans/{plan.id}/generation-status") assert resp.status_code == 200 data = resp.json() - expected_keys = {"plan_id", "plan_status", "generation_task_id", "clips"} + expected_keys = { + "plan_id", + "plan_status", + "generation_task_id", + "generation_task_status", + "progress", + "video_url", + "error_message", + "clips", + } assert set(data.keys()) == expected_keys