151 lines
7.7 KiB
Markdown
151 lines
7.7 KiB
Markdown
# TTS 接口契约与适配边界
|
||
|
||
状态:Phase 0 审计基线,已补充旧 TTS 工程只读核查事实
|
||
审计日期:2026-09-08
|
||
重要说明:本文件将“已核实事实”和“目标契约”分开。已授权只读检查外部工程 `E:\RD\Kaotings\kts_site\KT26-0903_Big-TTS`,未复制或修改该工程。
|
||
|
||
## 1. 现有接口事实
|
||
|
||
| 项目 | 结论 | 证据/处理 |
|
||
| --- | --- | --- |
|
||
| 上游地址 | 代码默认:`http://43.248.188.28:44480`,路径 `/v1/audio/speech` | `ReadMe.md` 和 `server.js` 初始 SQLite 配置;不是实际运行地址证明 |
|
||
| 协议和方法 | `POST`,OpenAI 兼容 JSON 请求 | 旧工程 `/api/tts` 使用 `fetch` |
|
||
| 鉴权 | 配置有 API Key 时发送 `Authorization: Bearer <key>`;默认 Key 为空 | Key 只存旧工程服务端 SQLite,配置接口返回掩码 |
|
||
| 输入文本字段 | `input` | 旧工程将业务文本映射为 `input` |
|
||
| 音色 ID/语言 | `voice`;默认 `default`,逗号分隔配置;无真实语言清单 | 旧工程 `tts_config` 和前端 `/api/config` |
|
||
| 参数范围 | `response_format`: `wav`/`mp3`;`speed`: `0.5` 至 `2.0`;文本 `1` 至 `5000` 字符 | `server.js` 服务端校验 |
|
||
| 模型 | 默认 `qwen3-tts`,可由旧工程管理员配置 | `ReadMe.md`、`tts_config` |
|
||
| 同步/异步 | 同步 | 单次 `fetch` 等待完整响应,无 task ID |
|
||
| 结果格式 | 音频字节流;WAV `audio/wav`,MP3 `audio/mpeg` | 旧工程返回完整 `arrayBuffer` |
|
||
| 错误语义 | 输入错误 `400`;未登录 `401`;上游非 2xx/超时统一 `502` | 旧工程业务层映射 |
|
||
| 超时和大小限制 | 上游超时 `120000ms`;请求体最多 `1 MiB`;文本最多 `5000` 字符;未见上游响应大小限制 | `body()` 与 `AbortSignal.timeout(120000)` |
|
||
| 幂等支持 | 未实现 | 无幂等键、provider task ID 或重复请求去重 |
|
||
|
||
代码契约已核实;首次无鉴权请求返回 `401 Unauthorized`,配置服务端凭据后最小文本请求已返回 `200 audio/wav`。当前测试服务器没有 TTS 上游监听端口,业务 API 通过固定环境地址访问外部上游。
|
||
|
||
旧工程自身的业务接口为:登录后 `GET /api/config` 获取模型/音色元数据,`POST /api/tts` 同步返回音频,`GET /api/history` 返回当前用户最多 100 条历史;管理员配置接口为 `/api/admin/config`。Phase 3 只复用上游边界,不复制旧工程用户体系或整套工程。
|
||
|
||
`www_site` 不复用旧工程的网页端管理员配置接口。上游主机、API Key、超时和相关秘密只由服务端环境配置注入;网站用户和管理员均不能通过网页修改上游连接配置。
|
||
|
||
## 2. 业务层目标契约
|
||
|
||
以下是依据 `V1_PLAN.md` 第 9、10 章拟定的业务层边界。它是 Phase 2/3 的实现输入,不是上游协议。
|
||
|
||
### 2.1 公开业务 API
|
||
|
||
| 方法与路径 | 用途 | 认证 |
|
||
| --- | --- | --- |
|
||
| `GET /api/v1/tts/voices` | 返回当前可用音色及安全参数元数据 | 可公开,实际策略待定 |
|
||
| `POST /api/v1/tts/tasks` | 创建 TTS 任务,返回 `202` 和 `task_id` | 登录、限流、额度和并发校验 |
|
||
| `GET /api/v1/tts/tasks` | 当前用户分页历史 | 当前用户 |
|
||
| `GET /api/v1/tts/tasks/{id}` | 查询状态和结果元数据 | 所有者或管理员 |
|
||
| `GET /api/v1/tts/tasks/{id}/audio` | 受控播放 | 所有者或管理员 |
|
||
| `GET /api/v1/tts/tasks/{id}/download` | 受控下载 | 所有者或管理员 |
|
||
|
||
认证、账户和管理接口以 `V1_PLAN.md` 第 9 章为准。业务层统一使用同源 `/api/v1`,浏览器不直接访问上游 TTS 地址。
|
||
|
||
### 2.2 创建任务请求
|
||
|
||
下面是脱敏的目标样例,仅用于说明业务层字段;字段名、音色和参数必须在上游联调后固定。
|
||
|
||
```json
|
||
{
|
||
"text": "待转换文本",
|
||
"voice_id": "configured-voice-id",
|
||
"parameters": {
|
||
"format": "mp3"
|
||
},
|
||
"idempotency_key": "client-generated-opaque-key"
|
||
}
|
||
```
|
||
|
||
服务端必须重新计算 Unicode 码点计量、校验文本长度/音色/参数/权益/并发和频率,不能信任客户端计数或隐藏字段。旧工程会把完整原始文本写入 SQLite 历史,Phase 3 不直接复制该隐私行为。
|
||
|
||
### 2.3 创建成功响应
|
||
|
||
```json
|
||
{
|
||
"task_id": "uuid",
|
||
"status": "queued",
|
||
"text_length": 123,
|
||
"reserved_amount": 123,
|
||
"request_id": "request-id"
|
||
}
|
||
```
|
||
|
||
返回 `202 Accepted` 表示任务已持久化并冻结额度,不表示上游已成功生成音频。额度冻结和任务创建必须在同一数据库事务中完成。
|
||
|
||
### 2.4 状态响应
|
||
|
||
```json
|
||
{
|
||
"task_id": "uuid",
|
||
"status": "queued|running|succeeded|failed",
|
||
"text_length": 123,
|
||
"voice_id": "configured-voice-id",
|
||
"audio": {
|
||
"available": false,
|
||
"duration_ms": null,
|
||
"expires_at": null
|
||
},
|
||
"error": null,
|
||
"request_id": "request-id"
|
||
}
|
||
```
|
||
|
||
成功时 `audio` 只返回受控业务地址或短期授权结果,不返回存储桶内部路径。管理员默认不展开完整输入文本。
|
||
|
||
## 3. 适配器目标边界
|
||
|
||
`services/worker` 通过配置固定的上游主机和端点调用适配器;用户输入不能成为 URL、Host、路径或凭据。适配器负责:
|
||
|
||
- 将业务层标准请求映射为真实上游请求,并从真实响应提取 provider task ID、音频数据/地址和计量信息。
|
||
- 对上游鉴权、连接超时、读取超时、响应大小、MIME 和音频可解析性做服务端校验。
|
||
- 将真实上游错误映射到内部错误码,不向浏览器泄露内部地址、密钥、模型路径或堆栈。
|
||
- 在上游语义明确时实现有限重试;超时且结果不明时先保留 `running` 并按 provider task ID 核对,禁止盲目重复生成。
|
||
- 将音频写入私有对象存储后,才允许任务转为 `succeeded` 并把冻结额度转为消费。
|
||
|
||
适配器不负责用户授权、额度决策、跨用户资源判断或 CMS 权限;这些由 API/业务服务负责。
|
||
|
||
## 4. 失败语义基线
|
||
|
||
以下是业务层目标分类,不是对未核实上游返回码的断言:
|
||
|
||
| 内部错误码 | HTTP 建议 | 处理 |
|
||
| --- | ---: | --- |
|
||
| `AUTH_REQUIRED` | 401 | 不创建任务,不冻结额度 |
|
||
| `FORBIDDEN` | 403 | 不泄露资源存在性 |
|
||
| `INVALID_INPUT` | 422 | 文本、音色或参数不合法 |
|
||
| `QUOTA_EXCEEDED` | 409 | 不创建任务,不产生负余额 |
|
||
| `RATE_LIMITED` | 429 | 返回安全的重试提示 |
|
||
| `UPSTREAM_UNAVAILABLE` | 503 | 按任务状态处理,不盲目重试不确定请求 |
|
||
| `UPSTREAM_REJECTED` | 502 | 记录脱敏上游分类,失败时释放冻结 |
|
||
| `AUDIO_PERSIST_FAILED` | 500/503 | 不标记成功,执行对账/释放策略 |
|
||
| `TASK_FAILED` | 500 | 任务失败,保留可追踪错误码 |
|
||
| `AUDIO_EXPIRED` | 410 | 保留历史元信息,不返回内部路径 |
|
||
|
||
错误响应统一使用:
|
||
|
||
```json
|
||
{
|
||
"error": {
|
||
"code": "INVALID_INPUT",
|
||
"message": "请求参数不可用",
|
||
"request_id": "request-id"
|
||
}
|
||
}
|
||
```
|
||
|
||
不记录密码、会话令牌、验证码、上游密钥或完整原始文本。
|
||
|
||
## 5. 待确认清单和验证顺序
|
||
|
||
1. 确认 `43.248.188.28:44480` 是否仍是获授权的测试上游;代码默认值不作为部署事实。
|
||
2. 提供该上游测试环境的 API Key 或其他鉴权凭据注入方式;本次无鉴权最小请求返回 `401`,未保存或输出响应内容。
|
||
3. 获取当前音色 ID、语言、参数和计量补充资料;旧工程只有 `default` 示例,没有真实清单。
|
||
4. 确认上游是否支持幂等、取消、重试和 provider task ID 查询;当前旧工程不提供这些能力。
|
||
5. 在测试环境执行最小成功、参数拒绝、超时、上游失败、重复请求和响应不明测试;不得用 Mock 结果替代。
|
||
6. 依据真实结果固定 `TTSVoice`、`TTSTask`、错误映射、超时、重试、音频校验和额度计量配置。
|
||
|
||
在上述步骤完成前,Phase 3 不得宣称“真实 TTS 已接入”。
|