最近做了一个本地 AI 视频生成项目,名字叫「帧流 Frameflow」。
它可以把图片、提示词和视频生成任务放在一张画布上。图片可以连到视频节点,也可以在输入框里通过 @ 引用。生成完成后,结果会自动保存到素材库。
项目的起因很简单。
平时用 AI 生成视频,提示词、参考图和生成结果经常散落在不同地方。视频生成时间又比较长,页面一刷新,任务状态还可能丢失。
所以我想做一个工具,把这些东西集中到一张画布里。
项目现在能做什么
目前已经完成的功能:
- 创建和保存多个视频项目。
- 上传本地图片,在画布中作为参考图使用。
- 调用 Agnes Video V2.0 生成视频。
- 支持文生视频、图生视频、多图参考和关键帧模式。
- 支持图片生成和图片编辑。
- 可以通过连线或
@引用其他节点。 - 保存每次生成的请求、响应和结果。
- 页面刷新后,继续查询没有完成的视频任务。
- 在工作台查看项目、素材和生成记录。
- 使用账号密码登录,API Key 只保存在服务端。
项目是本地运行的,还不是一个对外提供服务的 SaaS。
第一版先把接口跑通
刚开始没有做复杂功能,目标只有一个:在本地创建视频任务,并且能拿到最后的视频。
技术栈如下:
前端:React、Vite、React Flow、Zustand
后端:Node.js、Express
数据库:SQLite
视频接口:Agnes Video V2.0
React Flow 用来处理节点和连线,Zustand 保存画布状态。后端负责调用 Agnes、上传素材和保存任务记录。
数据库使用 Node.js 22 内置的 node:sqlite,不需要再安装单独的数据库服务。对本地项目来说比较省事,复制数据库文件也能直接备份。
第一版的页面很像一个开发工具:
左边是节点库
中间是画布
右边是参数
底部是任务日志
界面不算好看,但文生视频、任务轮询和结果保存这条流程先跑通了。
中间加了很多节点,后来又删了
项目中间有一版做了 16 种以上的节点,包括文本、脚本、分镜、镜头卡、Prompt、反向词、图片、视频、音频、素材库和输出。
当时觉得节点越完整,越接近一套 AI 视频工作流。
真正用起来后发现,有些节点只是界面做好了,后面的生成流程并没有完全接上。节点数量多了以后,用户还要先弄懂每个节点应该怎么连。
所以后来又做了一次精简。
当前主要保留:
- 图片素材。
- 图片生成。
- 图片编辑。
- Agnes 视频生成。
- 素材库。
- 图片和视频结果。
角色库、模板、视频合成这些功能还没有做完,就直接标记为规划中,不再放模拟数据。
这次调整比较实际。项目功能少一点没关系,先保证页面上能看到的功能是真的能用。
后来把首页改成了工作台
第一版打开就是画布,对开发者来说没问题,但项目多了以后不方便管理。
后来增加了一个工作台,里面可以看:
- 最近的项目;
- 已经上传或生成的素材;
- 视频和图片生成任务;
- Agnes 服务是否配置成功。
进入项目后才打开画布。
画布底部还增加了一个输入框,可以直接写提示词,也可以用 @ 引用画布里的图片。
比如:
让 @人物参考图 站在雨夜街头,
镜头从远景缓慢推进到半身特写。
选择图片后,系统会自动创建一条引用关系。如果引用一张图片,视频模式自动切换成图生视频;引用多张图片,则切换成多图模式。
这个操作比手动找端口、拉连线快一些。需要固定工作流时仍然可以手动连线。
开发时遇到的几个问题
1. 本地图片不能直接交给云端
浏览器能打开这样的地址:
http://localhost:8787/uploads/example.png
但 Agnes 运行在云端,它访问不到我电脑上的 localhost。
一种解决方法是把所有图片先上传到对象存储。但这个项目目前主要在本地使用,为此再接一套存储服务有点重。
最后的处理方式是:
- 后端识别本站
/uploads/目录里的图片。 - 读取本地文件。
- 转成 base64 格式。
- 再把图片内容发送给 Agnes。
同时限制单张图片不能超过 10MB,并且只允许读取上传目录里的文件。
公网图片不需要转换,继续使用原地址。
2. 视频任务不能只靠一个定时器
视频生成不是立即返回结果。创建任务后,要拿着任务 ID 每隔一段时间查询状态。
刚开始就是普通的轮询,后来遇到了不少情况:
- 创建任务后马上刷新页面;
- 生成过程中切换到另一个项目;
- 同一个项目开了多个浏览器标签页;
- 查询接口暂时返回 404、429、502 或 503;
- 状态已经完成,但视频地址还没有返回;
- 上游已经创建任务,前端却没有保存任务 ID。
现在的处理方式:
- 拿到任务 ID 后先保存,再开始查询。
- 重新打开项目时恢复未完成任务。
- 用户切换项目后,结果仍然写回原来的项目。
- 多个标签页之间加锁,避免重复查询。
- 临时网络错误自动重试。
- 连续失败后暂停轮询,下次打开项目再继续。
视频生成接口真正麻烦的部分,不是发起请求,而是保证任务不会因为刷新或网络问题丢掉。
3. 多张参考图的顺序不能乱
在多图和关键帧模式里,图片顺序是有含义的。
比如两张图片分别代表首帧和尾帧,如果后台把顺序调换,生成结果就会发生变化。
现在会优先按照用户在提示词中 @ 图片的顺序组织请求。只通过连线加入、没有被引用的图片,再按原顺序放到后面。
这部分代码不复杂,但如果没有明确规则,同一张画布可能生成不同的请求。
4. 改节点时要考虑旧项目
项目数据保存在 SQLite 里。节点端口调整后,旧项目里保存的端口名称可能已经不存在。
后来增加了一份端口注册表,统一使用下面这类名称:
in:asset
out:image
out:video
旧端口也保留了迁移关系。打开历史项目时,先转换旧端口,再加载画布。
一些已经废弃的节点也会在加载时处理,避免旧项目直接打不开。
项目里是怎么使用 AI 的
这个项目的开发也用了不少 AI 工具。
大致流程是:
- 先写开发文档,列清楚功能范围、数据结构和验收条件。
- 用设计工具制作 HTML 交互原型。
- 根据原型实现 React 页面。
- 用编码助手修改具体功能和处理报错。
- 自己运行真实任务,再根据结果继续调整。
AI 写界面和基础代码比较快,但也容易一次加太多功能。
例如前面提到的 16 种节点,做出来不难,判断哪些节点应该保留反而更难。接口返回字段不一致、任务恢复、旧数据迁移这些问题,也都是实际运行后才逐步补上的。
我现在使用 AI 开发项目时,会尽量先把任务拆小,并且写清楚什么情况才算完成。
目前还没有做的功能
帧流现在可以完成图片到视频的基本流程,但还不是完整的视频制作工具。
下面这些功能还在计划中:
- 使用 LLM 自动拆解脚本和分镜。
- 根据分镜批量创建视频任务。
- 使用 ffmpeg 拼接多个视频片段。
- 接入对象存储,不再依赖 base64 传本地图片。
- 保存和复用常用工作流。
- 增加更完整的自动化测试。
最后的总结
这个项目最开始只是想把 Agnes 视频接口放进一张节点画布。
做完第一版后才发现,调用接口是最简单的部分。后面花时间最多的是任务保存、异常重试、本地素材、旧数据兼容和界面精简。
现在它已经可以作为一个本地工具使用,但还有不少功能没完成。
先把正在使用的流程做稳定,再继续增加新的节点。这是我做这个项目到现在最直接的感受。