refactor(worker): generate_video直接读取edit_plan_clips渲染 (#1468)
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 47s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 50s
CI/CD Pipeline / Validate - Type Check (mypy) (pull_request) Successful in 3m22s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 3m27s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 3m31s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 3m40s
CI/CD Pipeline / Validate - Migration (alembic) (pull_request) Successful in 3m4s
AI Code Review / AI Code Review (pull_request) Failing after 3m53s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m31s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 30s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m45s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 3m30s
CI/CD Pipeline / Build Staging API Image (push) Successful in 7m24s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 7m21s
CI/CD Pipeline / Validate - Code Quality (push) Successful in 8m19s
CI/CD Pipeline / Validate - Code Quality (pull_request) Successful in 8m24s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m4s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m21s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 2m25s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m21s
CI/CD Pipeline / Integration Tests (push) Successful in 3m28s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m27s
CI/CD Pipeline / Unit Tests (push) Successful in 15m5s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 14m25s
CI/CD Pipeline / CI Gate (pull_request) Successful in 9s
CI/CD Pipeline / Production Browser E2E (pull_request) Failing after 575h4m31s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 575h4m36s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 575h4m36s
CI/CD Pipeline / Canary Release to Production (push) Failing after 575h6m30s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 575h4m34s
CI/CD Pipeline / Production Browser E2E (push) Failing after 575h6m30s
CI/CD Pipeline / Build Production API Image (push) Failing after 575h6m34s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 575h4m36s
CI/CD Pipeline / CI Gate (push) Failing after 575h6m34s
CI/CD Pipeline / Deploy Production (push) Failing after 575h6m31s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 575h6m32s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 575h15m53s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 575h15m55s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 575h16m32s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 575h15m58s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 575h18m56s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 575h18m57s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 575h19m6s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 575h19m5s
CI/CD Pipeline / PR Build Web Image (push) Failing after 575h19m7s
CI/CD Pipeline / PR Build API Image (push) Failing after 575h19m9s
CI/CD Pipeline / Frontend Lint (push) Failing after 575h21m41s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 575h21m43s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 575h22m37s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 575h21m45s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 575h21m47s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 575h38m24s
CI/CD Pipeline / Build Production Web Image (push) Failing after 575h40m23s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 575h49m49s

This commit was merged in pull request #1468.
This commit is contained in:
2026-08-23 16:03:30 +08:00
parent 4de4b8dc08
commit b4e3bb0fe7
17 changed files with 732 additions and 1142 deletions
@@ -17,6 +17,8 @@ from fastapi import APIRouter, Depends, HTTPException, Query, status
from .dependencies import get_draft_plan_id, get_editor_services
from .schemas import (
EditorClipBatchUpdateRequest,
EditorClipBatchUpdateResponse,
EditorDraftResponse,
EditorPublishResponse,
EditorRollbackRequest,
@@ -126,11 +128,7 @@ def list_template_versions(
clip_count=len(v.clip_configs),
change_note=v.change_note,
published_by=v.published_by,
created_at=(
v.created_at.isoformat()
if hasattr(v.created_at, "isoformat")
else str(v.created_at)
),
created_at=(v.created_at.isoformat() if hasattr(v.created_at, "isoformat") else str(v.created_at)),
)
for v in versions
]
@@ -162,3 +160,35 @@ def rollback_template(
new_version=tpl.version,
clip_count=len(clip_configs),
)
@router.put("/clips", response_model=EditorClipBatchUpdateResponse)
def batch_update_clips(
template_id: str,
req: EditorClipBatchUpdateRequest,
plan_id: str = Depends(get_draft_plan_id),
services: tuple[EditTemplateService, EditPlanService] = Depends(get_editor_services),
_: AuthenticatedUser = Depends(get_current_user),
):
"""批量替换草稿clips(全量覆盖,用于前端选择素材后同步片段)
事务保证:清空→创建→标记ready 在同一数据库事务内完成,
任何步骤失败时自动回滚,避免数据不一致。
"""
_, plan_svc = services
plan_svc.get_plan_or_raise(plan_id)
clips_data = []
for clip_item in req.clips:
item = {
"asset_id": clip_item.asset_id,
"start_time": clip_item.start_time,
"duration": clip_item.duration,
}
if clip_item.order is not None:
item["order"] = clip_item.order
clips_data.append(item)
plan_svc.replace_all_clips_transactional(plan_id, clips_data)
return EditorClipBatchUpdateResponse(plan_id=plan_id, clip_count=len(req.clips))
@@ -197,7 +197,7 @@ def generate_editor_draft(
plan_svc.update_plan_config(plan_id, {"generation_task_id": gen_task.id})
plan_svc.transition_status(plan_id, EditPlanStatus.RENDERING)
celery_app.send_task("worker.render_edit_plan", args=[plan_id])
celery_app.send_task("worker.generate_video", args=[gen_task.id])
updated_plan = plan_svc.get_plan_or_raise(plan_id)
@@ -46,6 +46,7 @@ class EditPlanGenerationStatusResponse(BaseModel):
class EditPlanGenerateRequest(BaseModel):
"""模板编辑器触发生成请求体"""
title_config: Optional[Dict[str, Any]] = Field(
default_factory=dict,
description="标题配置(可选),渲染时烧录到视频中。支持字段: text/font/font_size/font_color/position/bold/stroke/shadow",
@@ -75,12 +76,8 @@ class AIRecommendRequest(BaseModel):
"""AI 推荐片段方案请求体"""
asset_ids: List[str] = Field(default_factory=list, description="素材 ID 列表")
editing_mode: str = Field(
default="one_take", description="剪辑模式: one_take / pip / voice_over / voice_pip"
)
target_duration: float = Field(
default=30.0, ge=1.0, le=600.0, description="目标时长(秒)"
)
editing_mode: str = Field(default="one_take", description="剪辑模式: one_take / pip / voice_over / voice_pip")
target_duration: float = Field(default=30.0, ge=1.0, le=600.0, description="目标时长(秒)")
class AIRecommendClipItem(BaseModel):
@@ -107,8 +104,6 @@ class AIRecommendResponse(BaseModel):
confidence: float = Field(..., ge=0.0, le=1.0, description="AI 推荐置信度 (0~1)")
# ── BGM ────────────────────────────────────────────────────────────────────
@@ -224,9 +219,7 @@ class ClipBatchDeleteResponse(BaseModel):
class ClipsFromAssetsRequest(BaseModel):
"""从素材批量创建片段请求"""
asset_ids: List[str] = Field(
..., min_length=1, max_length=200, description="素材 ID 列表,按顺序追加到时间线末尾"
)
asset_ids: List[str] = Field(..., min_length=1, max_length=200, description="素材 ID 列表,按顺序追加到时间线末尾")
clip_type: str = Field(default="main", description="片段类型,默认 main")
@@ -501,6 +494,28 @@ class EditorClipUpdateRequest(BaseModel):
config: Optional[dict[str, Any]] = None
class EditorClipBatchItem(BaseModel):
"""批量更新clips的单个片段"""
asset_id: str = Field(default="", max_length=100, description="关联素材ID,可为空(占位片段)")
start_time: float = Field(default=0.0, ge=0.0)
duration: float = Field(default=0.0, ge=0.0)
order: Optional[int] = Field(default=None, ge=0, description="排序,None表示按数组顺序")
class EditorClipBatchUpdateRequest(BaseModel):
"""批量替换clips请求(全量覆盖)"""
clips: List[EditorClipBatchItem] = Field(default_factory=list)
class EditorClipBatchUpdateResponse(BaseModel):
"""批量更新clips响应"""
plan_id: str
clip_count: int
class EditorPublishResponse(BaseModel):
"""发布草稿响应"""