视频项目模型
本文引用的文件
- video-generator.types.ts
- video-generator.service.ts
- video-generator.controller.ts
- video-generator.ffmpeg.ts
- schema.prisma
- video-generator.ts
- video-generator-api.ts
- storage.service.ts
- websocket.service.ts
目录
- 简介
- 项目结构
- 核心组件
- 架构总览
- 详细组件分析
- 依赖分析
- 性能考虑
- 故障排查指南
- 结论
- 附录
简介
本文件面向AI有声书生成平台的“视频项目模型”,系统性阐述VideoProject模型的字段设计、生命周期状态机、与书籍/章节的关联关系、配置管理与参数传递机制,并提供创建、更新、查询、生成等操作的实现要点与最佳实践。同时给出视频文件的存储、压缩与分发策略,帮助开发者在前后端协同下高效构建视频生成能力。
项目结构
视频项目相关的核心代码分布在后端模块与前端类型/工具层:
- 后端模块
- 类型与数据模型:video-generator.types.ts
- 业务逻辑:video-generator.service.ts
- 控制器路由:video-generator.controller.ts
- FFmpeg封装:video-generator.ffmpeg.ts
- 数据库模型:Prisma schema.prisma
- 存储与分发:storage.service.ts
- 实时通知:websocket.service.ts
前端类型与API
- 类型定义:video-generator.ts
API封装:video-generator-api.ts
graph TB
subgraph "后端"
Types["类型定义<br/>video-generator.types.ts"]
Service["业务逻辑<br/>video-generator.service.ts"]
Controller["控制器<br/>video-generator.controller.ts"]
FFMPEG["FFmpeg封装<br/>video-generator.ffmpeg.ts"]
Prisma["数据库模型<br/>schema.prisma"]
Storage["存储服务<br/>storage.service.ts"]
WS["WebSocket服务<br/>websocket.service.ts"]
end
subgraph "前端"
FE_Types["类型定义<br/>video-generator.ts"]
FE_API["API封装<br/>video-generator-api.ts"]
end
FE_API --> Controller
Controller --> Service
Service --> FFMPEG
Service --> Prisma
Service --> Storage
Service --> WS
Types --> Service
Types --> Controller
Types --> FFMPEG
FE_Types --> FE_API
图表来源
- video-generator.types.ts:1-308
- video-generator.service.ts:1-556
- video-generator.controller.ts:1-244
- video-generator.ffmpeg.ts:1-300
- schema.prisma:194-218
- video-generator.ts:1-116
- video-generator-api.ts:1-188
章节来源
- video-generator.types.ts:1-308
- video-generator.service.ts:1-556
- video-generator.controller.ts:1-244
- video-generator.ffmpeg.ts:1-300
- schema.prisma:194-218
- video-generator.ts:1-116
- video-generator-api.ts:1-188
核心组件
- VideoProject模型(数据库)
- 字段与约束:见Prisma模型定义与类型定义
- 关联关系:与Book、BookChapter的外键关联
- 配置模型
- VideoConfig:包含图片、音频、背景音乐、字幕、视频参数、全局Ken Burns等
- 预设配置:portrait/landscape/square三套预设
- 生命周期状态
- draft、processing、completed、failed
- 生成流程
- 从章节音频优先获取,支持带/不带BGM两种合成路径
- 生成完成后回写项目与章节状态并推送WebSocket事件
章节来源
- schema.prisma:194-218
- video-generator.types.ts:75-93
- video-generator.types.ts:214-275
- video-generator.service.ts:154-312
架构总览
视频项目从“创建—生成—回写—分发”的全链路如下:
sequenceDiagram
participant FE as "前端应用"
participant API as "控制器<br/>video-generator.controller.ts"
participant Svc as "业务逻辑<br/>video-generator.service.ts"
participant DB as "数据库<br/>Prisma schema.prisma"
participant FF as "FFmpeg封装<br/>video-generator.ffmpeg.ts"
participant ST as "存储服务<br/>storage.service.ts"
participant WS as "WebSocket服务<br/>websocket.service.ts"
FE->>API : 创建视频项目
API->>Svc : createVideoProject()
Svc->>DB : 插入VideoProject(draft, progress=0)
DB-->>Svc : 新项目记录
Svc-->>API : 返回项目(含config解析)
API-->>FE : 成功响应
FE->>API : 开始生成
API->>Svc : generateVideoForProject()
Svc->>DB : 更新status=processing, progress=0
Svc->>FF : generateVideo()/generateVideoWithBgm()
FF-->>Svc : 输出视频元数据(duration,size)
Svc->>DB : 更新status=completed, progress=100, outputUrl,duration,fileSize
Svc->>DB : 若有chapterId, 更新章节videoUrl/videoDuration
Svc->>WS : 推送video_generation_complete事件
API-->>FE : 返回outputUrl/duration/fileSize
图表来源
- video-generator.controller.ts:44-129
- video-generator.service.ts:33-57
- video-generator.service.ts:157-312
- video-generator.ffmpeg.ts:23-118
- schema.prisma:194-218
- websocket.service.ts:81-86
详细组件分析
VideoProject模型字段设计与约束
- 主键与标识
- 用户与归属
- userId:可空,关联用户
- bookId/chapterId:可空,直接关联书籍与章节
- 基础信息
- title、description、coverUrl
- 配置与产物
- configJson:序列化后的VideoConfig
- outputUrl:生成视频的访问地址
- duration、fileSize:生成后回填
- 状态与进度
- status:枚举值draft/processing/completed/failed
- progress:百分比
- errorMsg:失败原因
- 时间戳
字段约束与校验要点
- configJson必须为合法JSON字符串;解析失败时应降级为空配置
- status默认draft,progress默认0
- outputUrl在生成完成后回填,需确保路径可访问
- 与Book/BookChapter的外键关系允许为NULL,便于独立项目或跨章节生成
章节来源
- schema.prisma:194-218
- video-generator.types.ts:97-115
- video-generator.types.ts:279-292
- video-generator.service.ts:39-56
生命周期状态机
状态流转
图表来源
- video-generator.types.ts:8-9
- video-generator.service.ts:171-173
- video-generator.service.ts:293-299
章节来源
- video-generator.types.ts:8-9
- video-generator.service.ts:157-312
配置模型与参数传递
- VideoConfig组成
- images:图片数组,每张含URL、显示时长、转场、可选Ken Burns
- audio:音频URL、起止截取、音量
- bgm:可选,含URL、音量、循环、淡入淡出
- subtitle:可选,文本、字号、颜色、背景色、位置、边距、样式
- video:分辨率、帧率、码率、格式
- kenburns:全局开关与缩放范围
- 预设配置
- portrait/landscape/square三套模板,便于快速生成
- 参数传递
- 前端通过VideoConfig对象提交
- 后端将VideoConfig序列化为configJson存库
- 生成时从数据库读取并反序列化为运行时配置
章节来源
- video-generator.types.ts:75-93
- video-generator.types.ts:214-275
- video-generator.types.ts:279-292
- video-generator-api.ts:10-26
与书籍/章节的关联关系
- 直接关联
- VideoProject.bookId → Book
- VideoProject.chapterId → BookChapter
- 生成时优先策略
- 若项目包含chapterId,则优先从章节表读取audioUrl与content,作为音频与字幕内容来源
- 回写行为
- 生成完成后,若存在chapterId,同步更新章节videoUrl与videoDuration
章节来源
- schema.prisma:211-212
- video-generator.service.ts:192-202
- video-generator.service.ts:271-283
视频生成流程与实现要点
- 输入准备
- 校验项目状态与必要素材(图片URL、音频URL)
- 将URL统一转换为本地文件路径并检查存在性
- 生成执行
- 无BGM:调用generateVideo
- 有BGM:先下载BGM至临时目录,再调用generateVideoWithBgm
- 多图轮播:generateSlideshow
- 输出与回写
- 生成完成后计算duration与fileSize,回写数据库
- 若关联章节,同步更新章节视频信息
- 推送WebSocket事件,通知前端
错误处理
- 捕获异常,回写status=failed与errorMsg
推送失败事件
flowchart TD
Start(["开始生成"]) --> CheckProj["读取项目与状态"]
CheckProj --> StatusOK{"状态为draft/processing?"}
StatusOK --> |processing| ErrBusy["返回已在生成中"]
StatusOK --> |draft| UpdateProc["更新为processing(progress=0)"]
UpdateProc --> LoadCfg["加载配置(configJson)"]
LoadCfg --> HasMedia{"图片/音频可用?"}
HasMedia --> |否| ErrMedia["返回缺少素材"]
HasMedia --> |是| Paths["转换URL为本地路径并校验存在"]
Paths --> GenType{"是否包含BGM?"}
GenType --> |是| GenBGM["下载BGM并生成(带BGM)"]
GenType --> |否| Gen["生成(无BGM)"]
GenBGM --> WriteBack["回写结果: url,duration,size,status=completed,progress=100"]
Gen --> WriteBack
WriteBack --> UpdateChapter{"是否关联章节?"}
UpdateChapter --> |是| UpdChap["更新章节videoUrl/videoDuration"]
UpdateChapter --> |否| SkipChap["跳过"]
UpdChap --> Notify["推送WebSocket事件"]
SkipChap --> Notify
Notify --> End(["完成"])
ErrBusy --> End
ErrMedia --> End
图表来源
- video-generator.service.ts:164-312
- video-generator.ffmpeg.ts:23-118
- video-generator.ffmpeg.ts:123-199
章节来源
- video-generator.service.ts:154-312
- video-generator.ffmpeg.ts:1-300
FFmpeg参数与压缩策略
- 视频编码
- 编码器:libx264
- 预设:fast
- CRF:18(质量优先)
- 像素格式:yuv420p(兼容性)
- 音频编码
- 滤镜链
- Ken Burns:zoompan(动态缩放)
- 缩放与填充:scale + pad(保持比例并居中)
- 字幕:drawtext(按位置渲染)
- 混音
章节来源
- video-generator.ffmpeg.ts:38-98
- video-generator.ffmpeg.ts:169-186
存储、压缩与分发策略
- 本地存储
- 输出视频存放于public/videos,访问路径为/videos/{filename}
- 素材下载至temp/images或temp/audio临时目录
- OSS存储(可选)
- 通过storage.service.ts统一抽象,支持OSS与本地无缝切换
- 提供上传/下载/删除/签名URL等能力
- 压缩与分发
- 采用H.264+AAC组合,CRF 18兼顾画质与体积
- 生成完成后回写duration与fileSize,便于前端展示与统计
- 可结合CDN加速公开视频资源
章节来源
- video-generator.ffmpeg.ts:11-18
- video-generator.service.ts:236-237
- storage.service.ts:1-278
API与操作示例(路径指引)
- 创建视频项目
- 后端:POST /api/video/projects
- 前端:createVideoProject()
- 查询项目列表
- 后端:GET /api/video/projects
- 前端:getVideoProjects()
- 获取项目详情
- 后端:GET /api/video/projects/:id
- 前端:getVideoProject()
- 更新项目
- 后端:PUT /api/video/projects/:id
- 前端:updateVideoProject()
- 删除项目
- 后端:DELETE /api/video/projects/:id
- 前端:deleteVideoProject()
- 开始生成
- 后端:POST /api/video/projects/:id/generate
- 前端:generateVideo()
- 获取生成进度
- 后端:GET /api/video/projects/:id/status
- 前端:getGenerateProgress()
- 从书籍生成项目
- 后端:POST /api/video/books/:bookId/generate
- 前端:createVideoProjectFromBook()
章节来源
- video-generator.controller.ts:28-140
- video-generator-api.ts:78-187
依赖分析
- 模块耦合
- controller依赖service;service依赖types、ffmpeg、prisma、storage、websocket
- ffmpeg封装与配置解耦,便于扩展其他合成引擎
- 外部依赖
- fluent-ffmpeg:视频合成
- Prisma:数据库ORM
- WebSocket:实时事件推送
潜在风险
- 生成流程阻塞IO,建议引入队列异步化
FFmpeg命令行依赖系统环境,需容器化部署保证一致性
graph LR
Controller["控制器"] --> Service["业务逻辑"]
Service --> Types["类型定义"]
Service --> FFMPEG["FFmpeg封装"]
Service --> Prisma["Prisma模型"]
Service --> Storage["存储服务"]
Service --> WS["WebSocket服务"]
图表来源
- video-generator.controller.ts:1-244
- video-generator.service.ts:1-556
- video-generator.types.ts:1-308
- video-generator.ffmpeg.ts:1-300
- schema.prisma:1-470
- storage.service.ts:1-278
- websocket.service.ts:1-136
章节来源
- video-generator.controller.ts:1-244
- video-generator.service.ts:1-556
性能考虑
- IO与CPU瓶颈
- FFmpeg合成为CPU密集型任务,建议使用专用GPU或容器资源限制
- 异步化
- 缓存与复用
- 并发控制
- CDN与分发
- 使用CDN加速public/videos下的视频资源
故障排查指南
常见问题与定位
- 项目不存在或状态异常
- 缺少必要素材
- FFmpeg命令失败
- WebSocket未收到事件
- 检查/upgrade路径与clientId参数;确认wss实例已初始化
- 存储异常
- 若使用OSS,检查凭证与Bucket权限;本地存储检查目录权限
章节来源
- video-generator.service.ts:166-173
- video-generator.service.ts:204-206
- video-generator.service.ts:291-311
- websocket.service.ts:102-133
- storage.service.ts:252-272
结论
VideoProject模型以清晰的字段设计与严格的生命周期管理为基础,配合灵活的配置体系与稳健的FFmpeg合成流程,实现了从书籍章节到视频的自动化生产。通过Prisma的外键约束与WebSocket的实时通知,系统在数据一致性与用户体验上取得平衡。建议后续引入队列异步化与容器化部署,进一步提升稳定性与可扩展性。
附录
- 关键实现路径参考
- VideoProject创建:video-generator.service.ts:33-57
- 视频生成主流程:video-generator.service.ts:157-312
- FFmpeg合成实现:video-generator.ffmpeg.ts:23-118
- WebSocket事件推送:websocket.service.ts:81-86
- 前端API封装:video-generator-api.ts:78-187