架构说明
本文档描述 ArcReel 的稳定架构边界、主要数据流和扩展点。它不替代代码级 API 文档,也不记录临时实现计划。
1. 架构目标
ArcReel 的核心目标不是绑定某个模型,而是提供一条:
- 可编排;
- 可审核;
- 可中断恢复;
- 可替换供应商;
- 可追踪成本;
- 可保留版本;
- 可继续后期编辑
的 AI 视频生产流水线。
2. 总体架构
3. 前端层
前端使用 React 19 和 TypeScript,主要职责包括:
- 项目列表和创建;
- 项目工作台;
- 素材预览;
- AI 助手对话;
- 任务状态;
- 费用统计;
- 设置和供应商管理;
- 版本历史;
- 项目导入和导出。
前端不应直接处理供应商密钥或绕过后端调用模型。
4. API 与实时状态
FastAPI 提供:
- REST API;
- 认证;
- 项目和资产操作;
- 任务创建与查询;
- Agent 对话;
- Agent 与项目事件 SSE;
- 生成任务查询;
- 外部 API Key 接入。
Agent 回复通过助手 SSE 流式返回;项目终态变化通过项目事件 SSE 触发界面刷新,生成任务的中间状态和断线兜底由任务查询补充。部署反向代理时必须关闭 SSE 代理缓冲并设置足够长的读取超时。
5. Agent Runtime
Agent Runtime 基于 Claude Agent SDK,并采用“编排 Skill + 聚焦 Subagent”的结构。
5.1 编排 Skill
负责:
- 判断项目当前状态;
- 选择下一步;
- 调用确定性工具;
- 分发 Subagent;
- 控制阶段边界;
- 在需要时等待用户确认。
编排层不应承担所有内容推理,否则会让主上下文快速膨胀。
5.2 聚焦 Subagent
每个 Subagent 聚焦一个任务,例如:
- 角色、场景和道具提取;
- 说书片段拆分;
- 剧集动画剧本规范化;
- 单集结构化剧本;
- 资产生成。
大量小说原文和中间推理尽量保留在 Subagent 内部,主 Agent 接收摘要和结果引用。
5.3 确定性工具
确定性操作更适合由工具或 Skill 执行,例如:
- 读取和写入项目文件;
- 创建任务;
- 查询状态;
- 生成结构化文件;
- 合成视频;
- 导出归档。
这类操作不应反复交给语言模型自由生成。
6. 应用服务层
应用服务协调:
- 项目;
- 剧集;
- 角色、场景和道具;
- 分镜;
- 媒体任务;
- 文件上传;
- 项目导入和导出;
- 剪映草稿;
- 费用和用量;
- 诊断信息。
服务层应依赖稳定协议,而不是直接向上层泄漏供应商 SDK 的具体对象。
7. 供应商抽象
ArcReel 使用:
TextBackendImageBackendVideoBackendAudioBackend
统一不同供应商的调用方式。
抽象层负责统一:
- 请求输入;
- 任务创建;
- 任务轮询;
- 输出位置;
- 统一错误;
- 用量信息;
- 费用计算入口。
供应商差异仍然存在,例如:
- 参数;
- 时长;
- 参考图数量;
- 异步任务状态;
- 失败语义;
- 计费单位。
正确做法是把这些差异封装在后端适配器和能力描述中,而不是假装所有供应商完全相同。
8. 生成任务队列
图像、视频和音频任务具有不同的成本和延迟特征,因此使用独立并发通道。
主要能力:
- 异步执行;
- RPM 限制;
- Image / Video / Audio 独立并发;
- 状态持久化;
- 中断恢复;
- 失败记录;
- 任务取消;
- 项目事件通知与任务状态刷新。
8.1 为什么需要持久化任务
模型调用可能持续数分钟。任务不能只存在于内存,否则进程重启会丢失:
- 已提交的远程任务 ID;
- 当前状态;
- 费用;
- 输出路径;
- 错误信息。
8.2 幂等性
创建和重试任务时应避免:
- 同一个镜头重复扣费;
- 远程任务已成功但本地重复提交;
- SSE 断开导致任务被认为失败;
- 重复点击产生相同的生成任务。
任务身份、持久化状态和供应商任务 ID 是处理这些问题的关键。
9. 项目和资产模型
ArcReel 的项目不仅是一条数据库记录,还包括文件系统中的媒体资产。
典型内容:
- 原始小说、剧本或商品素材;
- 项目配置;
- 角色、场景和道具定义;
- 参考图;
- 分镜;
- 视频片段;
- 音频;
- 合成输出;
- 历史版本;
- 导出归档。
应用数据根目录解析顺序:
ARCREEL_DATA_DIR- 兼容变量
AI_ANIME_PROJECTS - 默认
projects/
默认 SQLite 数据库也位于应用数据目录中。
10. 数据库
ArcReel 使用 SQLAlchemy 2.0 异步 ORM。
SQLite
适合:
- 个人体验;
- 本地开发;
- 轻量单实例。
默认使用 WAL、忙等待超时和外键约束。
PostgreSQL
适合:
- 生产环境;
- 较高并发;
- 长期运行;
- 更成熟的备份和恢复。
应用启动时运行 Alembic 迁移,将数据库升级到当前版本。
11. 版本历史
媒体生成具有不确定性,因此“重新生成”不应简单覆盖旧文件。
版本历史用于:
- 对比不同生成结果;
- 回滚;
- 保留已审核版本;
- 降低试错风险;
- 为项目归档提供完整上下文。
服务层应通过统一的资产版本接口操作,而不是让各供应商适配器自行决定如何覆盖文件。
12. 用量和费用
用量追踪跨越:
- 文本;
- 图片;
- 视频;
- TTS;
- 不同供应商;
- 不同币种;
- 预估和实际。
设计原则:
- 供应商适配器提供原始用量;
- 费用策略负责转换;
- 不同币种默认分开统计;
- 失败任务是否计费按供应商语义处理;
- ArcReel 记录不替代供应商官方账单。
13. 视频合成与剪映导出
媒体生成完成后有两种输出路径。
成片合成
使用 FFmpeg 处理:
- 片段拼接;
- 转场;
- 音频;
- 最终编码。
剪映草稿
导出可继续编辑的项目结构,用于:
- 调整片段;
- 编辑字幕;
- 替换配音;
- 增加音乐;
- 修改转场;
- 人工精修。
“可继续编辑”是 ArcReel 与只输出单个视频文件的生成工具之间的重要差异。
成片读取模型
浏览器预览、可编辑包下载和剪映草稿不各自推导声音、字幕或时长,而是共同消费成片读取模型。该模型固定已选视频版本、可选 TTS 版本、实际媒体时长、原音开关、字幕时序以及当前或历史状态;当前成片的字幕和呈现描述分别物化到 subtitles/ 与 presentations/,并登记到项目 Artifact Manifest。历史选择只读,不覆盖当前物化结果。
手动上传但尚无生成来源证明的视频走显式 raw-only 分支:保留原始视频,不猜测来源基点或新旧状态,不生成 TTS 和字幕,也不登记派生成片。这样三个输出入口仍共享同一选择,同时把来源未知与来源已验证区分开。
14. 认证和外部集成
ArcReel 提供:
- 用户名和密码登录;
- JWT;
arc-前缀 API Key;- 外部 Agent 同步对话端点。
API Key 应使用哈希存储,不应在创建后以明文持续返回。
外部 Agent 集成应:
- 最小化权限;
- 限制可访问的项目;
- 记录调用;
- 支持撤销;
- 避免把管理员密码提供给第三方平台。
15. 沙箱和安全边界
Agent 工具可能访问:
- 文件系统;
- 网络;
- 子进程;
- FFmpeg;
- Bash 工具。
ArcReel 在支持的环境中使用 bwrap 等机制限制这些能力。Docker Compose 为沙箱配置了额外权限,因此生产部署需要在功能和宿主机隔离之间做清晰取舍。
安全原则:
- 默认最小权限;
- 文件和网络白名单;
- 不挂载 Docker Socket;
- 不挂载不必要的宿主机路径;
- 对外只暴露反向代理;
- 使用 HTTPS;
- 定期更新;
- 把未知项目输入视为不可信数据。
16. 扩展一个新供应商
一个完整的新供应商接入通常需要:
- 定义能力和配置模型;
- 实现对应 Backend 协议;
- 统一错误类型;
- 实现同步或异步任务生命周期;
- 保存远程任务 ID;
- 解析输出和用量;
- 实现费用策略;
- 接入设置页;
- 添加单元和集成测试;
- 更新供应商文档;
- 验证取消、超时和重试。
不要只实现“成功路径”。视频供应商的轮询、超时、失败和重复提交往往比创建请求更复杂。
17. 扩展一个新工作流阶段
新阶段应回答:
- 输入是什么;
- 输出是什么;
- 是否可重复执行;
- 如何判断已完成;
- 是否需要用户确认;
- 失败后如何恢复;
- 是否产生费用;
- 是否需要版本历史;
- 主 Agent、Skill、Subagent 和确定性工具各负责什么。
一个阶段只有在完成条件可以由项目状态明确判断时,才能可靠地被编排和恢复。
18. 架构约束
建议长期保持以下约束:
- UI 不直接调用供应商;
- 业务服务不依赖供应商 SDK 返回对象;
- Agent 不直接拼接数据库 SQL;
- 供应商适配器不决定产品工作流;
- 重试不绕过幂等性;
- 费用记录与生成任务关联;
- 项目文件和数据库状态可共同备份;
- 具体模型名称不进入稳定领域接口;
- 长文本推理不无限累积在主 Agent 上下文;
- 确定性操作优先使用工具而不是自然语言生成。