插件开发.md 22 KB

插件开发

本文引用的文件

  • server/src/app.ts
  • server/src/config/index.ts
  • server/src/types/index.ts
  • server/src/modules/tts/tts.controller.ts
  • server/src/modules/tts/tts.service.ts
  • server/src/modules/tts/aliyun.provider.ts
  • server/src/modules/tts/minimax.provider.ts
  • server/src/modules/tts/mock.provider.ts
  • server/src/modules/tts/aliyun-realtime.provider.ts
  • server/src/modules/tts/audio-merger.ts
  • server/src/services/storage.service.ts
  • server/src/services/oss.service.ts
  • server/src/middleware/errorHandler.js

目录

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

简介

本文件面向希望为AI有声书生成平台开发“插件”的工程师,系统讲解如何开发三类插件:

  • TTS音色提供商插件:对接不同厂商的语音合成能力
  • AI模型插件:扩展文本生成、理解等LLM能力
  • 存储插件:统一管理本地与云存储(如OSS)

文档覆盖插件架构设计、接口规范、生命周期管理、注册机制、依赖注入与配置管理,并提供开发模板、最佳实践与调试技巧,以及插件间通信、错误处理与性能优化策略。

项目结构

平台采用模块化与分层架构:

  • 应用入口负责中间件、静态资源、路由注册与服务初始化
  • 配置中心集中管理模型与第三方服务配置
  • TTS模块负责音色合成、文本分段、并发与合并、状态查询
  • 存储模块统一抽象本地与OSS,屏蔽差异
  • 中间件提供错误处理、安全与性能监控

    graph TB
    subgraph "应用层"
    APP["应用入口<br/>server/src/app.ts"]
    ROUTER["路由注册<br/>TTS/业务路由"]
    end
    subgraph "服务层"
    TTS_CTRL["TTS控制器<br/>tts.controller.ts"]
    TTS_SVC["TTS服务<br/>tts.service.ts"]
    STORAGE["存储服务<br/>storage.service.ts"]
    OSS["OSS服务<br/>oss.service.ts"]
    end
    subgraph "插件层"
    ALIYUN["阿里云TTS插件<br/>aliyun.provider.ts"]
    MINIMAX["MiniMax TTS插件<br/>minimax.provider.ts"]
    MOCK["Mock TTS插件<br/>mock.provider.ts"]
    REALTIME["阿里云实时TTS插件<br/>aliyun-realtime.provider.ts"]
    MERGER["音频合并器<br/>audio-merger.ts"]
    end
    subgraph "配置与类型"
    CFG["配置中心<br/>config/index.ts"]
    TYPES["类型定义<br/>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
  • server/src/modules/tts/tts.controller.ts:1-274
  • server/src/modules/tts/tts.service.ts:1-715
  • server/src/modules/tts/aliyun.provider.ts:1-152
  • server/src/modules/tts/minimax.provider.ts:1-280
  • server/src/modules/tts/mock.provider.ts:1-61
  • server/src/modules/tts/aliyun-realtime.provider.ts:1-158
  • server/src/modules/tts/audio-merger.ts:1-86
  • server/src/services/storage.service.ts:1-278
  • server/src/services/oss.service.ts:1-256
  • server/src/config/index.ts:1-117
  • server/src/types/index.ts:1-124

章节来源

  • server/src/app.ts:1-194
  • server/src/config/index.ts:1-117
  • server/src/types/index.ts:1-124

核心组件

  • 应用入口与中间件
    • 负责全局中间件(CORS、日志、安全、限流、Sentry)、静态资源挂载、路由注册与优雅关闭
    • 初始化数据库、Redis、存储、WebSocket、书籍生成队列
  • 配置中心
    • 统一加载.env与models.json,提供模型枚举、启用筛选、错误识别与自动切换辅助
  • TTS控制器与服务
    • 控制器负责参数校验、配额检查、路由转发
    • 服务负责文本分段、并发合成、合并、上传、状态查询、回调与WebSocket推送
  • 存储服务
    • 抽象本地与OSS,提供上传/下载/删除/签名URL/目录清理等能力
  • 插件(TTS提供商)
    • 阿里云HTTP/TTS、MiniMax异步、Mock占位、阿里云实时WebSocket
  • 音频合并器
    • 支持本地与远程URL的合并与时长探测

章节来源

  • server/src/app.ts:1-194
  • server/src/config/index.ts:1-117
  • server/src/modules/tts/tts.controller.ts:1-274
  • server/src/modules/tts/tts.service.ts:1-715
  • server/src/services/storage.service.ts:1-278
  • server/src/modules/tts/aliyun.provider.ts:1-152
  • server/src/modules/tts/minimax.provider.ts:1-280
  • server/src/modules/tts/mock.provider.ts:1-61
  • server/src/modules/tts/aliyun-realtime.provider.ts:1-158
  • server/src/modules/tts/audio-merger.ts:1-86

架构总览

TTS插件体系通过“服务工厂 + 插件实现 + 统一存储”的方式解耦。服务层根据配置与优先级选择具体插件,插件负责与外部API交互,最终由存储服务统一对外暴露URL。

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
  • server/src/modules/tts/tts.service.ts:200-542
  • server/src/modules/tts/aliyun.provider.ts:21-150
  • server/src/modules/tts/minimax.provider.ts:234-278
  • server/src/modules/tts/mock.provider.ts:12-60
  • server/src/modules/tts/audio-merger.ts:9-36
  • server/src/services/storage.service.ts:43-49
  • server/src/services/oss.service.ts:91-94

详细组件分析

TTS控制器(接口与生命周期)

  • 职责
    • 参数校验、配额检查、路由转发至服务层
    • 生命周期:请求进入 -> 校验 -> 调用服务 -> 返回任务ID/状态
  • 关键点

    • 支持可选鉴权、字数限制、书籍归属与章节标题
    • 生成成功后进行配额消耗
    • 提供状态查询、预览生成、下载信息与批量下载

      flowchart TD
      Start(["请求进入 /api/tts/generate"]) --> Validate["参数校验<br/>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

章节来源

  • server/src/modules/tts/tts.controller.ts:1-274

TTS服务(工厂、优先级与回退)

  • 职责
    • 文本分段、并发合成、合并、上传、状态查询、回调与WebSocket推送
    • 插件优先级:MiniMax -> 阿里云HTTP -> Mock
    • 额度限制错误自动回退到下一个插件
  • 关键点

    • MiniMax异步长文本无需分段;阿里云HTTP需分段
    • 并发策略:MiniMax串行,其他并行
    • 云端URL降级到本地文件再统一上传

      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

章节来源

  • server/src/modules/tts/tts.service.ts:1-715

TTS插件(接口规范与实现要点)

  • 接口规范
    • 统一方法:synthesize(text, voiceId, params, outputPath, retries?, modelOverride?)
    • 返回值:本地文件路径或“cloud:”前缀的云端URL
    • 错误处理:区分速率限制与服务错误,支持指数退避重试
  • 实现要点

    • 阿里云HTTP:支持指令模型参数拼装、云端URL回退
    • MiniMax异步:创建任务 -> 轮询 -> tar提取MP3
    • Mock:FFmpeg生成占位音频,失败时写入最小MP3头
    • 阿里云实时:WebSocket流式合成,适合长文本

      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
  • server/src/modules/tts/minimax.provider.ts:42-280
  • server/src/modules/tts/mock.provider.ts:11-61
  • server/src/modules/tts/aliyun-realtime.provider.ts:11-158

章节来源

  • server/src/modules/tts/aliyun.provider.ts:1-152
  • server/src/modules/tts/minimax.provider.ts:1-280
  • server/src/modules/tts/mock.provider.ts:1-61
  • server/src/modules/tts/aliyun-realtime.provider.ts:1-158

存储插件(统一抽象与OSS)

  • 职责
    • 本地与OSS无缝切换,提供上传/下载/删除/签名URL/目录清理
    • 通过环境变量STORAGE_TYPE切换模式
  • 关键点

    • OSS服务封装OSS SDK,支持对象键规范化、CDN域名回源
    • 存储服务在本地模式下直接写入uploads目录

      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
  • server/src/services/oss.service.ts:13-256

章节来源

  • server/src/services/storage.service.ts:1-278
  • server/src/services/oss.service.ts:1-256

音频合并器(跨域与本地处理)

  • 职责
    • 合并本地或多段远程URL音频,计算时长
    • 远程URL通过FFmpegProcessor处理,本地使用FFmpeg concat
  • 关键点
    • 单文件直接复制,避免不必要的转码
    • 输出格式自动适配

章节来源

  • server/src/modules/tts/audio-merger.ts:1-86

配置与类型(模型与参数)

  • 配置中心
    • 加载.env与models.json,提供模型枚举、启用筛选、错误识别与自动切换辅助
    • TTS相关:DashScope API Key、模型列表、实时模型开关
  • 类型定义
    • VoiceParams、Voice、IUser、IAudio、ApiResponse等

章节来源

  • server/src/config/index.ts:1-117
  • server/src/types/index.ts:1-124

依赖关系分析

  • 组件耦合
    • 控制器仅依赖服务接口,低耦合
    • 服务层通过工厂选择插件,便于替换与扩展
    • 存储服务对上层透明,对下层可替换
  • 外部依赖
    • HTTP/WS调用第三方TTS
    • FFmpeg/ffprobe用于合并与时长探测
    • OSS SDK用于对象存储
  • 循环依赖

    • 未见循环导入;服务与插件通过函数调用解耦

      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
  • server/src/modules/tts/tts.controller.ts:1-274
  • server/src/modules/tts/tts.service.ts:1-715
  • server/src/modules/tts/aliyun.provider.ts:1-152
  • server/src/modules/tts/minimax.provider.ts:1-280
  • server/src/modules/tts/mock.provider.ts:1-61
  • server/src/modules/tts/aliyun-realtime.provider.ts:1-158
  • server/src/modules/tts/audio-merger.ts:1-86
  • server/src/services/storage.service.ts:1-278
  • server/src/services/oss.service.ts:1-256
  • server/src/config/index.ts:1-117
  • server/src/types/index.ts:1-124

性能考量

  • 并发与批处理
    • 非MiniMax场景采用并行分段合成,提升吞吐
    • MiniMax异步轮询较长,串行避免超时
  • 重试与退避
    • 速率限制与服务错误采用指数退避重试
  • 存储与网络
    • 云端URL优先,失败时本地降级并统一上传
    • OSS签名URL用于私有桶下载
  • 工具链
    • FFmpeg/ffprobe用于高效合并与时长探测

章节来源

  • server/src/modules/tts/tts.service.ts:348-383
  • server/src/modules/tts/aliyun.provider.ts:125-141
  • server/src/services/storage.service.ts:184-193
  • server/src/modules/tts/audio-merger.ts:69-85

故障排查指南

  • 错误处理
    • 控制器与服务层均抛出自定义错误,便于统一拦截
    • 速率限制自动回退,非速率限制直接失败
  • 日志与诊断
    • 服务层写入本地日志文件,便于定位
    • 应用启动时打印存储模式、上传目录、缓存状态
  • 常见问题
    • API Key缺失:插件构造时抛错,触发Mock回退
    • 云端URL下载失败:自动降级到本地文件再上传
    • WebSocket实时合成失败:检查权限与网络,考虑禁用实时模式

章节来源

  • server/src/middleware/errorHandler.js:1-41
  • server/src/modules/tts/tts.service.ts:268-279
  • server/src/modules/tts/aliyun.provider.ts:118-146
  • server/src/services/storage.service.ts:160-176
  • server/src/app.ts:133-194

结论

平台通过“服务工厂 + 插件实现 + 统一存储”的架构,实现了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
  • server/src/modules/tts/minimax.provider.ts:45-278
  • server/src/modules/tts/mock.provider.ts:11-61

插件注册机制与依赖注入

  • 注册机制
    • 服务层通过工厂函数选择插件,无需硬编码依赖
    • 配置中心提供模型与供应商列表,便于动态切换
  • 依赖注入
    • 插件通过构造函数注入配置
    • 存储服务通过单例注入,对外透明

章节来源

  • server/src/modules/tts/tts.service.ts:163-190
  • server/src/config/index.ts:69-117
  • server/src/services/storage.service.ts:13-28

配置管理

  • 环境变量
    • STORAGE_TYPE:存储模式(oss/local)
    • DashScope/OSS相关环境变量:API Key、区域、Bucket、Endpoint、CDN域名
  • 模型配置
    • models.json统一管理供应商与模型,支持启用/禁用与类型过滤

章节来源

  • server/src/services/storage.service.ts:16-28
  • server/src/config/index.ts:83-117

插件间通信与事件

  • WebSocket事件
    • 生成完成后推送“音频生成完成”事件,携带bookId与chapterId
  • 回调机制
    • onComplete回调在服务层执行,确保异步流程可控

章节来源

  • server/src/modules/tts/tts.service.ts:510-515
  • server/src/modules/tts/tts.service.ts:497-508

最佳实践

  • 插件实现
    • 明确错误分类与重试策略
    • 提供Mock实现,便于本地联调
  • 服务层
    • 优先级与回退策略清晰,避免单一故障点
    • 统一上传与状态查询,保证一致性
  • 存储层
    • 云端URL优先,失败时本地降级
    • OSS签名URL用于私有桶下载

章节来源

  • server/src/modules/tts/aliyun.provider.ts:118-146
  • server/src/modules/tts/minimax.provider.ts:258-275
  • server/src/services/storage.service.ts:39-49