feat(viral-video): v1.6 单次Seedance出片+编导分镜脚本 #2124
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API 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
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 50s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m18s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 1m21s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Successful in 1m42s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m33s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m3s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m57s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 4m14s
CI/CD Pipeline / Build Production API Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Web Image (pull_request) Has been cancelled
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been cancelled
CI/CD Pipeline / Deploy Production (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Style (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Security (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (pull_request) Has been cancelled
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / CI Gate (pull_request) Has been cancelled
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been cancelled
CI/CD Pipeline / Unit Tests (pull_request) Has been cancelled
AI Code Review / AI Code Review (pull_request) Has been cancelled
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been cancelled

- 输出从营销口播文案改为专业编导分镜脚本(CopyResult v1.6:overview/scene_and_lighting/shots/hard_constraints/negative_prompts/voiceover_script)
- 新 SCRIPT_GENERATION 阶段替代原 copy_fusion+storyboard+review,prompt 指导 LLM 输出严格 JSON 结构
- pipeline 简化为4步:图片分析 → 编导脚本 → TTS整段合成(上传OSS做reference_audios) → 单次Seedance出片 → 上传
- 删除:多段分镜拆分、ffmpeg concat拼接、placeholder占位视频、分段重试降级、BGM单独混音(Seedance generate_audio=true原生合成音效/BGM)
- ai_client/ai_service video_generation 支持 reference_images/reference_audios/reference_videos/generate_audio 参数
- duration 默认15秒,上限30秒;前端时长下拉 5/10/15/20/25/30s
- 首帧图模式不传 ratio(保持 #2110 修复)
- Alembic migration 088 幂等添加 voice_id/voice_source/video_ratio/video_model/copy_result 五列
- _step_image_analysis call_vision() 全路径 None 防护
- 向后兼容:final_copy=voiceover_script、storyboard=shots、老数据 _build_copy_result 降级拼装
- TS types 更新 CopyResult v1.6 结构 + ShotScript/Overview
- 96个 viral 相关单测全通过
This commit is contained in:
xiaoxia
2026-10-01 13:34:08 +08:00
parent 069544da38
commit 6eeb33bbf3
14 changed files with 1233 additions and 898 deletions
@@ -954,6 +954,9 @@ class ViralVideoJobModel(Base):
image_analysis = Column(JSON, nullable=True)
storyboard = Column(JSON, nullable=True)
generated_copy_text = Column(Text, nullable=False, default="")
copy_result = Column(
JSON, nullable=True
) # v1.6: 编导脚本结构{overview,scene_and_lighting,shots,hard_constraints,negative_prompts,voiceover_script}
result_video_url = Column(String(1000), nullable=False, default="")
credits_cost = Column(Integer, nullable=False, default=0)
error_msg = Column(Text, nullable=False, default="")
@@ -88,6 +88,7 @@ _VIRAL_VIDEO_BACKFILL_COLS = [
("voice_source", "VARCHAR(20) NOT NULL DEFAULT ''"),
("video_ratio", "VARCHAR(10) NOT NULL DEFAULT '9:16'"),
("video_model", "VARCHAR(100) NOT NULL DEFAULT ''"),
("copy_result", "JSON"),
]
@@ -24,7 +24,7 @@ def _to_domain(model: ViralVideoJobModel) -> ViralVideoJob:
viral_structure=model.viral_structure or "",
marketing_purpose=model.marketing_purpose or "",
bgm_preference=model.bgm_preference or "",
duration=model.duration or 30,
duration=model.duration or 15,
user_copy_text=model.user_copy_text or "",
fusion_level=model.fusion_level or "ai_polish",
reference_audio_path=model.reference_audio_path or "",
@@ -41,6 +41,7 @@ def _to_domain(model: ViralVideoJobModel) -> ViralVideoJob:
image_analysis=dict(model.image_analysis) if getattr(model, "image_analysis", None) else None,
storyboard=list(model.storyboard) if getattr(model, "storyboard", None) else None,
generated_copy_text=getattr(model, "generated_copy_text", "") or "",
copy_result=dict(model.copy_result) if getattr(model, "copy_result", None) else None,
result_video_url=model.result_video_url or "",
credits_cost=model.credits_cost or 0,
error_msg=model.error_msg or "",
@@ -86,6 +87,7 @@ class SQLAlchemyViralVideoJobRepository:
image_analysis=job.image_analysis,
storyboard=job.storyboard,
generated_copy_text=job.generated_copy_text,
copy_result=job.copy_result,
result_video_url=job.result_video_url,
credits_cost=job.credits_cost,
error_msg=job.error_msg,
@@ -108,6 +110,7 @@ class SQLAlchemyViralVideoJobRepository:
model.image_analysis = job.image_analysis
model.storyboard = job.storyboard
model.generated_copy_text = job.generated_copy_text or ""
model.copy_result = job.copy_result
model.result_video_url = job.result_video_url
model.credits_cost = job.credits_cost
model.error_msg = job.error_msg