文本转音频
本文引用的文件
- tts.service.ts
- tts.controller.ts
- aliyun.provider.ts
- aliyun-realtime.provider.ts
- minimax.provider.ts
- mock.provider.ts
- audio-merger.ts
- ffmpeg.processor.ts
- index.ts
- index.ts
- ai-summary.service.ts
- app.ts
- API.md
目录
- 引言
- 项目结构
- 核心组件
- 架构总览
- 详细组件分析
- 依赖关系分析
- 性能考量
- 故障排查指南
- 结论
- 附录
引言
本技术文档围绕“文本转音频”(TTS)能力进行系统化梳理,覆盖异步音频生成流程、队列与状态管理、智能分段算法、音频拼接、质量控制、错误处理与重试、以及 API 使用与最佳实践。文档面向开发者与产品/运营人员,既提供代码级细节,也给出概念性说明与可视化图示。
项目结构
TTS 功能位于后端服务的 TTS 模块,主要由控制器、服务层、提供者(Provider)、合并器与 FFmpeg 处理器组成,并通过配置中心与类型定义支撑运行时行为。
graph TB
subgraph "应用入口"
APP["app.ts<br/>注册路由/中间件/静态资源"]
end
subgraph "TTS 模块"
CTRL["tts.controller.ts<br/>REST 控制器"]
SVC["tts.service.ts<br/>业务服务"]
MERGE["audio-merger.ts<br/>本地合并/时长"]
FPROC["ffmpeg.processor.ts<br/>远程下载/合并/时长"]
SUMM["ai-summary.service.ts<br/>标题/摘要/标签"]
end
subgraph "TTS 提供者"
ALI["aliyun.provider.ts<br/>HTTP 合成"]
REAL["aliyun-realtime.provider.ts<br/>WebSocket 实时"]
MINI["minimax.provider.ts<br/>异步长文本"]
MOCK["mock.provider.ts<br/>模拟/占位"]
end
subgraph "配置与类型"
CFG["config/index.ts<br/>DashScope/模型/上传"]
TYPES["types/index.ts<br/>VoiceParams/AudioStatus"]
end
APP --> CTRL --> SVC
SVC --> ALI
SVC --> REAL
SVC --> MINI
SVC --> MOCK
SVC --> MERGE
MERGE --> FPROC
SVC --> SUMM
SVC --> CFG
SVC --> TYPES
图表来源
- app.ts:99-130
- tts.controller.ts:10-13
- tts.service.ts:1-20
- audio-merger.ts:9-36
- ffmpeg.processor.ts:24-122
- aliyun.provider.ts:9-19
- aliyun-realtime.provider.ts:11-21
- minimax.provider.ts:42-51
- mock.provider.ts:11-17
- index.ts:69-117
- index.ts:40-46
章节来源
- app.ts:99-130
- tts.controller.ts:10-13
- tts.service.ts:1-20
- index.ts:69-117
核心组件
- 控制器(tts.controller.ts):负责参数校验、配额检查、调用服务层并返回统一响应格式。
- 服务层(tts.service.ts):实现异步生成、文本分段、Provider 选择与回退、并发合成、合并与上传、状态更新、回调与 WebSocket 通知。
- 提供者(Provider):封装不同 TTS 供应商的调用细节,含重试与错误分类。
- 合并器(audio-merger.ts):本地文件合并与时长探测;远程场景委托 FFmpeg 处理器。
- FFmpeg 处理器(ffmpeg.processor.ts):统一处理远程 URL 的下载、合并、格式转换、裁剪、音量调节与上传。
- 配置与类型(config/index.ts、types/index.ts):提供 DashScope/MiniMax 等配置、模型列表、上传目录、音质参数等。
- AI 摘要(ai-summary.service.ts):生成标题、摘要与标签,提升内容可发现性。
章节来源
- tts.controller.ts:52-127
- tts.service.ts:200-542
- audio-merger.ts:9-86
- ffmpeg.processor.ts:69-208
- index.ts:83-93
- index.ts:40-46
- ai-summary.service.ts:7-169
架构总览
TTS 采用“控制器-服务-提供者-存储”的分层设计,结合 Provider 工厂与优先级回退策略,确保在多供应商环境下具备高可用与弹性。异步生成流程通过文件系统状态与 WebSocket 事件实现进度通知,同时通过配额与订阅服务保障资源使用合规。
sequenceDiagram
participant C as "客户端"
participant R as "tts.controller.ts"
participant S as "tts.service.ts"
participant P as "Provider(阿里云/MiniMax/模拟)"
participant M as "AudioMerger/FFmpeg"
participant ST as "存储服务"
participant WS as "WebSocket"
C->>R : POST /api/tts/generate
R->>R : 校验参数/配额检查
R->>S : generateAudio(userId,text,voice,voiceParams,...)
S->>S : 选择Provider/分段/并发合成
S->>P : synthesize(分段xN)
P-->>S : 本地文件/云端URL
S->>M : 合并/时长探测
M-->>S : 合成文件/URL
S->>ST : 上传/返回最终URL
ST-->>S : 最终URL
S->>WS : 推送完成事件
S-->>R : 返回{audioId,audioUrl}
R-->>C : 统一响应
图表来源
- tts.controller.ts:52-127
- tts.service.ts:200-542
- audio-merger.ts:9-86
- ffmpeg.processor.ts:69-122
详细组件分析
异步音频生成流程与状态跟踪
- 入口:控制器接收请求,进行参数与配额校验后调用服务层异步生成。
- 服务层:
- 生成唯一音频 ID,创建记录(processing),并进入异步处理。
- 选择 Provider(优先级:MiniMax → 阿里云 → 模拟),按类型决定分段策略与并发度。
- 并行合成各段音频,聚合本地文件与云端 URL。
- 合并为最终 MP3,计算时长与大小,上传至存储服务。
- 生成标题/摘要/标签,写入书籍章节(如存在),更新记录状态为 completed。
- 回调 onComplete(如有),推送 WebSocket 完成事件。
状态查询:基于文件系统与失败标记判断(not_found/processing/completed/failed)。
flowchart TD
Start(["开始"]) --> Validate["参数与配额校验"]
Validate --> CreateRec["创建处理记录(processing)"]
CreateRec --> SelectProv["选择Provider(优先级)"]
SelectProv --> DecideSplit{"是否分段?"}
DecideSplit --> |是| Split["智能分段(段落/句子/强制切分)"]
DecideSplit --> |否| NoSplit["整段直传(如MiniMax)"]
Split --> Concurrency["并发合成(1/2)"]
NoSplit --> Concurrency
Concurrency --> Merge["合并/时长/上传"]
Merge --> AI["AI生成标题/摘要/标签"]
AI --> Save["写入书籍章节/更新记录"]
Save --> Callback["回调/推送事件"]
Callback --> End(["结束"])
图表来源
- tts.controller.ts:87-120
- tts.service.ts:285-542
章节来源
- tts.controller.ts:52-127
- tts.service.ts:200-542
- tts.service.ts:547-597
智能分段处理算法
- 分段策略:
- 按段落(按换行)合并,超过阈值(550 字)再按句子切分。
- 句子仍超限则强制按字符块切分。
- 最终安全检查:超过阈值的段落截断,避免越界。
- 适用范围:HTTP Provider(阿里云);MiniMax 异步长文本不进行分段。
设计动机:兼顾供应商字符上限与自然语义边界,保证合成质量与稳定性。
flowchart TD
A["输入文本"] --> Clean["清理/去回车"]
Clean --> Para["按段落拆分"]
Para --> CheckLen{"当前段<=550?"}
CheckLen --> |是| Acc["累加到当前段"]
CheckLen --> |否| OverPara["段超限"]
OverPara --> Sent["按句号/感叹号等切分"]
Sent --> SentCheck{"句<=550?"}
SentCheck --> |是| Acc
SentCheck --> |否| Force["强制按字符块切分"]
Force --> Acc
Acc --> NextPara["下一个段落"]
NextPara --> Done["汇总为若干段(≤550)"]
图表来源
章节来源
音频生成与拼接
- 合成阶段:Provider 返回本地文件路径或云端 URL。
- 合并阶段:
- 本地:使用 FFmpeg concat 合并,MP3 转码为 192k。
- 远程:委托 FFmpeg 处理器下载、合并、上传,统一返回最终 URL。
- 时长探测:本地使用 ffprobe;远程通过 FFmpeg 处理器探测。
上传:统一经存储服务处理(本地/oss 可切换)。
classDiagram
class AudioMerger {
+merge(inputFiles,outputPath) Promise~string~
+getDuration(filePath) Promise~number~
-mergeLocalFiles(inputFiles,outputPath) Promise~string~
}
class FFmpegProcessor {
+mergeAudio(urls,format) Promise~string~
+getDuration(url) Promise~number~
+convertFormat(url,format,bitrate) Promise~string~
+trimAudio(url,start,duration) Promise~string~
+adjustVolume(url,volume) Promise~string~
-downloadFile(url) Promise~string~
}
AudioMerger --> FFmpegProcessor : "远程场景委托"
图表来源
- audio-merger.ts:9-86
- ffmpeg.processor.ts:69-208
章节来源
- audio-merger.ts:9-86
- ffmpeg.processor.ts:69-208
Provider 与质量控制
- 阿里云(HTTP):支持 instruct 模型的指令控制(速度/音调),带指数退避重试与速率限制处理。
- 阿里云(实时 WebSocket):长文本流式合成,支持会话配置与音频流拼接。
- MiniMax:异步长文本任务,轮询状态,tar 包内提取 MP3,音频采样率 32kHz、码率 128kbps、单声道 MP3。
模拟 Provider:FFmpeg 生成占位音频,便于开发调试。
classDiagram
class AliyunTtsProvider {
+synthesize(text,voice,params,output,retries,model?) Promise~string~
}
class AliyunRealtimeTtsProvider {
+synthesize(text,voice,params,output) Promise~string~
}
class MiniMaxTtsProvider {
+synthesize(text,voice,params,output,retries,_) Promise~string~
}
class MockTtsProvider {
+synthesize(text,voice,params,output) Promise~string~
}
图表来源
- aliyun.provider.ts:9-152
- aliyun-realtime.provider.ts:11-158
- minimax.provider.ts:42-280
- mock.provider.ts:11-61
章节来源
- aliyun.provider.ts:21-150
- aliyun-realtime.provider.ts:23-156
- minimax.provider.ts:53-278
- mock.provider.ts:12-60
错误处理与重试机制
- 速率限制/服务器错误:指数退避重试(2^attempt × 1000 ms),最多 N 次。
- Provider 回退:若为额度受限错误,切换下一个 Provider;否则直接抛错。
- 文件系统状态:失败标记文件、空目录僵尸任务检测、超时失败回写数据库。
WebSocket 通知:生成成功/失败均推送事件,前端可订阅。
flowchart TD
Call["调用Provider"] --> Resp{"响应状态"}
Resp --> |200+有效| OK["成功返回"]
Resp --> |429/配额| Rate["速率限制/配额超限"]
Resp --> |5xx/网络| Retry["指数退避重试"]
Resp --> |其他| Fail["抛错/回退"]
Rate --> NextProv["切换下一Provider"]
Retry --> Call
NextProv --> Call
Fail --> End["结束"]
OK --> End
图表来源
- tts.service.ts:518-542
- aliyun.provider.ts:125-145
- minimax.provider.ts:258-278
章节来源
- tts.service.ts:518-542
- tts.service.ts:547-597
- aliyun.provider.ts:125-145
- minimax.provider.ts:258-278
API 使用示例与最佳实践
- 获取音色列表与可用供应商
- GET /api/tts/voices
- GET /api/tts/providers
- 生成音频(异步)
- POST /api/tts/generate
- 请求体包含 text、voiceId、voiceParams(speed/pitch/volume)、可选 bookId/chapterTitle/ttsProvider
- 响应返回 audioId(立即可用),最终 URL 通过回调/WebSocket/状态接口获取
- 预览音色
- 下载音频
- GET /api/tts/download/:audioId
- 批量下载:POST /api/tts/download/batch
最佳实践
- 参数校验:必填字段与数值范围(速度 0.5-2.0、音调 -500~500、音量 0-100)。
- 并发与配额:合理设置并发度(MiniMax 1,其他 2),关注订阅配额与字数限制。
- Provider 选择:优先 MiniMax(长文本),否则阿里云 HTTP;无密钥回退模拟。
- 状态查询:使用 /api/tts/status/:audioId 或 WebSocket 事件。
- 质量控制:MP3 192k、采样率 32kHz(MiniMax),必要时通过 FFmpeg 转换。
章节来源
- API.md:95-158
- tts.controller.ts:12-180
- tts.controller.ts:182-272
- index.ts:40-46
- minimax.provider.ts:72-77
依赖关系分析
- 控制器依赖服务层与中间件(鉴权、限流、错误处理、性能监控、安全防护)。
- 服务层依赖 Provider、合并器、AI 摘要、存储服务、WebSocket 服务、数据库。
- Provider 依赖配置中心(DashScope/MiniMax)与网络库。
合并器与 FFmpeg 处理器依赖系统命令(ffmpeg/ffprobe)与存储服务。
graph LR
CTRL["tts.controller.ts"] --> SVC["tts.service.ts"]
SVC --> ALI["aliyun.provider.ts"]
SVC --> REAL["aliyun-realtime.provider.ts"]
SVC --> MINI["minimax.provider.ts"]
SVC --> MOCK["mock.provider.ts"]
SVC --> MERGE["audio-merger.ts"]
MERGE --> FPROC["ffmpeg.processor.ts"]
SVC --> SUMM["ai-summary.service.ts"]
SVC --> CFG["config/index.ts"]
CTRL --> TYPES["types/index.ts"]
图表来源
- tts.controller.ts:1-10
- tts.service.ts:1-14
- audio-merger.ts:1-7
- ffmpeg.processor.ts:1-12
- index.ts:1-11
- index.ts:1-12
章节来源
- tts.controller.ts:1-10
- tts.service.ts:1-14
- audio-merger.ts:1-7
- ffmpeg.processor.ts:1-12
- index.ts:1-11
- index.ts:1-12
性能考量
- 并发策略:MiniMax 异步轮询耗时较长,采用并发=1;HTTP Provider 并发=2,提升吞吐。
- 分段阈值:550 字安全余量,平衡字符上限与语义完整性。
- 合并优化:本地合并直接复制流(非 MP3)或转码(MP3),远程场景统一通过 FFmpeg 处理器。
- 存储上传:统一经存储服务,支持本地/oss 切换,减少耦合。
- 时长与大小:合并后即时统计,避免重复探测。
[本节为通用性能讨论,不直接分析具体文件]
故障排查指南
常见问题与定位步骤
- 生成失败:检查 Provider 日志与错误类型(速率限制/配额/网络),确认回退链路是否生效。
- 文件缺失:确认上传目录存在、权限正确;检查失败标记文件与僵尸任务检测逻辑。
- 时长/大小异常:确认合并与探测流程是否执行;远程场景检查 FFmpeg 处理器下载与探测。
- WebSocket 未推送:确认初始化与事件推送逻辑;检查回调是否被正确 await。
- 配额不足:核对订阅状态与字数消耗;必要时提示升级会员等级。
章节来源
- tts.service.ts:547-597
- tts.service.ts:272-279
- ffmpeg.processor.ts:190-208
结论
该 TTS 方案通过“控制器-服务-Provider-存储”的清晰分层,结合智能分段、并发合成、统一合并与上传、AI 摘要与状态跟踪,实现了高可用、可扩展、可维护的文本转音频能力。配合订阅配额与错误回退机制,可在多供应商环境下稳定运行,并为后续扩展(队列、批处理、更多 Provider)奠定基础。
附录
- 关键配置项
- DashScope API Key、模型、音色、TTS 模型列表、是否启用实时模式
- 上传目录、最大文件大小
- 关键类型
- VoiceParams:speed/pitch/volume
- AudioStatus:processing/completed/failed
- 常用接口
- GET /api/tts/voices
- GET /api/tts/providers
- POST /api/tts/generate
- GET /api/tts/status/:audioId
- POST /api/tts/preview
- GET /api/tts/download/:audioId
- POST /api/tts/download/batch
章节来源
- index.ts:83-93
- index.ts:113-117
- index.ts:40-46
- API.md:95-158