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