一个 AI 创作平台的长视频功能:用户输入一个创意,后端自动完成意图分析 → 剧本生成 → 分镜拆分 → 视频生成 → 最终合成,全程通过 SSE 向用户推送进度。这里记录一下整体架构设计。
一、整体流程
1 2 3 4 5 6 7 8 9 10 11 12 13
| 用户输入意图 ↓ Phase 1: 意图识别 → 生成剧本大纲 + 时长规划 ↓ (文本模型,内部免费) Phase 2: 剧本生成 → 完整的分幕剧情 ↓ (文本模型,内部免费) Phase 3: 分镜拆分 → 拆成 N 个镜头,每个镜头有画面描述 + 动作 + 对白 + 情绪 + 出图提示词 ↓ (文本模型,内部免费) Phase 4: 分镜渲染 → 每个镜头独立生成视频 ↓ (视频模型,每个镜头独立扣费,失败退款) Phase 5: 最终合成 → ffmpeg 本地合成所有已通过审核的分镜视频 ↓ (本地处理,不额外收费) 输出: 封面 + 视频 → 进入作品列表
|
每个阶段之间通过 SSE 向用户推送进度,用户可以在任意阶段确认或修改后继续。
二、核心数据模型
项目主表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| CREATE TABLE long_video ( id BIGINT PRIMARY KEY AUTO_INCREMENT, trace_id VARCHAR(64) NOT NULL COMMENT '项目追踪ID', account_id BIGINT NOT NULL,
title VARCHAR(255), status VARCHAR(32) NOT NULL COMMENT 'draft/processing/waiting_user/rendering/completed/failed/cancelled', current_stage VARCHAR(64) COMMENT 'intent/script/storyboard/render_plan/shot_render/compose/done',
video_model VARCHAR(128) NOT NULL COMMENT '用户选择的生视频模型', aspect_ratio VARCHAR(32) DEFAULT '16:9', duration INT COMMENT '目标总时长',
stages JSON NOT NULL COMMENT '完整阶段状态(意图、剧本、分镜、渲染记录)', billing_summary JSON COMMENT '项目级费用汇总', final_result_url TEXT COMMENT '最终成片地址', cover_url TEXT COMMENT '封面地址',
version INT NOT NULL DEFAULT 1 COMMENT '乐观锁版本', UNIQUE KEY uk_trace_id (trace_id), KEY idx_account_status (account_id, status) );
|
项目与 AI 任务关系表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| CREATE TABLE long_video_ai_task ( id BIGINT PRIMARY KEY AUTO_INCREMENT, long_video_id BIGINT NOT NULL, ai_task_id BIGINT NOT NULL,
task_role VARCHAR(32) NOT NULL COMMENT 'shot_render|final_render|reference_frame|shot_reference_frame', asset_scope VARCHAR(32) NOT NULL DEFAULT 'project_asset' COMMENT 'project_asset|final_work|hidden',
shot_index INT, render_id VARCHAR(64), selected TINYINT DEFAULT 0, need_rerender TINYINT DEFAULT 0, billing_mode VARCHAR(32),
UNIQUE KEY uk_render_id (long_video_id, render_id), KEY idx_long_video_role (long_video_id, task_role) );
|
设计要点:
- 不复用
ai_task.task_type 表达业务角色。task_type 只保持 image/video/3d 的媒体类型语义,业务角色(shot_render、final_render 等)放在 long_video_ai_task.task_role
asset_scope 控制素材可见范围。project_asset = 中间分镜素材不进入作品列表,final_work = 最终成片进入作品列表
- 乐观锁
version:所有对 stages 的写入都带版本条件
三、分镜渲染与断点续跑
批量提交
用户确认分镜后,render-all 接口处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public void renderAll(LongVideoDO project) { boolean serialMode = isSerialModel(project.getVideoModel());
writeShotRenderPending(project, serialMode);
if (serialMode) { submitChainNext(project); } else { submitBatchFirstChunk(project); } }
|
分镜创建 AI 任务
每个分镜走独立的 AI 任务创建流程:
断点续跑
后端重启或前端重新进入时,需要恢复未完成的任务:
四、SSE 事件推送
长视频使用 SSE 向前端实时推送进度。事件流设计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
|
前端接收端处理:
五、最终合成
所有分镜视频完成后,ffmpeg 本地合成:
六、核心不可变规则
- 每个分镜 render 必须有独立
ai_task.trace_id。决不允许多个分镜共用同一个 traceId
- 先创建
ai_task → 再扣费 → 再调上游。扣费成功后上游失败,必须通过 ai_task.trace_id 退款
consumption.request_id == ai_task.trace_id,balance_log.ref_id == ai_task.trace_id
- 中间分镜素材不进入普通作品列表(
asset_scope=project_asset)
- 最终成片进入普通作品列表(
asset_scope=final_work)
- 复刻
long_video.stages 必须带乐观锁版本
- SSE 只推送事务提交后的完整快照,不推增量包络
- 断点续跑必须基于
long_video_ai_task 关系表恢复,不能只依赖 project.status/currentStage
- 文本阶段(意图/剧本/分镜)默认免费,调用
TextCompletionService 但不写消费流水
七、并发安全
这套方案从前端到后端经过了多轮迭代,当前已在线上稳定运行。