www_site/docs/API_CONTRACT.md

161 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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` 校验;真实上游目前只实测 WAV、speed=1 |
| 模型 | 默认 `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 通过固定环境地址访问外部上游。
### 1.1 V1 已验证最小能力
- `provider_voice_id=default`
- 同步 `POST` 生成。
- `response_format=wav`
- `speed=1`
- 最小中文文本成功返回音频;业务任务、私有保存、历史、回放、下载和额度消费已走通一次。
以下能力仍不能写成已通过MP3、非 1.0 语速、其他音色/语言、provider task ID、异步查询、取消、上游幂等和安全重试。
旧工程自身的业务接口为:登录后 `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 创建任务请求
下面是当前业务层请求样例V1 最小实现只允许 `default`、WAV 和 `speed=1`。字段名和服务端规则已经固定,上游高级参数不在本版默认开放。
```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 已接入”。