# 视频批量并行生成经验 ## 背景 爆款 MV 和爆款视频第三步原本按镜头顺序串行生成,主要理由是把上一段视频尾帧传给下一段首帧。实测尾帧传递对后续片段影响不大,串行等待反而显著拉长整条生成链路。因此本轮将“全部→生成视频”改为镜头级并行:每个镜头独立执行“首帧图 → 本节视频”,镜头之间不再互相等待。 ## 经验 ### 1. 先拆清楚依赖是真依赖还是历史惯性 上一段尾帧传下一段首帧看起来能保证连贯,但如果实际收益有限,它就会把所有镜头绑成一个长串。批量生成前应判断依赖的真实价值: - 真依赖:必须等待上游结果,否则下游无法生成。 - 软约束:有助于质量,但可通过提示词、角色参考图、全局参考图替代。 - 历史惯性:过去为了规避某个问题留下的串行流程,但当前模型或产品目标已经变化。 本次把镜头间尾帧传递降级为非批量主路径能力,保留手动帧传递按钮,批量默认追求速度。 ### 2. 并行不是无序,每个镜头内部仍要有顺序 批量层可以并行,但单镜头 pipeline 必须保持: 1. 复用或生成本镜头首帧。 2. 首帧写回记录。 3. 用该首帧提交本镜头视频任务。 4. 视频完成后按镜头 ID 写回。 这样既能并行加速,又避免视频任务在缺少首帧时退化成纯文生视频,导致角色和主体一致性下降。 ### 3. 批量任务要隔离自动回填副作用 现有任务监听会在普通视频任务完成后自动提取相邻帧。如果批量并行生成的视频也走这条自动回填,就会重新把并行流程污染成隐形链式依赖。 做法是记录批量创建的视频任务 ID,任务监听识别到这些 ID 时只写回视频 URL,不触发相邻首帧/尾帧自动回填。手动单镜头生成仍保留原来的自动辅助逻辑。 ### 4. 并发写回必须按镜头 ID 合并 并行任务完成顺序不可预测,不能拿启动时的 shots 快照整体覆盖记录。写回时应读取最新 `latestShotsRef.current`,按 `shot.id` 局部替换: - 首帧结果只更新对应镜头的 `generated_first_frame_url`。 - 视频结果只更新对应镜头的 `generated_video_url`。 - 不把旧快照中的其它镜头字段写回去。 这能降低多个镜头同时完成时互相覆盖的风险。 ### 5. 停止按钮要管理一组活跃任务 串行流程只需要记一个 active task;并行流程必须维护 task ID 集合。停止时: - 标记批量停止,阻止 pipeline 进入下一阶段。 - cancel 当前集合里的所有本地任务。 - abort 当前等待。 远端已经接收的任务不一定能撤销,但前端不应继续推进批量编排或产生新的依赖任务。 ### 6. 高并发文件服务里只传引用,不搬运大对象 批量生成中不要读取图片/视频二进制,不保存 base64,不把完整素材对象塞进 workflow record。首帧、主体参考图、全局参考图和视频结果都用 URL 引用流转,写回记录只保存轻量字段,避免内存峰值和交换分区压力。 ### 7. 主体参考图要同时覆盖批量和单镜头入口 第三步优化主体一致性时,不能只改“全部生成视频”的自动编排。用户也会在单个镜头里手动打开首帧生成弹窗,此时应把当前镜头绑定角色的参考图、已有草稿图和已生成首帧合并后传入弹窗,并按 URL 去重。 这样手动微调和批量生成使用同一套轻量引用,既提升角色继承效果,也避免把素材库实体或二进制内容塞回生成记录。 ## 检查清单 - 批量生成文案是否从“串行第 N 段”改为并行进度。 - 批量流程是否还有上一段尾帧变量或下一段首帧自动写入。 - 首帧失败时是否会阻止本镜头视频继续提交。 - 视频任务完成监听是否跳过批量任务的相邻帧自动回填。 - 并发写回是否基于最新 shots 按 ID 合并。 - 停止逻辑是否取消全部活跃 task,而不是只取消最后一个。 - 生成编排是否只传 URL 引用,不读取大文件或 base64。 - 单镜头首帧弹窗是否合并角色参考图,并对 URL 去重。