feat(api): 剪辑计划生成状态API增强 - 新增progress/video_url/error_message等字段 #351

Merged
xiaoxia merged 4 commits from fix/edit-plan-generation-api-enhancement into develop 2026-07-15 11:15:56 +08:00
7 changed files with 81 additions and 10 deletions
+4
View File
@@ -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]
+17 -4
View File
@@ -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,
)
@@ -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]:
@@ -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)
@@ -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"
+16 -3
View File
@@ -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) ────────────────────────────────────────
+10 -1
View File
@@ -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