Files
AiVideo/ARCHITECTURE.md
2026-03-25 13:43:00 +08:00

6.8 KiB
Raw Permalink Blame History

AiVideo Architecture Guide

1. 项目目标与当前定位

该项目是一个 AIGC 视频 POC核心能力是把用户 prompt 转成三分镜短视频,并通过 Node API 流式返回进度与结果。当前实现已经覆盖:

  • 分镜生成(script
  • 单分镜润色(refine
  • 视频渲染与合成(render
  • task_id 级别隔离输出(outputs/{task_id}/
  • Docker 内置 ComfyUI + Node + Python 联动
  • 启动时自检Comfy 可达性 + workflow/节点约束)

整体设计是「Node 作为编排/网关Python 作为生成引擎」。

2. 目录与职责

  • server/Node API + SSE 网关 + 启动自检入口
  • engine/Python 生成引擎LLM 分镜、TTS、Comfy、MoviePy 合成)
  • scripts/Comfy 连通性和 workflow 约束检查
  • configs/config.yaml运行时配置Comfy 地址、模型、workflow 映射等)
  • docker-compose.ymlaivideo + comfyui 双服务部署
  • dev.sh:本地开发启动/日志/重建封装
  • outputs/{task_id}/:任务级产物目录(分镜、润色结果、最终视频)

3. 运行架构(容器级)

  • aivideo 服务
    • 运行 Node (server/index.js)
    • Node 通过 spawn 调用 Pythonpython -m engine.main
    • 对外暴露 3000
  • comfyui 服务
    • 默认镜像:jamesbrink/comfyui:latest
    • 对外暴露 8188
    • 挂载 ./ComfyUI/* 到容器 /comfyui/*
  • 服务连接
    • aivideo 通过 http://comfyui:8188 访问 ComfyUI API容器内 DNS

4. 应用架构(进程级)

4.1 Node 层(server/index.js

职责:

  • 提供 HTTP/SSE 接口
  • 统一生成 task_id 并创建输出目录
  • 把请求参数透传给 Python 引擎
  • 把 Python stdout 协议行转成 SSE 事件
  • 启动前执行自检(check_comfy.py + inspect_comfy_node.py

主要接口:

  • GET /api/health
  • GET /api/scriptSSE
  • POST /api/refineJSON
  • POST /api/renderSSE
  • GET /api/static/...(输出视频静态托管,禁缓存)

并发策略(当前):

  • 渲染接口使用单全局锁 isBusy(同一时刻只允许一个渲染)

4.2 Python 引擎层(engine/main.py

职责:

  • 解析参数并分发 stepscript/refine/render
  • 处理全局风格与角色注入
  • 与 OpenAI、ComfyUI、TTS、MoviePy 协同
  • 按协议输出进度与结构化结果(SCENE_JSONPROGRENDER_DONE

子模块职责:

  • engine/script_gen.pyLLM 分镜生成与润色
  • engine/audio_gen.pyEdge TTS 合成旁白
  • engine/comfy_client.py:提交 workflow、轮询 history、提取产物
  • engine/video_editor.py:字幕叠加 + 转场 + 最终拼接
  • engine/config.pyYAML 配置读取

5. 核心流程

5.1 Script 生成

  1. Node 收到 GET /api/script
  2. 生成 task_id,创建 outputs/{task_id}
  3. Node spawn Python --step script
  4. Python 调 LLM 生成三分镜(无 key 时可 mock fallback
  5. Python 输出多行 SCENE_JSON ...
  6. Node 将其转发为 SSE scene 事件

5.2 Refine 润色

  1. Node 收到 POST /api/refine
  2. 透传当前 scenes/scene 到 Python stdin
  3. Python 调 LLM 润色指定分镜
  4. 返回 SCENE_JSONNode 组装 JSON 响应

5.3 Render 渲染

  1. Node 收到 POST /api/renderSSE
  2. 全局 isBusy 判定是否可渲染
  3. Python 先做 TTS并发再逐分镜调 Comfy
  4. 收集视频 + 音频MoviePy 合成 final.mp4
  5. Python 输出 PROG 进度与 RENDER_DONE
  6. Node 转发 SSE 完成事件

6. 关键设计约束

  • task_id 必须贯穿 API 与引擎,保证产物隔离
  • 启动自检失败时服务不启动fail fast
  • workflow 参数注入基于:
    • 明确 node_id
    • class_type fallback 自动定位
  • 全局风格/角色必须双重注入:
    • LLM prompt 约束
    • 渲染前 image_prompt 装饰character + style + scene

7. 当前架构优势

  • 职责拆分清晰Node 编排、Python 算法,边界明确
  • 可观测性较好SSE 实时进度 + 结构化协议行
  • 生产思路正确:自检机制避免“半可用”状态
  • 兼容能力强mock 路径可脱离 Comfy/LLM 快速调通

8. 主要架构风险与优化方向

P0优先处理

  1. 作业状态只在内存

    • 问题Node 重启后任务状态丢失,前端不可恢复
    • 建议引入任务元数据存储SQLite/Redis记录状态机queued/running/succeeded/failed
  2. 单点渲染锁 isBusy

    • 问题:无法扩展并发;请求高峰体验差
    • 建议:升级为队列模型(本地队列或 Redis/BullMQ支持排队和取消
  3. SSE 协议基于字符串前缀

    • 问题:协议演进脆弱,难版本化
    • 建议:统一 JSON line 协议(字段:type, task_id, ts, payload, version

P1中期

  1. 配置与环境耦合较松散

    • 建议:增加 config schema 校验pydantic/JSON schema启动即检查缺项与类型
  2. Comfy 产物识别依赖 history + 文件存在

    • 建议扩展更稳定的完成判定WebSocket event 或更严格 history 状态判断)
  3. 缺少全链路 trace id

    • 建议:在 Node/Python/Comfy 请求中统一注入 task_idrequest_id

P2长期

  1. 引擎内聚度可再提升

    • 建议:把 script/refine/render 拆成独立 use-case 模块CLI 仅作参数适配
  2. 测试体系不足

    • 建议:
    • 单元测试config、workflow 注入、scene 解析
    • 集成测试mock 渲染链路
    • 冒烟测试Docker 启动 + /api/health

9. 推荐重构路线4 周)

  • 第 1 周:任务状态持久化 + API 状态查询接口(/api/tasks/:id
  • 第 2 周:渲染队列化(先单 worker替换 isBusy
  • 第 3 周统一事件协议JSON line + version前后端同时改
  • 第 4 周:补测试与可观测(结构化日志、错误码、性能指标)

10. 建议新增接口(便于运维和前端)

  • GET /api/tasks/:task_id:任务状态与阶段信息
  • POST /api/tasks/:task_id/cancel:取消任务
  • GET /api/tasks/:task_id/artifacts:列出产物路径和类型
  • GET /api/system/checks:最近一次自检结果

11. 性能优化清单(先易后难)

  • TTS 结果按文本 hash 缓存,避免重复合成
  • 分镜视频生成支持失败重试与断点继续
  • MoviePy 合成参数按场景切换(开发 veryfast,生产 medium/slow
  • outputs/ 增加清理策略TTL + 最大磁盘占用阈值)

12. 你下一步可以直接做的事

  1. 先落地任务持久化和状态查询(收益最大、侵入最小)
  2. 再把 isBusy 改为队列(并保留单 worker
  3. 最后统一事件协议,减少前后端耦合与兼容风险

这份文档的目的不是重写现有实现,而是在保留当前可用链路的前提下,把系统逐步推进到可扩展的生产形态。