TTS-API

TTS 版 New-API 架构设计 · 多 Provider 统一 TTS 网关 · 2026-05-21

1. 项目定位

参考 new-api 的设计理念,TTS-API 定位为企业级 TTS 统一网关与资产管理平台,核心能力:

能力维度说明
统一接入以 OpenAI /v1/audio/speech 为唯一入口,屏蔽火山引擎、阿里、Azure、讯飞等上游差异
统一音色定义标准音色命名体系,自动映射到各 Provider 的实际音色 ID
统一计费按字符数 / 时长计费,支持配额管理与成本核算
统一治理权限分组、速率限制、渠道故障切换、审计日志、可视化看板

2. 与 new-api 的关键差异

维度new-api(LLM)TTS-API(本项目)
核心接口/v1/chat/completions/v1/audio/speech
协议转换OpenAI ↔ Claude ↔ Gemini 互转只需转到各 Provider 原生格式(单向)
模型映射模型名 → 渠道选择音色映射:标准 voice → 各 Provider 实际音色 ID
(这是最大难点)
输出处理文本 / JSON 流二进制音频流,需处理格式转换(wav/mp3/pcm)
计费单位Token 数字符数 + 音频时长
缓存语义缓存(相同问题命中)音频缓存(相同文本+音色 → 直接返回已合成音频)
流式SSE 文本流音频流式推送(边合成边返回,首字节延迟是关键指标)

3. 整体分层架构

