文本转音频.md 19 KB

文本转音频

本文引用的文件

  • 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

目录

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

引言

本技术文档围绕“文本转音频”(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)"]
    

图表来源

  • tts.service.ts:98-158

章节来源

  • tts.service.ts:98-158

音频生成与拼接

  • 合成阶段: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/状态接口获取
  • 预览音色
    • POST /api/tts/preview
  • 下载音频
    • 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