视频项目模型.md 20 KB

视频项目模型

本文引用的文件

  • 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

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向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模型字段设计与约束

  • 主键与标识
    • id:自增主键
  • 用户与归属
    • userId:可空,关联用户
    • bookId/chapterId:可空,直接关联书籍与章节
  • 基础信息
    • title、description、coverUrl
  • 配置与产物
    • configJson:序列化后的VideoConfig
    • outputUrl:生成视频的访问地址
    • duration、fileSize:生成后回填
  • 状态与进度
    • status:枚举值draft/processing/completed/failed
    • progress:百分比
    • errorMsg:失败原因
  • 时间戳
    • createdAt、updatedAt

字段约束与校验要点

  • 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

生命周期状态机

状态流转

  • draft → processing:开始生成
  • processing → completed:生成成功
  • processing → failed:生成异常
  • draft → failed:配置缺失或素材不可用

    stateDiagram-v2
    [*] --> 草稿
    草稿 --> 处理中 : "开始生成"
    处理中 --> 完成 : "成功"
    处理中 --> 失败 : "异常"
    完成 --> [*]
    失败 --> [*]
    

图表来源

  • 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(兼容性)
  • 音频编码
    • 编码器:aac
    • 码率:192k
  • 滤镜链
    • Ken Burns:zoompan(动态缩放)
    • 缩放与填充:scale + pad(保持比例并居中)
    • 字幕:drawtext(按位置渲染)
  • 混音
    • amix:将主音频与BGM混合,取最长时长

章节来源

  • 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或容器资源限制
  • 异步化
    • 将生成放入队列,避免阻塞HTTP请求
  • 缓存与复用
    • 重复素材可缓存至临时目录,减少网络下载
  • 并发控制
    • 限制同一用户的并发生成数量,防止资源争抢
  • CDN与分发
    • 使用CDN加速public/videos下的视频资源

故障排查指南

常见问题与定位

  • 项目不存在或状态异常
    • 检查项目ID与状态;避免重复触发生成
  • 缺少必要素材
    • 确认images与audio.url存在且可访问
  • FFmpeg命令失败
    • 查看stderr日志;确认系统已安装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