# 插件开发 **本文引用的文件** - [server/src/app.ts](file://server/src/app.ts) - [server/src/config/index.ts](file://server/src/config/index.ts) - [server/src/types/index.ts](file://server/src/types/index.ts) - [server/src/modules/tts/tts.controller.ts](file://server/src/modules/tts/tts.controller.ts) - [server/src/modules/tts/tts.service.ts](file://server/src/modules/tts/tts.service.ts) - [server/src/modules/tts/aliyun.provider.ts](file://server/src/modules/tts/aliyun.provider.ts) - [server/src/modules/tts/minimax.provider.ts](file://server/src/modules/tts/minimax.provider.ts) - [server/src/modules/tts/mock.provider.ts](file://server/src/modules/tts/mock.provider.ts) - [server/src/modules/tts/aliyun-realtime.provider.ts](file://server/src/modules/tts/aliyun-realtime.provider.ts) - [server/src/modules/tts/audio-merger.ts](file://server/src/modules/tts/audio-merger.ts) - [server/src/services/storage.service.ts](file://server/src/services/storage.service.ts) - [server/src/services/oss.service.ts](file://server/src/services/oss.service.ts) - [server/src/middleware/errorHandler.js](file://server/src/middleware/errorHandler.js) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向希望为AI有声书生成平台开发“插件”的工程师,系统讲解如何开发三类插件: - TTS音色提供商插件:对接不同厂商的语音合成能力 - AI模型插件:扩展文本生成、理解等LLM能力 - 存储插件:统一管理本地与云存储(如OSS) 文档覆盖插件架构设计、接口规范、生命周期管理、注册机制、依赖注入与配置管理,并提供开发模板、最佳实践与调试技巧,以及插件间通信、错误处理与性能优化策略。 ## 项目结构 平台采用模块化与分层架构: - 应用入口负责中间件、静态资源、路由注册与服务初始化 - 配置中心集中管理模型与第三方服务配置 - TTS模块负责音色合成、文本分段、并发与合并、状态查询 - 存储模块统一抽象本地与OSS,屏蔽差异 - 中间件提供错误处理、安全与性能监控 ```mermaid graph TB subgraph "应用层" APP["应用入口
server/src/app.ts"] ROUTER["路由注册
TTS/业务路由"] end subgraph "服务层" TTS_CTRL["TTS控制器
tts.controller.ts"] TTS_SVC["TTS服务
tts.service.ts"] STORAGE["存储服务
storage.service.ts"] OSS["OSS服务
oss.service.ts"] end subgraph "插件层" ALIYUN["阿里云TTS插件
aliyun.provider.ts"] MINIMAX["MiniMax TTS插件
minimax.provider.ts"] MOCK["Mock TTS插件
mock.provider.ts"] REALTIME["阿里云实时TTS插件
aliyun-realtime.provider.ts"] MERGER["音频合并器
audio-merger.ts"] end subgraph "配置与类型" CFG["配置中心
config/index.ts"] TYPES["类型定义
types/index.ts"] end APP --> ROUTER ROUTER --> TTS_CTRL TTS_CTRL --> TTS_SVC TTS_SVC --> ALIYUN TTS_SVC --> MINIMAX TTS_SVC --> MOCK TTS_SVC --> REALTIME TTS_SVC --> MERGER TTS_SVC --> STORAGE STORAGE --> OSS APP --> CFG APP --> TYPES ``` 图表来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [server/src/modules/tts/tts.controller.ts:1-274](file://server/src/modules/tts/tts.controller.ts#L1-L274) - [server/src/modules/tts/tts.service.ts:1-715](file://server/src/modules/tts/tts.service.ts#L1-L715) - [server/src/modules/tts/aliyun.provider.ts:1-152](file://server/src/modules/tts/aliyun.provider.ts#L1-L152) - [server/src/modules/tts/minimax.provider.ts:1-280](file://server/src/modules/tts/minimax.provider.ts#L1-L280) - [server/src/modules/tts/mock.provider.ts:1-61](file://server/src/modules/tts/mock.provider.ts#L1-L61) - [server/src/modules/tts/aliyun-realtime.provider.ts:1-158](file://server/src/modules/tts/aliyun-realtime.provider.ts#L1-L158) - [server/src/modules/tts/audio-merger.ts:1-86](file://server/src/modules/tts/audio-merger.ts#L1-L86) - [server/src/services/storage.service.ts:1-278](file://server/src/services/storage.service.ts#L1-L278) - [server/src/services/oss.service.ts:1-256](file://server/src/services/oss.service.ts#L1-L256) - [server/src/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) 章节来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [server/src/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) ## 核心组件 - 应用入口与中间件 - 负责全局中间件(CORS、日志、安全、限流、Sentry)、静态资源挂载、路由注册与优雅关闭 - 初始化数据库、Redis、存储、WebSocket、书籍生成队列 - 配置中心 - 统一加载.env与models.json,提供模型枚举、启用筛选、错误识别与自动切换辅助 - TTS控制器与服务 - 控制器负责参数校验、配额检查、路由转发 - 服务负责文本分段、并发合成、合并、上传、状态查询、回调与WebSocket推送 - 存储服务 - 抽象本地与OSS,提供上传/下载/删除/签名URL/目录清理等能力 - 插件(TTS提供商) - 阿里云HTTP/TTS、MiniMax异步、Mock占位、阿里云实时WebSocket - 音频合并器 - 支持本地与远程URL的合并与时长探测 章节来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [server/src/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/modules/tts/tts.controller.ts:1-274](file://server/src/modules/tts/tts.controller.ts#L1-L274) - [server/src/modules/tts/tts.service.ts:1-715](file://server/src/modules/tts/tts.service.ts#L1-L715) - [server/src/services/storage.service.ts:1-278](file://server/src/services/storage.service.ts#L1-L278) - [server/src/modules/tts/aliyun.provider.ts:1-152](file://server/src/modules/tts/aliyun.provider.ts#L1-L152) - [server/src/modules/tts/minimax.provider.ts:1-280](file://server/src/modules/tts/minimax.provider.ts#L1-L280) - [server/src/modules/tts/mock.provider.ts:1-61](file://server/src/modules/tts/mock.provider.ts#L1-L61) - [server/src/modules/tts/aliyun-realtime.provider.ts:1-158](file://server/src/modules/tts/aliyun-realtime.provider.ts#L1-L158) - [server/src/modules/tts/audio-merger.ts:1-86](file://server/src/modules/tts/audio-merger.ts#L1-L86) ## 架构总览 TTS插件体系通过“服务工厂 + 插件实现 + 统一存储”的方式解耦。服务层根据配置与优先级选择具体插件,插件负责与外部API交互,最终由存储服务统一对外暴露URL。 ```mermaid sequenceDiagram participant Client as "客户端" participant Ctrl as "TTS控制器" participant Svc as "TTS服务" participant Prov as "TTS插件(阿里云/MiniMax/Mock)" participant Merge as "音频合并器" participant Store as "存储服务" participant OSS as "OSS服务" Client->>Ctrl : "POST /api/tts/generate" Ctrl->>Svc : "generateAudio(userId,text,voiceId,params,options)" Svc->>Svc : "选择插件(优先级/配置)" Svc->>Prov : "synthesize(分段,参数,输出路径)" Prov-->>Svc : "返回本地文件路径或云端URL" Svc->>Merge : "合并多段音频" Merge-->>Svc : "输出合并文件" Svc->>Store : "uploadAudio(合并文件,audioId)" Store->>OSS : "OSS上传(可选)" Store-->>Svc : "返回访问URL" Svc-->>Ctrl : "{audioId,audioUrl}" Ctrl-->>Client : "任务已创建" ``` 图表来源 - [server/src/modules/tts/tts.controller.ts:52-127](file://server/src/modules/tts/tts.controller.ts#L52-L127) - [server/src/modules/tts/tts.service.ts:200-542](file://server/src/modules/tts/tts.service.ts#L200-L542) - [server/src/modules/tts/aliyun.provider.ts:21-150](file://server/src/modules/tts/aliyun.provider.ts#L21-L150) - [server/src/modules/tts/minimax.provider.ts:234-278](file://server/src/modules/tts/minimax.provider.ts#L234-L278) - [server/src/modules/tts/mock.provider.ts:12-60](file://server/src/modules/tts/mock.provider.ts#L12-L60) - [server/src/modules/tts/audio-merger.ts:9-36](file://server/src/modules/tts/audio-merger.ts#L9-L36) - [server/src/services/storage.service.ts:43-49](file://server/src/services/storage.service.ts#L43-L49) - [server/src/services/oss.service.ts:91-94](file://server/src/services/oss.service.ts#L91-L94) ## 详细组件分析 ### TTS控制器(接口与生命周期) - 职责 - 参数校验、配额检查、路由转发至服务层 - 生命周期:请求进入 -> 校验 -> 调用服务 -> 返回任务ID/状态 - 关键点 - 支持可选鉴权、字数限制、书籍归属与章节标题 - 生成成功后进行配额消耗 - 提供状态查询、预览生成、下载信息与批量下载 ```mermaid flowchart TD Start(["请求进入 /api/tts/generate"]) --> Validate["参数校验
text/voiceId/可选bookId/chapterTitle"] Validate --> Quota["配额检查(音频分钟)"] Quota --> CallSvc["调用 TTS 服务 generateAudio"] CallSvc --> Return["返回 {audioId,audioUrl}"] Return --> End(["结束"]) ``` 图表来源 - [server/src/modules/tts/tts.controller.ts:52-127](file://server/src/modules/tts/tts.controller.ts#L52-L127) 章节来源 - [server/src/modules/tts/tts.controller.ts:1-274](file://server/src/modules/tts/tts.controller.ts#L1-L274) ### TTS服务(工厂、优先级与回退) - 职责 - 文本分段、并发合成、合并、上传、状态查询、回调与WebSocket推送 - 插件优先级:MiniMax -> 阿里云HTTP -> Mock - 额度限制错误自动回退到下一个插件 - 关键点 - MiniMax异步长文本无需分段;阿里云HTTP需分段 - 并发策略:MiniMax串行,其他并行 - 云端URL降级到本地文件再统一上传 ```mermaid flowchart TD A["输入: text, voiceId, voiceParams, options"] --> B["构建优先级列表"] B --> C{"逐个尝试插件"} C --> |额度限制| D["记录最后错误, 继续下一个"] C --> |真实失败| E["抛出错误, 停止"] C --> |成功| F["合并音频 -> 上传存储 -> 更新记录 -> 回调/推送"] D --> C F --> G["返回 {audioId,audioUrl,bookId}"] ``` 图表来源 - [server/src/modules/tts/tts.service.ts:304-542](file://server/src/modules/tts/tts.service.ts#L304-L542) 章节来源 - [server/src/modules/tts/tts.service.ts:1-715](file://server/src/modules/tts/tts.service.ts#L1-L715) ### TTS插件(接口规范与实现要点) - 接口规范 - 统一方法:synthesize(text, voiceId, params, outputPath, retries?, modelOverride?) - 返回值:本地文件路径或“cloud:”前缀的云端URL - 错误处理:区分速率限制与服务错误,支持指数退避重试 - 实现要点 - 阿里云HTTP:支持指令模型参数拼装、云端URL回退 - MiniMax异步:创建任务 -> 轮询 -> tar提取MP3 - Mock:FFmpeg生成占位音频,失败时写入最小MP3头 - 阿里云实时:WebSocket流式合成,适合长文本 ```mermaid classDiagram class TtsProvider { +synthesize(text, voiceId, params, outputPath, retries, modelOverride) string } class AliyunTtsProvider { -apiKey string -model string -voice string } class MiniMaxTtsProvider { -apiKey string } class MockTtsProvider class AliyunRealtimeTtsProvider { -apiKey string -model string -voice string } TtsProvider <|.. AliyunTtsProvider TtsProvider <|.. MiniMaxTtsProvider TtsProvider <|.. MockTtsProvider TtsProvider <|.. AliyunRealtimeTtsProvider ``` 图表来源 - [server/src/modules/tts/aliyun.provider.ts:9-152](file://server/src/modules/tts/aliyun.provider.ts#L9-L152) - [server/src/modules/tts/minimax.provider.ts:42-280](file://server/src/modules/tts/minimax.provider.ts#L42-L280) - [server/src/modules/tts/mock.provider.ts:11-61](file://server/src/modules/tts/mock.provider.ts#L11-L61) - [server/src/modules/tts/aliyun-realtime.provider.ts:11-158](file://server/src/modules/tts/aliyun-realtime.provider.ts#L11-L158) 章节来源 - [server/src/modules/tts/aliyun.provider.ts:1-152](file://server/src/modules/tts/aliyun.provider.ts#L1-L152) - [server/src/modules/tts/minimax.provider.ts:1-280](file://server/src/modules/tts/minimax.provider.ts#L1-L280) - [server/src/modules/tts/mock.provider.ts:1-61](file://server/src/modules/tts/mock.provider.ts#L1-L61) - [server/src/modules/tts/aliyun-realtime.provider.ts:1-158](file://server/src/modules/tts/aliyun-realtime.provider.ts#L1-L158) ### 存储插件(统一抽象与OSS) - 职责 - 本地与OSS无缝切换,提供上传/下载/删除/签名URL/目录清理 - 通过环境变量STORAGE_TYPE切换模式 - 关键点 - OSS服务封装OSS SDK,支持对象键规范化、CDN域名回源 - 存储服务在本地模式下直接写入uploads目录 ```mermaid classDiagram class StorageService { -storageType StorageType +setStorageType(type) +getStorageType() StorageType +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 } class OSSService { -client OSS -bucket string -cdnDomain string +uploadFile(localPath, objectKey) string +uploadBuffer(buffer, objectKey, contentType) string +uploadAudio(localPath, audioId) string +uploadVideo(localPath, videoId) string +uploadCover(localPath, bookId) string +deleteFile(objectKey) +deleteDirectory(prefix) +getSignedUrl(objectKey, expires) string +downloadFile(objectKey) Buffer +getFileUrl(objectKey) string +testConnection() boolean } StorageService --> OSSService : "OSS模式委托" ``` 图表来源 - [server/src/services/storage.service.ts:13-278](file://server/src/services/storage.service.ts#L13-L278) - [server/src/services/oss.service.ts:13-256](file://server/src/services/oss.service.ts#L13-L256) 章节来源 - [server/src/services/storage.service.ts:1-278](file://server/src/services/storage.service.ts#L1-L278) - [server/src/services/oss.service.ts:1-256](file://server/src/services/oss.service.ts#L1-L256) ### 音频合并器(跨域与本地处理) - 职责 - 合并本地或多段远程URL音频,计算时长 - 远程URL通过FFmpegProcessor处理,本地使用FFmpeg concat - 关键点 - 单文件直接复制,避免不必要的转码 - 输出格式自动适配 章节来源 - [server/src/modules/tts/audio-merger.ts:1-86](file://server/src/modules/tts/audio-merger.ts#L1-L86) ### 配置与类型(模型与参数) - 配置中心 - 加载.env与models.json,提供模型枚举、启用筛选、错误识别与自动切换辅助 - TTS相关:DashScope API Key、模型列表、实时模型开关 - 类型定义 - VoiceParams、Voice、IUser、IAudio、ApiResponse等 章节来源 - [server/src/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) ## 依赖关系分析 - 组件耦合 - 控制器仅依赖服务接口,低耦合 - 服务层通过工厂选择插件,便于替换与扩展 - 存储服务对上层透明,对下层可替换 - 外部依赖 - HTTP/WS调用第三方TTS - FFmpeg/ffprobe用于合并与时长探测 - OSS SDK用于对象存储 - 循环依赖 - 未见循环导入;服务与插件通过函数调用解耦 ```mermaid graph LR CTRL["tts.controller.ts"] --> SVC["tts.service.ts"] SVC --> ALI["aliyun.provider.ts"] SVC --> MINI["minimax.provider.ts"] SVC --> MOCK["mock.provider.ts"] SVC --> RT["aliyun-realtime.provider.ts"] SVC --> MERGE["audio-merger.ts"] SVC --> STORE["storage.service.ts"] STORE --> OSS["oss.service.ts"] APP["app.ts"] --> CTRL APP --> CFG["config/index.ts"] APP --> TYPES["types/index.ts"] ``` 图表来源 - [server/src/app.ts:1-194](file://server/src/app.ts#L1-L194) - [server/src/modules/tts/tts.controller.ts:1-274](file://server/src/modules/tts/tts.controller.ts#L1-L274) - [server/src/modules/tts/tts.service.ts:1-715](file://server/src/modules/tts/tts.service.ts#L1-L715) - [server/src/modules/tts/aliyun.provider.ts:1-152](file://server/src/modules/tts/aliyun.provider.ts#L1-L152) - [server/src/modules/tts/minimax.provider.ts:1-280](file://server/src/modules/tts/minimax.provider.ts#L1-L280) - [server/src/modules/tts/mock.provider.ts:1-61](file://server/src/modules/tts/mock.provider.ts#L1-L61) - [server/src/modules/tts/aliyun-realtime.provider.ts:1-158](file://server/src/modules/tts/aliyun-realtime.provider.ts#L1-L158) - [server/src/modules/tts/audio-merger.ts:1-86](file://server/src/modules/tts/audio-merger.ts#L1-L86) - [server/src/services/storage.service.ts:1-278](file://server/src/services/storage.service.ts#L1-L278) - [server/src/services/oss.service.ts:1-256](file://server/src/services/oss.service.ts#L1-L256) - [server/src/config/index.ts:1-117](file://server/src/config/index.ts#L1-L117) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) ## 性能考量 - 并发与批处理 - 非MiniMax场景采用并行分段合成,提升吞吐 - MiniMax异步轮询较长,串行避免超时 - 重试与退避 - 速率限制与服务错误采用指数退避重试 - 存储与网络 - 云端URL优先,失败时本地降级并统一上传 - OSS签名URL用于私有桶下载 - 工具链 - FFmpeg/ffprobe用于高效合并与时长探测 章节来源 - [server/src/modules/tts/tts.service.ts:348-383](file://server/src/modules/tts/tts.service.ts#L348-L383) - [server/src/modules/tts/aliyun.provider.ts:125-141](file://server/src/modules/tts/aliyun.provider.ts#L125-L141) - [server/src/services/storage.service.ts:184-193](file://server/src/services/storage.service.ts#L184-L193) - [server/src/modules/tts/audio-merger.ts:69-85](file://server/src/modules/tts/audio-merger.ts#L69-L85) ## 故障排查指南 - 错误处理 - 控制器与服务层均抛出自定义错误,便于统一拦截 - 速率限制自动回退,非速率限制直接失败 - 日志与诊断 - 服务层写入本地日志文件,便于定位 - 应用启动时打印存储模式、上传目录、缓存状态 - 常见问题 - API Key缺失:插件构造时抛错,触发Mock回退 - 云端URL下载失败:自动降级到本地文件再上传 - WebSocket实时合成失败:检查权限与网络,考虑禁用实时模式 章节来源 - [server/src/middleware/errorHandler.js:1-41](file://server/src/middleware/errorHandler.js#L1-L41) - [server/src/modules/tts/tts.service.ts:268-279](file://server/src/modules/tts/tts.service.ts#L268-L279) - [server/src/modules/tts/aliyun.provider.ts:118-146](file://server/src/modules/tts/aliyun.provider.ts#L118-L146) - [server/src/services/storage.service.ts:160-176](file://server/src/services/storage.service.ts#L160-L176) - [server/src/app.ts:133-194](file://server/src/app.ts#L133-L194) ## 结论 平台通过“服务工厂 + 插件实现 + 统一存储”的架构,实现了TTS能力的可插拔扩展。开发者只需遵循统一接口与生命周期规范,即可快速接入新的TTS提供商、AI模型与存储后端。配合完善的错误处理、重试与性能优化策略,可在生产环境中稳定运行。 ## 附录 ### 插件开发模板(TTS提供商) - 必备接口 - 构造函数:读取配置(API Key/模型/音色映射) - synthesize(text, voiceId, params, outputPath, retries?, modelOverride?):返回本地路径或“cloud:”URL - 建议实现 - 明确错误类型(速率限制/服务错误/参数错误) - 支持重试与指数退避 - 提供最小可用的Mock实现以便联调 章节来源 - [server/src/modules/tts/aliyun.provider.ts:15-150](file://server/src/modules/tts/aliyun.provider.ts#L15-L150) - [server/src/modules/tts/minimax.provider.ts:45-278](file://server/src/modules/tts/minimax.provider.ts#L45-L278) - [server/src/modules/tts/mock.provider.ts:11-61](file://server/src/modules/tts/mock.provider.ts#L11-L61) ### 插件注册机制与依赖注入 - 注册机制 - 服务层通过工厂函数选择插件,无需硬编码依赖 - 配置中心提供模型与供应商列表,便于动态切换 - 依赖注入 - 插件通过构造函数注入配置 - 存储服务通过单例注入,对外透明 章节来源 - [server/src/modules/tts/tts.service.ts:163-190](file://server/src/modules/tts/tts.service.ts#L163-L190) - [server/src/config/index.ts:69-117](file://server/src/config/index.ts#L69-L117) - [server/src/services/storage.service.ts:13-28](file://server/src/services/storage.service.ts#L13-L28) ### 配置管理 - 环境变量 - STORAGE_TYPE:存储模式(oss/local) - DashScope/OSS相关环境变量:API Key、区域、Bucket、Endpoint、CDN域名 - 模型配置 - models.json统一管理供应商与模型,支持启用/禁用与类型过滤 章节来源 - [server/src/services/storage.service.ts:16-28](file://server/src/services/storage.service.ts#L16-L28) - [server/src/config/index.ts:83-117](file://server/src/config/index.ts#L83-L117) ### 插件间通信与事件 - WebSocket事件 - 生成完成后推送“音频生成完成”事件,携带bookId与chapterId - 回调机制 - onComplete回调在服务层执行,确保异步流程可控 章节来源 - [server/src/modules/tts/tts.service.ts:510-515](file://server/src/modules/tts/tts.service.ts#L510-L515) - [server/src/modules/tts/tts.service.ts:497-508](file://server/src/modules/tts/tts.service.ts#L497-L508) ### 最佳实践 - 插件实现 - 明确错误分类与重试策略 - 提供Mock实现,便于本地联调 - 服务层 - 优先级与回退策略清晰,避免单一故障点 - 统一上传与状态查询,保证一致性 - 存储层 - 云端URL优先,失败时本地降级 - OSS签名URL用于私有桶下载 章节来源 - [server/src/modules/tts/aliyun.provider.ts:118-146](file://server/src/modules/tts/aliyun.provider.ts#L118-L146) - [server/src/modules/tts/minimax.provider.ts:258-275](file://server/src/modules/tts/minimax.provider.ts#L258-L275) - [server/src/services/storage.service.ts:39-49](file://server/src/services/storage.service.ts#L39-L49)