d08835ec9f
P0-1: Seedance 2.5 视频生成对接 - packages/shared/ai_client.py: DoubaoClient 新增 video_generation(prompt, image_url, duration, ratio, ...) 方法:走方舟 /contents/generations/tasks 异步任务(submit→poll→download),返回本地 MP4 路径 - packages/shared/ai_service.py: 新增 call_video_generation() 高层封装 - packages/config/base.py: 新增 doubao_video_model/doubao_video_timeout/doubao_video_poll_interval 配置 - apps/worker/.../viral_video.py _step_render 重写:按 storyboard 分镜逐段调 Seedance 生成短视频 → ffmpeg concat 拼接 → 混入 TTS 音频(-map 0:v/1:a -shortest -c:v copy) - 单分镜失败自动用 ffmpeg color 源占位片段兜底,保证 concat 不中断 - 新增 _normalize_storyboard/_fallback_storyboard/_build_segment_prompt/_probe_ok/_make_placeholder_clip 等辅助函数 P0-2: _step_video_analysis import 路径修复 - from worker_app.tasks.viral_video_analyzer → from viral_video.video_analyzer import analyze_video_style (文件在 apps/worker/viral_video/video_analyzer.py,worker PYTHONPATH 包含 apps/worker) - ImportError 仍兜底返回占位 style_guide,不阻塞流水线 P0-3: image_analysis 持久化 - packages/domain/viral_video.py: ViralVideoJob 新增 image_analysis: dict|None 字段 - packages/adapters/sqlalchemy_impl/models.py: viral_video_jobs 加 image_analysis JSON 列 - packages/adapters/sqlalchemy_impl/viral_video_repository.py: _to_domain/save/update 同步该字段 - alembic/versions/087_viral_video_image_analysis.py: migration 087 - run_viral_video_pipeline: step1 后立即 job.image_analysis = image_analysis 并 _save_job - resume_viral_video_pipeline: 从 job.image_analysis 读取,不再硬编码空 dict P1 顺手修复: - _step_tts: 返回值统一为 Path|None,Path 不存在/ImportError/synthesize 失败均返回 None - _step_bgm_select: BGM 素材未就绪前统一返回 None,渲染时跳过 BGM 混音 - _step_musetalk: GPU 端点未就绪前(即使有 persona_id)也直接跳过,不发 HTTP 请求 - TTS 工厂 import 路径修正: worker_app.services.tts_service_factory → services.tts_service_factory - credits_cost 赋值保留 TODO(等 credits.deduct() 总开关) - tests/unit/test_viral_video.py: BGM/TTS mock 对齐新返回语义 - tests/unit/test_viral_video_p0.py: 新增 15 个单测覆盖 video_analysis/storyboard 规范化/ TTS Path 处理/BGM None/MuseTalk 跳过/call_video_generation 委托/placeholder clip/resume 读 job