┌─────────────────────────────────────────────────────────────────┐ │ 客户端 / 应用层 │ │ OpenAI SDK │ REST API │ Web 管理后台 │ └────────────────────────────┬────────────────────────────────────┘ │ ┌────────────────────────────▼────────────────────────────────────┐ │ Gin HTTP Server │ │ ┌──────────────────────────────────────────────────────────────┐│ │ │ 路由层 (router/) ││ │ │ /v1/audio/speech /api/* (管理) /web/* (前端静态) ││ │ └──────────────────────────────────────────────────────────────┘│ └────────────────────────────┬────────────────────────────────────┘ │ ┌────────────────────────────▼────────────────────────────────────┐ │ 中间件层 (middleware/) │ │ 认证(JWT/API Key) │ 限流(IP/用户) │ 日志 │ CORS │ 请求分发 │ └────────────────────────────┬────────────────────────────────────┘ │ ┌────────────────────────────▼────────────────────────────────────┐ │ 控制器层 (controller/) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │ │ 语音合成 │ │ 用户管理 │ │ 渠道管理 │ │ 计费 & 统计 │ │ │ │ controller│ │controller │ │controller │ │ controller │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ └────────────────────────────┬────────────────────────────────────┘ │ ┌─────────────────────┼─────────────────────┐ │ │ │ ┌──────▼──────┐ ┌────────▼────────┐ ┌───────▼──────┐ │ 服务层 │ │ 适配器层 │ │ 数据层 │ │ (service/) │ │ (adapter/) │ │ (model/) │ │ │ │ │ │ │ │ · 配额管理 │ │ 接口定义 │ │ GORM ORM │ │ · 音频缓存 │ │ · volcano │ │ │ │ · 音色映射 │ │ · aliyun │ │ │ │ · 格式转换 │ │ · azure │ │ │ │ · 计费服务 │ │ · tencent │ │ │ │ · 渠道调度 │ │ · xunfei │ │ │ └──────────────┘ │ · openai │ └───────┬──────┘ │ · fish_audio │ │ │ · bert_vits │ ┌───────┼───────┐ └─────────────────┘ │ │ │ ┌──────▼──┐ ┌──▼──┐ ┌─▼────┐ │ SQLite │ │MySQL│ │ PG │ └─────────┘ └─────┘ └──────┘

4. 请求处理全流程

客户端发送 OpenAI 格式 TTS 请求 │ ▼ [1] Gin 路由匹配 → /v1/audio/speech │ ▼ [2] 中间件链:认证(API Key) → 用户级限流 → 请求日志 │ ▼ [3] 控制器:解析请求 { model, input, voice, speed, response_format } │ ▼ [4] 音色映射服务:标准 voice 名 → 查找可用渠道 → 映射为渠道实际音色ID │ 例: "gentle_male" → 火山引擎(zh_male_qingxin) │ → Azure(zh-CN-YunxiNeural) │ → 阿里(cosyvoice-v1-longxiaochun) ▼ [5] 渠道调度器:按权重+可用性选择最优渠道,失败自动切换 │ ▼ [6] 适配器:将 OpenAI 请求转为 Provider 原生格式,发送请求 │ ▼ [7] 音频处理:接收二进制音频 → 格式转换(如需) → 写入音频缓存 │ ▼ [8] 计费结算:按字符数/时长扣费,记录日志 │ ▼ [9] 返回响应:Content-Type: audio/wav,流式或整段返回

5. 核心设计:适配器接口

参考 new-api 的 Adaptor 接口设计,TTS 版适配器接口如下:

// adapter.go — TTS Provider 统一接口 type TTSAdapter interface { // 初始化:传入渠道配置(API Key / Resource ID / 默认音色等) Init(info *TTSRelayInfo) error // 构建上游请求 URL BuildRequestURL(info *TTSRelayInfo) (string, error) // 设置请求头(鉴权、Content-Type 等) SetupRequestHeader(c *gin.Context, req *http.Request, info *TTSRelayInfo) error // 核心:将 OpenAI 格式请求转为 Provider 原生请求体 ConvertRequest(info *TTSRelayInfo, req *dto.OpenAITTSRequest) (any, error) // 发送请求到上游 DoRequest(c *gin.Context, info *TTSRelayInfo, body io.Reader) (*http.Response, error) // 处理上游响应:提取音频、统计字符数/时长、返回标准结构 DoResponse(c *gin.Context, resp *http.Response, info *TTSRelayInfo) (*dto.TTSUsage, *dto.TTSError) // 返回此渠道支持的音色列表(用于音色映射表构建) GetVoiceList() []ProviderVoice // 渠道标识 GetChannelName() string // 是否支持流式 TTS SupportStreaming() bool } // ProviderVoice 各 Provider 的音色结构 type ProviderVoice struct { ProviderID string // Provider 内部音色 ID,如 "zh_female_qingxin" Language string // zh-CN / en-US / ja-JP Gender string // male / female Style string // 风格标签,如 "news" / "story" / "chat" Description string // 音色描述 }

6. 核心设计:音色映射系统

这是 TTS 网关区别于 LLM 网关的最大难点与核心创新点。LLM 网关只需按模型名路由,但 TTS 需要一套跨 Provider 的音色统一体系。

标准音色命名空间 ┌──────────────────────────────────┐ │ tts-1-gentle-male │ │ tts-1-gentle-female │ │ tts-1-news-male │ │ tts-1-story-female │ │ tts-1-casual-male │ │ ... │ └──────────┬───────────────────────┘ │ 音色映射表 (voice_mapping) │ ┌───────────────┼───────────────┬───────────────┐ │ │ │ │ ▼ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 火山引擎 │ │ Azure │ │ 阿里 │ │ 讯飞 │ │ │ │ │ │ │ │ │ │zh_male_ │ │zh-CN- │ │cosyvoice│ │x4_ling │ │qingxin │ │Yunxi │ │-v1-long │ │xiaoxuan │ │ │ │Neural │ │xiaochun │ │ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘

6.1 音色映射表结构

// voice_mapping 表 (数据库) type VoiceMapping struct { ID uint StandardVoice string // "tts-1-gentle-male" ChannelID uint // 渠道 ID ProviderVoice string // Provider 原始音色 ID Priority int // 优先级(同一标准音色多渠道时,优先选谁) IsDefault bool // 是否为该标准音色的默认渠道 } // 示例数据: // standard_voice | channel | provider_voice | priority // tts-1-gentle-male | 火山引擎 | zh_male_qingxin | 1 // tts-1-gentle-male | Azure | zh-CN-YunxiNeural | 2 // tts-1-gentle-male | 阿里 | cosyvoice-v1-longxiaochun| 3

6.2 音色发现与自动映射建议

每个 Provider 适配器实现 GetVoiceList(),系统启动或渠道更新时自动拉取,通过语言+性别+风格标签与标准命名空间做相似度匹配,自动生成映射建议,管理员在 Web UI 审核确认即可。

7. 渠道调度与故障切换

请求 → 查找"tts-1-gentle-male"可用的渠道列表 │ ▼ 按 priority 排序 → 加权随机选择一个渠道 │ ▼ 适配器发送请求 → 成功? ├── 是 → 返回音频,记录成功 │ └── 否 → 标记渠道失败 │ ▼ 自动切换 priority+1 的渠道重试 │ ▼ 所有渠道失败 → 返回 503 + 错误详情

8. 项目目录结构

tts-api/ ├── main.go # 入口:初始化 DB、路由、启动服务 ├── go.mod / go.sum ├── .env.example # 环境变量示例 ├── Dockerfile # 多阶段构建 ├── docker-compose.yml │ ├── router/ # 路由层 │ ├── main.go # 路由聚合 │ ├── api-router.go # /api/* 管理接口 │ ├── relay-router.go # /v1/audio/speech TTS 代理 │ └── web-router.go # /web/* 管理后台静态资源 │ ├── middleware/ # 中间件 │ ├── auth.go # JWT + API Key 认证 │ ├── rate-limit.go # 用户/IP 级别限流 │ ├── cors.go # 跨域 │ └── logger.go # 请求日志 │ ├── controller/ # 控制器 │ ├── tts.go # TTS 合成入口(核心) │ ├── channel.go # 渠道 CRUD │ ├── user.go # 用户管理 │ ├── token.go # API Key 管理 │ ├── voice.go # 音色映射管理 │ └── billing.go # 计费统计 │ ├── service/ # 服务层 │ ├── voice_mapping/ # 音色映射服务(核心) │ │ └── matcher.go # 自动匹配 & 建议 │ ├── channel_scheduler/ # 渠道调度(权重/故障切换) │ │ └── scheduler.go │ ├── audio_cache/ # 音频缓存(相同文本+音色命中) │ │ └── cache.go │ ├── audio_convert/ # 音频格式转换(ffmpeg 封装) │ │ └── converter.go │ ├── billing/ # 计费服务 │ │ └── billing.go │ └── quota/ # 配额管理 │ └── quota.go │ ├── adapter/ # 适配器层(核心!) │ ├── adapter.go # TTSAdapter 接口定义 │ ├── volcano/ # 火山引擎 TTS │ │ └── volcano.go │ ├── aliyun/ # 阿里云 CosyVoice / 百炼 │ │ └── aliyun.go │ ├── azure/ # 微软 Azure TTS │ │ └── azure.go │ ├── tencent/ # 腾讯云 TTS │ │ └── tencent.go │ ├── xunfei/ # 讯飞 TTS │ │ └── xunfei.go │ ├── openai/ # OpenAI TTS(基准) │ │ └── openai.go │ ├── fish_audio/ # Fish Audio(开源) │ │ └── fish_audio.go │ └── bert_vits/ # Bert-VITS2(开源自建) │ └── bert_vits.go │ ├── model/ # 数据模型 (GORM) │ ├── user.go │ ├── channel.go # 渠道(Provider 配置) │ ├── token.go # API Key / Token │ ├── voice_mapping.go # 音色映射 │ ├── usage_record.go # 用量记录 │ └── audio_cache.go # 音频缓存记录 │ ├── dto/ # 请求/响应结构体 │ ├── openai_tts.go # OpenAI TTS 请求/响应格式 │ ├── relay_info.go # 中继上下文(TTSRelayInfo) │ └── common.go # 通用响应 │ ├── setting/ # 配置管理 (Viper) │ └── setting.go │ ├── common/ # 通用工具 │ ├── utils.go │ └── constants.go │ └── web/ # React 管理后台 ├── src/ │ ├── pages/ │ │ ├── Dashboard # 数据看板 │ │ ├── Channels # 渠道管理 │ │ ├── VoiceMapping # 音色映射配置 │ │ ├── Users # 用户管理 │ │ ├── Tokens # API Key │ │ ├── Billing # 计费 & 用量 │ │ └── Logs # 调用日志 │ └── ... └── package.json

9. 管理后台页面规划

页面功能
Dashboard今日合成次数、字符数、时长、费用、渠道健康状态、QPS 曲线
渠道管理添加/编辑 Provider(API Key、Resource ID、权重、并发上限)
音色映射核心页面:标准音色 ↔ 各渠道音色 ID 的映射表,支持自动匹配建议与手动调整
API Key生成/管理用户 API Key,绑定分组与配额
用户管理用户 CRUD、分组、角色(Admin / User)
计费统计按用户/渠道/日期维度的用量与费用报表
调用日志每次 TTS 请求的详细日志(文本、音色、渠道、耗时、费用)

10. 一期 vs 二期路线图

一期(MVP,你现有的 Volcano-Engine-TTS-UI 升级版)

模块内容
适配器火山引擎 + Azure + 阿里云,3 个 Provider
接口/v1/audio/speech,OpenAI 兼容
音色映射硬编码映射表(配置文件),先跑通再抽象
计费简单字符数计数 + 日志
管理后台极简版:渠道配置页面 + 用量看板
数据库SQLite,单文件部署

二期(完整版)

模块内容
适配器扩到 8+ Provider(讯飞、腾讯、Fish Audio、Bert-VITS2、OpenAI)
音色映射数据库驱动 + Web UI 可视化管理 + 自动匹配建议
计费字符数/时长双维度计费,用户配额,欠费阻断
缓存Redis 音频缓存,相同文本+音色直接命中
流式支持流式 TTS(SSE 推送音频 chunk),降低首字节延迟
管理后台完整 React 后台(参考 new-api 的 Semi Design UI)
数据库MySQL / PostgreSQL 支持
部署Docker Compose 一键部署

11. 关键工程建议

  1. 从你现有的火山引擎适配器起步,先抽象出 TTSAdapter 接口,接入 2~3 个 Provider 验证接口设计是否合理,不要一上来就搞 8 个适配器。
  2. 音色映射先硬编码,跑通流程后再做成数据库驱动的 Web UI。映射表是长期维护工作,需要社区共建。
  3. 音频格式转换用 ffmpeg,Go 侧通过 exec.Command 调用或使用 go-ffmpeg 绑定。各 Provider 输出格式不同(wav / mp3 / pcm),统一转码是刚需。
  4. 渠道调度直接复用 new-api 的加权随机 + 故障重试思路,这是成熟的模式,不需要重新发明。
  5. 管理后台前期可以不写,SQLite + 配置文件就能用;等 Provider 多了再补 React 前端。
  6. 考虑直接 fork new-api 改造:new-api 的渠道管理、用户系统、计费框架、中间件、部署方案都是现成的,你只需要把 relay 层的 LLM 适配器替换成 TTS 适配器,再加音色映射模块。这比从零搭建快得多。