这篇文章记录了我在做一个 AI 视频生成项目时的设计思路和踩坑经历。如果你也在探索 AIGC 在视频领域的应用,希望能给你一些启发。
在短视频时代,内容创作的效率成为关键竞争力。传统的视频制作流程需要编剧、分镜师、摄影师、后期制作等多个角色协作,周期长、成本高。本文旨在通过AI技术,打造一套从剧本文字到分镜视频的自动化生成系统,让普通用户也能快速产出专业级的视频内容。
做这个项目的起因很简单——我想把一段剧本快速变成视频。
传统流程是这样的:写剧本 → 画分镜 → 找素材/拍摄 → 剪辑 → 成片。每个环节都需要专业技能,一个人很难搞定。即使用 AI 生成图片和视频,也需要反复手动操作:复制描述词、调参数、下载、整理……效率很低。
我想要的是:把剧本扔进去,系统自动跑完整个流程,我只需要在关键节点做选择。
经过几个月的摸索,最终形成了现在这套方案。
在动手之前,我给自己定了三个原则:
选型过程其实挺纠结的,分享一下我的思考:
我试过三个方案:
React Flow 打动我的点:
// 自定义节点就是普通的 React 组件,太直观了 const StoryboardNode = ({ data }) => { return (); }; {data.description}![]()
节点内部可以做任意复杂的 UI,状态管理也很自然。几十个节点拖来拖去性能也没问题。
这个选择可能有点反直觉。原因:
没什么好说的,目前图生视频效果最好的选择。缺点是贵,而且有时候排队时间很长。
先看整体结构:
┌─────────────────────────────────────────────────────────────┐ │ 用户界面层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 项目管理 │ │ 工作流编排 │ │ 资源库管理 │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 节点组件层 │ │ ┌────────┐ ┌────────┐ ┌────────┐ ┌─────────┐ ┌────────┐ │ │ │剧情描述│ │小说输入│ │分镜列表│ │分镜图节点│ │视频展示│ │ │ └────────┘ └────────┘ └────────┘ └─────────┘ └────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ 业务逻辑层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ 剧本解析服务 │ │ 图像生成服务 │ │ 视频生成服务 │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ ├─────────────────────────────────────────────────────────────┤ │ AI 能力层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Gemini LLM │ │ 图像模型 │ │ Sora 视频 │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ └─────────────────────────────────────────────────────────────┘
为什么要分这么多层?说实话,最开始我也是“能跑就行”的心态,节点组件里直接调 API。
然后我就后悔了。
当我想把图像生成从 DALL-E 换成 Midjourney 时,发现要改七八个文件。当我想加一个“生成失败自动重试”的逻辑时,发现每个节点都要改一遍。
于是痛定思痛,花了一周重构成现在这个分层结构。核心原则:节点组件只管 UI 和交互,业务逻辑下沉到服务层,AI 调用再封装一层。
现在换模型只需要改 AI 层,加通用功能只需要改业务层,节点组件可以专注于用户体验。
用户输入剧本后,第一步不是直接拆分镜,而是让 AI 做一次“阅读理解”:
输入:一段小说或剧本文本 AI 分析输出: - 角色列表:姓名、外貌、性格特征 - 场景列表:环境描述、氛围 - 关键道具:会影响视觉呈现的物品 - 情节脉络:故事的起承转合
这一步很关键。我之前直接让 AI 拆分镜,结果经常出现角色描述前后不一致的问题。先提取结构化信息,后续生成时就可以始终引用同一份角色设定。
我设计了一个资源引用语法:[@角色ID]。在剧情描述中使用这个语法,系统会自动关联到对应的角色资源,确保生成时使用一致的参考图。
坦白说,让 AI 拆分镜是我踩坑最多的环节。
第一版:简单 prompt
请将以下剧本拆分成分镜:{script}
结果:AI 要么拆得太细(每句话一个镜头),要么太粗(整段只有一个镜头)。
第二版:加约束条件
请将剧本拆分成分镜,要求: - 每个分镜 5-15 秒 - 场景切换时必须分镜 - 重要动作需要单独分镜
好一些了,但还是不稳定。
第三版:引入结构化输出 最后我用了 JSON Schema 约束输出格式,并且给了详细的示例:
{ "storyboards": [ { "index": 1, "duration": 8, "summary": "林小雨独自走在暮色中的青石板路上", "visualDescription": "黄昏时分,一位身穿浅蓝色连衣裙的少女...", "cameraMovement": "缓慢推进", "mood": "孤独、思念" } ] }
稳定多了。关键是 visualDescription 这个字段,它是后续图像生成的直接输入,必须足够详细。
分镜描述有了,下一步是生成每个镜头的画面。
这里最大的挑战是角色一致性——同一个角色在不同分镜里应该长得一样。
我的解决方案:
效果还行,但远没到完美。有时候 AI 还是会“忘记”角色长什么样。这是目前技术的局限,我也在持续尝试新方案。
静态分镜图 → 动态视频片段,这一步交给 Sora。
我做了几个工程化处理:
异步任务队列 视频生成太慢了,必须异步。我用 Redis 做任务状态存储:
任务状态流转: PENDING → PROCESSING → SUCCESS / FAILED 前端轮询 /api/task/{taskId}/status 返回:进度百分比、预估剩余时间、结果 URL
自动重试 Sora 有时会超时或报错。我加了指数退避重试:
@Retryable( value = {VideoGenerationException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000, multiplier = 2) ) public VideoResult generate(VideoRequest request) { // ... }
批量生成优化 多个分镜可以并行提交,不需要等一个完成再提下一个。前端维护一个任务列表,实时更新每个任务的状态。
前面提到了,这是 AI 生成图像的老大难问题。目前的参考图方案只能做到“大致相似”,细节还是会飘。
一些正在尝试的方向:
相邻分镜之间的过渡有时很生硬。比如上一个镜头角色站在门口,下一个镜头直接跳到室内,缺少一个开门进入的过渡。
这个问题我还没有好的解决方案。可能需要在分镜阶段就让 AI 考虑转场,或者后期加一个“智能转场插入”的步骤。
一个 10 秒的视频,Sora 可能要跑 3-5 分钟。一个项目有 20 个分镜,全部生成完要一两个小时。
虽然做了异步和并行,但等待时间还是太长了。短期来看只能接受,长期可能需要等更快的模型出现。
AI 太“听话”会显得机械,太“自由发挥”又可能跑偏。
我的处理方式是提供多级控制:
给用户选择权,而不是替用户做决定。
这个项目还在持续迭代中。从最初的“能用就行”到现在的架构,大概重构了三四次。
回头看,最大的收获是理解了一件事:AI 能力再强,也需要好的工程化封装才能变成产品。
单独调 Sora API 谁都会,但怎么把它嵌入一个流畅的工作流?怎么处理失败和重试?怎么让用户在等待时不焦虑?这些“脏活累活”才是真正的工作量。
如果你也在做类似的项目,欢迎交流。我的经验是:
这篇文章会持续更新,记录后续的优化和新踩的坑。有问题欢迎留言讨论。