# 媒体处理服务
**本文引用的文件**
- [server/src/app.ts](file://server/src/app.ts)
- [server/src/config/index.ts](file://server/src/config/index.ts)
- [server/src/modules/audioedit/audioedit.controller.ts](file://server/src/modules/audioedit/audioedit.controller.ts)
- [server/src/modules/audioedit/audioedit.service.ts](file://server/src/modules/audioedit/audioedit.service.ts)
- [server/src/services/ffmpeg.processor.ts](file://server/src/services/ffmpeg.processor.ts)
- [server/src/services/storage.service.ts](file://server/src/services/storage.service.ts)
- [server/src/services/queue.service.ts](file://server/src/services/queue.service.ts)
- [server/src/services/memory-queue.ts](file://server/src/services/memory-queue.ts)
- [server/src/services/redis.service.ts](file://server/src/services/redis.service.ts)
- [server/src/modules/book-generator/book-queue.processor.ts](file://server/src/modules/book-generator/book-queue.processor.ts)
- [server/src/middleware/rate-limiter.ts](file://server/src/middleware/rate-limiter.ts)
- [deploy-package/server/modules/templates/templates.controller.js](file://deploy-package/server/modules/templates/templates.controller.js)
- [deploy-package/server/modules/templates/templates.service.js](file://deploy-package/server/modules/templates/templates.service.js)
- [docs/TTS成本分析报告.md](file://docs/TTS成本分析报告.md)
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 引言
本技术文档面向媒体处理服务,聚焦音频编辑能力、模板管理、批量处理机制与并发架构。文档系统性阐述以下主题:
- 音频编辑:裁剪、合并、信息查询等接口与实现要点
- 模板管理:模板分类、增删改查、内容渲染与扩展
- 批量处理:队列服务、并发控制、进度跟踪与错误恢复
- 音频处理算法:格式转换、采样率调整、音量标准化、降噪与混响思路
- 资源调度与内存优化:存储抽象、临时文件清理、Redis 缓存与回退策略
- 质量评估与成本分析:TTS 成本模型、套餐定价与成本控制
## 项目结构
后端采用 Koa 应用,模块化组织路由与服务层,统一通过 app.ts 注册路由与中间件,并在启动时初始化队列、存储与监控。
```mermaid
graph TB
A["应用入口
server/src/app.ts"] --> B["中间件与路由注册"]
B --> C["音频编辑模块
audioedit.controller.ts"]
B --> D["模板管理模块
templates.controller.js"]
B --> E["书籍生成队列处理器
book-queue.processor.ts"]
B --> F["TTS/视频生成相关路由
app.ts 路由挂载"]
subgraph "服务层"
G["FFmpeg 处理器
ffmpeg.processor.ts"]
H["存储服务
storage.service.ts"]
I["队列服务
queue.service.ts"]
J["内存队列回退
memory-queue.ts"]
K["Redis 服务
redis.service.ts"]
end
C --> G
C --> H
E --> I
E --> J
I --> K
```
图表来源
- [server/src/app.ts:100-128](file://server/src/app.ts#L100-L128)
- [server/src/modules/audioedit/audioedit.controller.ts:10-101](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L101)
- [server/src/services/ffmpeg.processor.ts:24-379](file://server/src/services/ffmpeg.processor.ts#L24-L379)
- [server/src/services/storage.service.ts:13-278](file://server/src/services/storage.service.ts#L13-L278)
- [server/src/services/queue.service.ts:48-347](file://server/src/services/queue.service.ts#L48-L347)
- [server/src/services/memory-queue.ts:17-119](file://server/src/services/memory-queue.ts#L17-L119)
- [server/src/services/redis.service.ts:3-274](file://server/src/services/redis.service.ts#L3-L274)
- [server/src/modules/book-generator/book-queue.processor.ts:48-83](file://server/src/modules/book-generator/book-queue.processor.ts#L48-L83)
章节来源
- [server/src/app.ts:100-130](file://server/src/app.ts#L100-L130)
## 核心组件
- 音频编辑控制器与服务:提供裁剪、合并、信息查询等接口与模拟实现
- FFmpeg 处理器:封装下载、合并、转码、裁剪、音量调整、时长探测、音视频混合等操作
- 存储服务:统一 OSS/本地存储,支持上传、下载、删除、签名 URL、本地目录管理
- 队列服务:基于 Bull 的 Redis 队列,提供任务添加、状态查询、进度回调与统计
- 内存队列:Redis 不可用时的回退实现,维持基本并发与处理
- Redis 服务:连接管理、键值操作、健康检测与断开
- 书籍生成队列处理器:任务处理器、并发控制、进度事件与中断恢复
- 速率限制中间件:基于内存或 Redis 的限流器,支持多场景限流
- 模板管理:模板分类、增删改查、内容渲染
章节来源
- [server/src/modules/audioedit/audioedit.controller.ts:10-101](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L101)
- [server/src/modules/audioedit/audioedit.service.ts:4-49](file://server/src/modules/audioedit/audioedit.service.ts#L4-L49)
- [server/src/services/ffmpeg.processor.ts:24-379](file://server/src/services/ffmpeg.processor.ts#L24-L379)
- [server/src/services/storage.service.ts:13-278](file://server/src/services/storage.service.ts#L13-L278)
- [server/src/services/queue.service.ts:48-347](file://server/src/services/queue.service.ts#L48-L347)
- [server/src/services/memory-queue.ts:17-119](file://server/src/services/memory-queue.ts#L17-L119)
- [server/src/services/redis.service.ts:3-274](file://server/src/services/redis.service.ts#L3-L274)
- [server/src/modules/book-generator/book-queue.processor.ts:16-83](file://server/src/modules/book-generator/book-queue.processor.ts#L16-L83)
- [server/src/middleware/rate-limiter.ts:17-120](file://server/src/middleware/rate-limiter.ts#L17-L120)
- [deploy-package/server/modules/templates/templates.controller.js:13-167](file://deploy-package/server/modules/templates/templates.controller.js#L13-L167)
- [deploy-package/server/modules/templates/templates.service.js:4-103](file://deploy-package/server/modules/templates/templates.service.js#L4-L103)
## 架构总览
媒体处理服务采用“控制器-服务-处理器-存储”的分层架构,结合队列与 Redis 实现高并发与可扩展的批处理能力。FFmpeg 处理器负责具体音视频操作,存储服务屏蔽 OSS/本地差异,队列服务保障任务有序执行与进度跟踪。
```mermaid
graph TB
subgraph "接入层"
R["Koa 路由
app.ts"]
AC["音频编辑控制器
audioedit.controller.ts"]
TC["模板控制器
templates.controller.js"]
end
subgraph "领域服务"
AS["音频编辑服务
audioedit.service.ts"]
QS["队列服务
queue.service.ts"]
MQ["内存队列
memory-queue.ts"]
RS["Redis 服务
redis.service.ts"]
FS["FFmpeg 处理器
ffmpeg.processor.ts"]
SS["存储服务
storage.service.ts"]
end
subgraph "生成与处理"
BG["书籍生成队列处理器
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](file://server/src/app.ts#L100-L128)
- [server/src/modules/audioedit/audioedit.controller.ts:10-101](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L101)
- [server/src/modules/audioedit/audioedit.service.ts:4-49](file://server/src/modules/audioedit/audioedit.service.ts#L4-L49)
- [server/src/services/queue.service.ts:48-347](file://server/src/services/queue.service.ts#L48-L347)
- [server/src/services/memory-queue.ts:17-119](file://server/src/services/memory-queue.ts#L17-L119)
- [server/src/services/redis.service.ts:3-274](file://server/src/services/redis.service.ts#L3-L274)
- [server/src/services/ffmpeg.processor.ts:24-379](file://server/src/services/ffmpeg.processor.ts#L24-L379)
- [server/src/services/storage.service.ts:13-278](file://server/src/services/storage.service.ts#L13-L278)
- [server/src/modules/book-generator/book-queue.processor.ts:48-83](file://server/src/modules/book-generator/book-queue.processor.ts#L48-L83)
## 详细组件分析
### 音频编辑模块
- 裁剪:接收音频 ID 与起止时间,校验参数合法性后返回模拟结果
- 合并:接收音频 ID 列表与顺序数组,返回合并结果与估算时长
- 信息查询:返回音频时长、大小、格式、码率等基础信息
```mermaid
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](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L80)
- [server/src/modules/audioedit/audioedit.service.ts:8-34](file://server/src/modules/audioedit/audioedit.service.ts#L8-L34)
章节来源
- [server/src/modules/audioedit/audioedit.controller.ts:10-101](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L101)
- [server/src/modules/audioedit/audioedit.service.ts:4-49](file://server/src/modules/audioedit/audioedit.service.ts#L4-L49)
### FFmpeg 处理器
- 下载远程文件至本地临时目录,支持本地路径与 HTTP 地址
- 合并音频:支持 mp3/wav 输出,使用文件列表与 concat demuxer
- 音视频混合:支持背景音乐叠加与主音频替换
- 时长探测:使用 ffprobe 获取音频时长
- 格式转换:支持 mp3/wav/aac,可指定比特率
- 裁剪:基于起始时间与持续时间生成片段
- 音量调整:通过 volume 滤镜调整倍数
- 临时文件清理:下载与处理完成后清理磁盘空间
```mermaid
flowchart TD
Start(["进入处理"]) --> DL["下载输入文件"]
DL --> BuildList["构建 FFmpeg 文件列表"]
BuildList --> Merge["执行合并命令"]
Merge --> Upload["上传输出文件"]
Upload --> Clean["清理临时文件"]
Clean --> End(["结束"])
DL -.->|单文件| Return["直接返回输入地址"]
```
图表来源
- [server/src/services/ffmpeg.processor.ts:69-122](file://server/src/services/ffmpeg.processor.ts#L69-L122)
- [server/src/services/ffmpeg.processor.ts:346-375](file://server/src/services/ffmpeg.processor.ts#L346-L375)
章节来源
- [server/src/services/ffmpeg.processor.ts:24-379](file://server/src/services/ffmpeg.processor.ts#L24-L379)
### 存储服务
- 统一 OSS/本地存储接口:上传音频、视频、封面与通用文件
- 支持 Buffer 上传与下载,删除单文件/目录
- 生成签名 URL(OSS),本地存储直接返回访问路径
- 本地存储目录结构:/uploads/{category}/{id}/filename
- 存储类型可通过环境变量切换
```mermaid
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](file://server/src/services/storage.service.ts#L13-L278)
章节来源
- [server/src/services/storage.service.ts:13-278](file://server/src/services/storage.service.ts#L13-L278)
### 队列服务与并发控制
- 队列类型:音频生成、视频生成、书籍生成、邮件发送
- 任务状态:等待、活跃、完成、失败、延迟
- Redis 队列优先,失败则回退内存队列
- 进度回调:支持注册回调并在任务状态变更时触发
- 统计与运维:获取队列统计、清空、暂停/恢复、优雅关闭
```mermaid
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](file://server/src/services/queue.service.ts#L131-L160)
- [server/src/services/memory-queue.ts:26-46](file://server/src/services/memory-queue.ts#L26-L46)
章节来源
- [server/src/services/queue.service.ts:48-347](file://server/src/services/queue.service.ts#L48-L347)
- [server/src/services/memory-queue.ts:17-119](file://server/src/services/memory-queue.ts#L17-L119)
### 书籍生成队列处理器与中断恢复
- 处理器:并发 3,捕获进度、完成、失败事件,更新书籍状态
- 中断恢复:启动时扫描处于生成阶段的书籍,重新入队继续生成
```mermaid
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](file://server/src/modules/book-generator/book-queue.processor.ts#L48-L83)
- [server/src/modules/book-generator/book-queue.processor.ts:88-124](file://server/src/modules/book-generator/book-queue.processor.ts#L88-L124)
章节来源
- [server/src/modules/book-generator/book-queue.processor.ts:16-83](file://server/src/modules/book-generator/book-queue.processor.ts#L16-L83)
- [server/src/modules/book-generator/book-queue.processor.ts:88-124](file://server/src/modules/book-generator/book-queue.processor.ts#L88-L124)
### 模板管理系统
- 模板分类与列表:支持按分类筛选与总数统计
- CRUD:创建、更新、删除、按 ID 查询
- 内容渲染:模板字符串占位符替换(示例:{{xxx}})
```mermaid
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](file://deploy-package/server/modules/templates/templates.controller.js#L13-L167)
- [deploy-package/server/modules/templates/templates.service.js:4-103](file://deploy-package/server/modules/templates/templates.service.js#L4-L103)
章节来源
- [deploy-package/server/modules/templates/templates.controller.js:13-167](file://deploy-package/server/modules/templates/templates.controller.js#L13-L167)
- [deploy-package/server/modules/templates/templates.service.js:4-103](file://deploy-package/server/modules/templates/templates.service.js#L4-L103)
### 速率限制中间件
- 支持内存与 Redis 两种限流器,自动选择
- 提供 API 全局限流、登录限流、短信验证码限流、TTS 限流、文件上传限流
- 429 响应包含 Retry-After 与提示信息
章节来源
- [server/src/middleware/rate-limiter.ts:17-120](file://server/src/middleware/rate-limiter.ts#L17-L120)
## 依赖关系分析
- 控制器依赖服务:audioedit.controller 依赖 audioedit.service
- 服务依赖处理器与存储:audioedit.service 调用 FFmpeg 处理器与存储服务
- 队列依赖 Redis/内存:queue.service 优先 Redis,失败回退 memory-queue
- 书籍生成处理器依赖队列与存储:book-queue.processor 调用队列与 FFmpeg/存储
- 应用入口集中注册路由与中间件,统一初始化
```mermaid
graph LR
AC["audioedit.controller.ts"] --> AS["audioedit.service.ts"]
AS --> FP["ffmpeg.processor.ts"]
AS --> SS["storage.service.ts"]
QS["queue.service.ts"] --> RS["redis.service.ts"]
QS --> MQ["memory-queue.ts"]
BG["book-queue.processor.ts"] --> QS
BG --> MQ
BG --> FP
BG --> SS
APP["app.ts"] --> AC
APP --> TC["templates.controller.js"]
```
图表来源
- [server/src/modules/audioedit/audioedit.controller.ts:10-101](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L101)
- [server/src/modules/audioedit/audioedit.service.ts:4-49](file://server/src/modules/audioedit/audioedit.service.ts#L4-L49)
- [server/src/services/ffmpeg.processor.ts:24-379](file://server/src/services/ffmpeg.processor.ts#L24-L379)
- [server/src/services/storage.service.ts:13-278](file://server/src/services/storage.service.ts#L13-L278)
- [server/src/services/queue.service.ts:48-347](file://server/src/services/queue.service.ts#L48-L347)
- [server/src/services/memory-queue.ts:17-119](file://server/src/services/memory-queue.ts#L17-L119)
- [server/src/services/redis.service.ts:3-274](file://server/src/services/redis.service.ts#L3-L274)
- [server/src/modules/book-generator/book-queue.processor.ts:48-83](file://server/src/modules/book-generator/book-queue.processor.ts#L48-L83)
- [server/src/app.ts:100-128](file://server/src/app.ts#L100-L128)
章节来源
- [server/src/app.ts:100-130](file://server/src/app.ts#L100-L130)
## 性能考量
- 并发与超时:队列任务针对不同场景设置超时(音频 5 分钟、视频 10 分钟、书籍 2 小时)
- 临时文件管理:FFmpeg 处理器在 finally 中清理临时文件,避免磁盘占用
- 存储切换:通过环境变量切换 OSS/本地,便于测试与生产解耦
- 限流策略:对高频接口进行限流,防止突发流量导致资源耗尽
- 进度回调:任务进度通过队列事件上报,前端可实时展示
章节来源
- [server/src/services/queue.service.ts:166-190](file://server/src/services/queue.service.ts#L166-L190)
- [server/src/services/ffmpeg.processor.ts:109](file://server/src/services/ffmpeg.processor.ts#L109)
- [server/src/services/storage.service.ts:17-28](file://server/src/services/storage.service.ts#L17-L28)
- [server/src/middleware/rate-limiter.ts:77-120](file://server/src/middleware/rate-limiter.ts#L77-L120)
## 故障排查指南
- 队列不可用:Redis 不可用时自动回退内存队列,检查 Redis 连接状态与日志
- 任务失败:查看队列失败事件与书籍状态更新,定位具体环节
- 存储异常:确认存储类型与路径,OSS 需检查凭证与网络连通性
- 临时文件未清理:检查清理逻辑与权限,必要时手动清理临时目录
- 限流触发:根据 429 响应头 Retry-After 调整请求节奏
章节来源
- [server/src/services/queue.service.ts:53-66](file://server/src/services/queue.service.ts#L53-L66)
- [server/src/modules/book-generator/book-queue.processor.ts:66-74](file://server/src/modules/book-generator/book-queue.processor.ts#L66-L74)
- [server/src/services/ffmpeg.processor.ts:346-375](file://server/src/services/ffmpeg.processor.ts#L346-L375)
- [server/src/middleware/rate-limiter.ts:52-71](file://server/src/middleware/rate-limiter.ts#L52-L71)
## 结论
媒体处理服务以清晰的分层架构与可扩展的队列机制为基础,结合 FFmpeg 处理器与统一存储抽象,实现了音频编辑、模板管理与批量处理的核心能力。通过 Redis/内存双轨队列与进度回调,系统具备良好的并发控制与可观测性。建议在生产环境中完善错误恢复策略、引入更细粒度的质量评估指标与成本控制模块。
## 附录
### 处理流程说明(音频编辑)
- 裁剪:校验参数 → 下载 → 裁剪 → 上传 → 返回结果
- 合并:校验参数 → 下载 → 构建列表 → 合并 → 上传 → 返回结果
- 信息查询:返回预设信息(时长、大小、格式、码率)
章节来源
- [server/src/modules/audioedit/audioedit.controller.ts:10-101](file://server/src/modules/audioedit/audioedit.controller.ts#L10-L101)
- [server/src/modules/audioedit/audioedit.service.ts:8-48](file://server/src/modules/audioedit/audioedit.service.ts#L8-L48)
- [server/src/services/ffmpeg.processor.ts:69-122](file://server/src/services/ffmpeg.processor.ts#L69-L122)
### 参数配置指南
- 存储类型:通过环境变量切换 OSS/本地
- 队列超时:按任务类型配置超时时间
- 限流策略:按接口场景配置限流参数
章节来源
- [server/src/services/storage.service.ts:17-28](file://server/src/services/storage.service.ts#L17-L28)
- [server/src/services/queue.service.ts:166-190](file://server/src/services/queue.service.ts#L166-L190)
- [server/src/middleware/rate-limiter.ts:77-120](file://server/src/middleware/rate-limiter.ts#L77-L120)
### 质量评估标准与成本分析
- TTS 成本模型:AI 生成成本 + TTS 合成成本
- 套餐定价:覆盖成本与合理利润,提供多档位套餐
- 成本控制:每日使用限制、单次生成上限、服务商切换策略
章节来源
- [docs/TTS成本分析报告.md:32-152](file://docs/TTS成本分析报告.md#L32-L152)
- [docs/TTS成本分析报告.md:156-329](file://docs/TTS成本分析报告.md#L156-L329)