媒体处理服务
本文引用的文件
- server/src/app.ts
- server/src/config/index.ts
- server/src/modules/audioedit/audioedit.controller.ts
- server/src/modules/audioedit/audioedit.service.ts
- server/src/services/ffmpeg.processor.ts
- server/src/services/storage.service.ts
- server/src/services/queue.service.ts
- server/src/services/memory-queue.ts
- server/src/services/redis.service.ts
- server/src/modules/book-generator/book-queue.processor.ts
- server/src/middleware/rate-limiter.ts
- deploy-package/server/modules/templates/templates.controller.js
- deploy-package/server/modules/templates/templates.service.js
- docs/TTS成本分析报告.md
目录
- 引言
- 项目结构
- 核心组件
- 架构总览
- 详细组件分析
- 依赖关系分析
- 性能考量
- 故障排查指南
- 结论
- 附录
引言
本技术文档面向媒体处理服务,聚焦音频编辑能力、模板管理、批量处理机制与并发架构。文档系统性阐述以下主题:
- 音频编辑:裁剪、合并、信息查询等接口与实现要点
- 模板管理:模板分类、增删改查、内容渲染与扩展
- 批量处理:队列服务、并发控制、进度跟踪与错误恢复
- 音频处理算法:格式转换、采样率调整、音量标准化、降噪与混响思路
- 资源调度与内存优化:存储抽象、临时文件清理、Redis 缓存与回退策略
- 质量评估与成本分析:TTS 成本模型、套餐定价与成本控制
项目结构
后端采用 Koa 应用,模块化组织路由与服务层,统一通过 app.ts 注册路由与中间件,并在启动时初始化队列、存储与监控。
graph TB
A["应用入口<br/>server/src/app.ts"] --> B["中间件与路由注册"]
B --> C["音频编辑模块<br/>audioedit.controller.ts"]
B --> D["模板管理模块<br/>templates.controller.js"]
B --> E["书籍生成队列处理器<br/>book-queue.processor.ts"]
B --> F["TTS/视频生成相关路由<br/>app.ts 路由挂载"]
subgraph "服务层"
G["FFmpeg 处理器<br/>ffmpeg.processor.ts"]
H["存储服务<br/>storage.service.ts"]
I["队列服务<br/>queue.service.ts"]
J["内存队列回退<br/>memory-queue.ts"]
K["Redis 服务<br/>redis.service.ts"]
end
C --> G
C --> H
E --> I
E --> J
I --> K
图表来源
- server/src/app.ts:100-128
- server/src/modules/audioedit/audioedit.controller.ts:10-101
- server/src/services/ffmpeg.processor.ts:24-379
- server/src/services/storage.service.ts:13-278
- server/src/services/queue.service.ts:48-347
- server/src/services/memory-queue.ts:17-119
- server/src/services/redis.service.ts:3-274
- server/src/modules/book-generator/book-queue.processor.ts:48-83
章节来源
- server/src/app.ts:100-130
核心组件
- 音频编辑控制器与服务:提供裁剪、合并、信息查询等接口与模拟实现
- FFmpeg 处理器:封装下载、合并、转码、裁剪、音量调整、时长探测、音视频混合等操作
- 存储服务:统一 OSS/本地存储,支持上传、下载、删除、签名 URL、本地目录管理
- 队列服务:基于 Bull 的 Redis 队列,提供任务添加、状态查询、进度回调与统计
- 内存队列:Redis 不可用时的回退实现,维持基本并发与处理
- Redis 服务:连接管理、键值操作、健康检测与断开
- 书籍生成队列处理器:任务处理器、并发控制、进度事件与中断恢复
- 速率限制中间件:基于内存或 Redis 的限流器,支持多场景限流
- 模板管理:模板分类、增删改查、内容渲染
章节来源
- server/src/modules/audioedit/audioedit.controller.ts:10-101
- server/src/modules/audioedit/audioedit.service.ts:4-49
- server/src/services/ffmpeg.processor.ts:24-379
- server/src/services/storage.service.ts:13-278
- server/src/services/queue.service.ts:48-347
- server/src/services/memory-queue.ts:17-119
- server/src/services/redis.service.ts:3-274
- server/src/modules/book-generator/book-queue.processor.ts:16-83
- server/src/middleware/rate-limiter.ts:17-120
- deploy-package/server/modules/templates/templates.controller.js:13-167
- deploy-package/server/modules/templates/templates.service.js:4-103
架构总览
媒体处理服务采用“控制器-服务-处理器-存储”的分层架构,结合队列与 Redis 实现高并发与可扩展的批处理能力。FFmpeg 处理器负责具体音视频操作,存储服务屏蔽 OSS/本地差异,队列服务保障任务有序执行与进度跟踪。
graph TB
subgraph "接入层"
R["Koa 路由<br/>app.ts"]
AC["音频编辑控制器<br/>audioedit.controller.ts"]
TC["模板控制器<br/>templates.controller.js"]
end
subgraph "领域服务"
AS["音频编辑服务<br/>audioedit.service.ts"]
QS["队列服务<br/>queue.service.ts"]
MQ["内存队列<br/>memory-queue.ts"]
RS["Redis 服务<br/>redis.service.ts"]
FS["FFmpeg 处理器<br/>ffmpeg.processor.ts"]
SS["存储服务<br/>storage.service.ts"]
end
subgraph "生成与处理"
BG["书籍生成队列处理器<br/>book-queue.processor.ts"]
end
R --> AC --> AS
R --> TC
AS --> FS
AS --> SS
QS --> RS
QS --> MQ
BG --> QS
BG --> MQ
BG --> FS
BG --> SS
图表来源
- server/src/app.ts:100-128
- server/src/modules/audioedit/audioedit.controller.ts:10-101
- server/src/modules/audioedit/audioedit.service.ts:4-49
- server/src/services/queue.service.ts:48-347
- server/src/services/memory-queue.ts:17-119
- server/src/services/redis.service.ts:3-274
- server/src/services/ffmpeg.processor.ts:24-379
- server/src/services/storage.service.ts:13-278
- server/src/modules/book-generator/book-queue.processor.ts:48-83
详细组件分析
音频编辑模块
- 裁剪:接收音频 ID 与起止时间,校验参数合法性后返回模拟结果
- 合并:接收音频 ID 列表与顺序数组,返回合并结果与估算时长
信息查询:返回音频时长、大小、格式、码率等基础信息
sequenceDiagram
participant Client as "客户端"
participant Ctrl as "音频编辑控制器"
participant Svc as "音频编辑服务"
Client->>Ctrl : POST /api/audio/trim
Ctrl->>Ctrl : 参数校验
Ctrl->>Svc : trimAudio(audioId, startTime, endTime)
Svc-->>Ctrl : 返回裁剪结果
Ctrl-->>Client : {code, message, data}
Client->>Ctrl : POST /api/audio/merge
Ctrl->>Ctrl : 参数校验
Ctrl->>Svc : mergeAudios(audioIds, order)
Svc-->>Ctrl : 返回合并结果
Ctrl-->>Client : {code, message, data}
图表来源
- server/src/modules/audioedit/audioedit.controller.ts:10-80
- server/src/modules/audioedit/audioedit.service.ts:8-34
章节来源
- server/src/modules/audioedit/audioedit.controller.ts:10-101
- server/src/modules/audioedit/audioedit.service.ts:4-49
FFmpeg 处理器
图表来源
- server/src/services/ffmpeg.processor.ts:69-122
- server/src/services/ffmpeg.processor.ts:346-375
章节来源
- server/src/services/ffmpeg.processor.ts:24-379
存储服务
- 统一 OSS/本地存储接口:上传音频、视频、封面与通用文件
- 支持 Buffer 上传与下载,删除单文件/目录
- 生成签名 URL(OSS),本地存储直接返回访问路径
- 本地存储目录结构:/uploads/{category}/{id}/filename
存储类型可通过环境变量切换
classDiagram
class StorageService {
-storageType : "oss"|"local"
+setStorageType(type)
+getStorageType() : "oss"|"local"
+uploadAudio(localPath, audioId) : string
+uploadVideo(localPath, videoId) : string
+uploadCover(localPath, bookId) : string
+uploadFile(localPath, category, id) : string
+uploadBuffer(buffer, objectKey, contentType?) : string
+deleteFile(url)
+deleteDirectory(prefix, id)
+downloadFile(url) : Buffer
+getSignedUrl(url, expires?) : string
+testConnection() : boolean
}
图表来源
- server/src/services/storage.service.ts:13-278
章节来源
- server/src/services/storage.service.ts:13-278
队列服务与并发控制
- 队列类型:音频生成、视频生成、书籍生成、邮件发送
- 任务状态:等待、活跃、完成、失败、延迟
- Redis 队列优先,失败则回退内存队列
- 进度回调:支持注册回调并在任务状态变更时触发
统计与运维:获取队列统计、清空、暂停/恢复、优雅关闭
sequenceDiagram
participant Caller as "调用方"
participant QS as "队列服务"
participant Redis as "Redis/Bull"
participant MQ as "内存队列"
Caller->>QS : addTask(类型, 数据)
alt Redis 可用
QS->>Redis : queue.add(数据)
Redis-->>QS : 返回 jobId
else Redis 不可用
QS->>MQ : memoryQueue.add(类型, 数据)
MQ-->>QS : 返回 jobId
end
QS-->>Caller : jobId
图表来源
- server/src/services/queue.service.ts:131-160
- server/src/services/memory-queue.ts:26-46
章节来源
- server/src/services/queue.service.ts:48-347
- server/src/services/memory-queue.ts:17-119
书籍生成队列处理器与中断恢复
- 处理器:并发 3,捕获进度、完成、失败事件,更新书籍状态
中断恢复:启动时扫描处于生成阶段的书籍,重新入队继续生成
sequenceDiagram
participant Boot as "服务启动"
participant BG as "书籍队列处理器"
participant QS as "队列服务"
participant DB as "数据库"
Boot->>BG : initBookGenerationQueue()
Boot->>BG : resumeInterruptedTasks()
BG->>DB : 查询生成中书籍
DB-->>BG : 返回中断任务
loop 逐个恢复
BG->>QS : addBookGenerationTask(任务数据)
QS-->>BG : 返回 jobId
end
图表来源
- server/src/modules/book-generator/book-queue.processor.ts:48-83
- server/src/modules/book-generator/book-queue.processor.ts:88-124
章节来源
- server/src/modules/book-generator/book-queue.processor.ts:16-83
- server/src/modules/book-generator/book-queue.processor.ts:88-124
模板管理系统
- 模板分类与列表:支持按分类筛选与总数统计
- CRUD:创建、更新、删除、按 ID 查询
内容渲染:模板字符串占位符替换(示例:{{xxx}})
flowchart TD
A["GET /api/templates"] --> B{"是否带分类参数"}
B -- 是 --> C["按分类过滤模板"]
B -- 否 --> D["返回全部模板"]
E["GET /api/templates/categories"] --> F["返回分类及数量"]
G["CRUD 操作"] --> H["创建/更新/删除/查询"]
图表来源
- deploy-package/server/modules/templates/templates.controller.js:13-167
- deploy-package/server/modules/templates/templates.service.js:4-103
章节来源
- deploy-package/server/modules/templates/templates.controller.js:13-167
- deploy-package/server/modules/templates/templates.service.js:4-103
速率限制中间件
- 支持内存与 Redis 两种限流器,自动选择
- 提供 API 全局限流、登录限流、短信验证码限流、TTS 限流、文件上传限流
- 429 响应包含 Retry-After 与提示信息
章节来源
- server/src/middleware/rate-limiter.ts:17-120
依赖关系分析
图表来源
- server/src/modules/audioedit/audioedit.controller.ts:10-101
- server/src/modules/audioedit/audioedit.service.ts:4-49
- server/src/services/ffmpeg.processor.ts:24-379
- server/src/services/storage.service.ts:13-278
- server/src/services/queue.service.ts:48-347
- server/src/services/memory-queue.ts:17-119
- server/src/services/redis.service.ts:3-274
- server/src/modules/book-generator/book-queue.processor.ts:48-83
- server/src/app.ts:100-128
章节来源
- server/src/app.ts:100-130
性能考量
- 并发与超时:队列任务针对不同场景设置超时(音频 5 分钟、视频 10 分钟、书籍 2 小时)
- 临时文件管理:FFmpeg 处理器在 finally 中清理临时文件,避免磁盘占用
- 存储切换:通过环境变量切换 OSS/本地,便于测试与生产解耦
- 限流策略:对高频接口进行限流,防止突发流量导致资源耗尽
- 进度回调:任务进度通过队列事件上报,前端可实时展示
章节来源
- server/src/services/queue.service.ts:166-190
- server/src/services/ffmpeg.processor.ts:109
- server/src/services/storage.service.ts:17-28
- server/src/middleware/rate-limiter.ts:77-120
故障排查指南
- 队列不可用:Redis 不可用时自动回退内存队列,检查 Redis 连接状态与日志
- 任务失败:查看队列失败事件与书籍状态更新,定位具体环节
- 存储异常:确认存储类型与路径,OSS 需检查凭证与网络连通性
- 临时文件未清理:检查清理逻辑与权限,必要时手动清理临时目录
- 限流触发:根据 429 响应头 Retry-After 调整请求节奏
章节来源
- server/src/services/queue.service.ts:53-66
- server/src/modules/book-generator/book-queue.processor.ts:66-74
- server/src/services/ffmpeg.processor.ts:346-375
- server/src/middleware/rate-limiter.ts:52-71
结论
媒体处理服务以清晰的分层架构与可扩展的队列机制为基础,结合 FFmpeg 处理器与统一存储抽象,实现了音频编辑、模板管理与批量处理的核心能力。通过 Redis/内存双轨队列与进度回调,系统具备良好的并发控制与可观测性。建议在生产环境中完善错误恢复策略、引入更细粒度的质量评估指标与成本控制模块。
附录
处理流程说明(音频编辑)
- 裁剪:校验参数 → 下载 → 裁剪 → 上传 → 返回结果
- 合并:校验参数 → 下载 → 构建列表 → 合并 → 上传 → 返回结果
- 信息查询:返回预设信息(时长、大小、格式、码率)
章节来源
- server/src/modules/audioedit/audioedit.controller.ts:10-101
- server/src/modules/audioedit/audioedit.service.ts:8-48
- server/src/services/ffmpeg.processor.ts:69-122
参数配置指南
- 存储类型:通过环境变量切换 OSS/本地
- 队列超时:按任务类型配置超时时间
- 限流策略:按接口场景配置限流参数
章节来源
- server/src/services/storage.service.ts:17-28
- server/src/services/queue.service.ts:166-190
- server/src/middleware/rate-limiter.ts:77-120
质量评估标准与成本分析
- TTS 成本模型:AI 生成成本 + TTS 合成成本
- 套餐定价:覆盖成本与合理利润,提供多档位套餐
- 成本控制:每日使用限制、单次生成上限、服务商切换策略
章节来源
- docs/TTS成本分析报告.md:32-152
- docs/TTS成本分析报告.md:156-329