# ASR 语音转文本接入

更新日期：2026-10-26。API 根地址：`https://work.zingyang.com/api`。

ASR（Automatic Speech Recognition）即自动语音识别，将音频转成文本。本指南介绍当前已有的 **Talk 短语音识别接口**，适用于语音输入、短句转写。接口同步返回文本，不创建正式录音会议、处理任务或纪要；不是实时流式转写接口。TTS（文字转语音）是另一种能力。

## 1. 身份、租户与套餐

每次请求携带：

```http
X-Access-Token: <平台登录token>
X-Tenant-Id: <当前租户ID>
```

用户必须有效且已登录；租户必须存在、启用并处于有效期内，当前用户须为正常成员。识别前检查租户的 `TALK_AI_PROCESS_MINUTES` 有效权益及可用余量，不以普通大模型 token 套餐替代。当前检查按至少 1 个额度单位判断准入，不代表本接口已经实现逐秒结算；不要把准入检查解释为完整扣费记录。

音频上传另外要求存储权益与余量。模型和供应商由服务端配置，客户端不提交厂商 API Key、模型密钥或自定义上游地址。

## 2. 先上传，再识别

1. 按 [COS 直传文档](/ios-cos-upload/) 完成 prepare → COS PUT → record，取得已登记 `fileId`；秒传命中时直接使用返回的文件 ID。
2. 保持同一登录用户与租户，用 `fileId` 调用本页接口。文件读取校验归属、生命周期以及实际字节与登记摘要的一致性。
3. 读取 `result.text`；无语音时提示重录，不将空文本提交给 AI 对话。

不能传本地路径、外部 URL、COS object key 或其他用户的文件 ID 替代 `fileId`。不要把二进制文件上传到此接口，也不要调用已删除的 `/sys/common/upload`。

## 3. 请求接口

```http
POST /talk/v1/ai/search/audio
Content-Type: application/x-www-form-urlencoded
```

| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| fileId | string，表单或查询参数 | 是 | COS 上传完成后得到的登记文件 ID |
| seconds | integer，表单或查询参数 | 否 | 客户端测量的音频时长，单位秒；建议向上取整并传正整数 |

参数通过 `@RequestParam` 接收，**不要发送 JSON 请求体**。接口不接受语言、model、stream 等参数。

```bash
curl --request POST 'https://work.zingyang.com/api/talk/v1/ai/search/audio' \
  --header 'X-Access-Token: <平台token>' \
  --header 'X-Tenant-Id: <当前租户ID>' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'fileId=<已登记文件ID>' \
  --data-urlencode 'seconds=8'
```

AI 工具代用户调用时，先取得用户对音频上传及识别的授权，并按平台规则携带 `X-Zing-Ai-Context: 1`、`X-Open-Confirm: confirmed`。普通应用请求不需要自行标记为 AI 工具操作。

## 4. 音频限制

当前代码兜底上限为 **10 MiB、60 秒**，配置中心可调整，最终以目标环境和接口错误为准；上传层及供应商还可能有更严格的限制。

当前服务端允许的文件扩展名：`m4a`、`mp3`、`wav`、`aac`、`flac`、`mp4`、`caf`、`opus`、`ogg`、`webm`、`amr`。扩展名通过不等于当前供应商支持所有容器、编码、采样率或语言；须使用实际供应商支持的音频格式，不要仅修改文件后缀。

`seconds` 目前是客户端声明值，代码只对已提供的值检查最大时长，没有在该方法里解析音频真实时长。客户端应真实测量并限制录音时长，不能省略字段来绕过限制。本接口不承诺长录音处理；正式会议录音使用已有录音上传与异步处理链路，不能直接套用本页请求。

## 5. 成功响应

```json
{
  "success": true,
  "code": 200,
  "message": "",
  "result": {
    "text": "请帮我查一下今天的会议。",
    "filename": "voice.m4a",
    "tenant_id": 1234
  },
  "timestamp": 1792972800000
}
```

| 字段 | 含义 |
|---|---|
| text | 去除首尾空白后的识别文本 |
| filename | 服务端规范化后的文件名，仅保留文件名部分 |
| tenant_id | 本次校验的租户 ID |
| emptied_reason | 识别完成但无文本时为 `NO_SPEECH`；有文本时通常不存在 |

无可识别人声也可能返回成功，此时 `text` 为空、`emptied_reason` 为 `NO_SPEECH`。客户端提示“未识别到语音，请重新录制”，不要当作非空结果自动发送。本接口不返回逐字时间戳、说话人标签、会议 ID 或 SSE 事件。

## 6. 错误与重试

同时检查 HTTP 状态、标准响应的 `success`、数值 `code` 和 `message`，不要假定全部错误都是 500。

| 场景 | 常见状态／处理 |
|---|---|
| 未登录、用户失效 | 401；恢复登录 |
| 租户无效、成员关系不满足 | 403；核对当前租户，不绕过授权 |
| 套餐权益或余量不足 | 402；引导查看套餐、续费或升级，不循环重试 |
| 缺少 fileId、参数格式错误 | 400；修正请求 |
| 音频为空或扩展名不支持 | 400，`AUDIO_INVALID` |
| 短音频超过大小／声明时长上限 | 400，`AUDIO_TOO_LARGE`；上传层可能更早拒绝 |
| ASR 未配置 | 503，`SERVICE_NOT_CONFIGURED`；联系管理员 |
| 上游识别失败 | 503，`TRANSCRIPTION_FAILED`；按实际重试提示有限重试 |
| 文件归属、读取或摘要校验失败 | 按实际错误处理，不换用其他用户文件或直接请求上游 |

Talk 业务异常可能附带细分错误信息；鉴权和共享服务错误不保证携带同样的扩展字段。网络超时不代表厂商未处理，本接口没有供客户端使用的幂等键；避免自动无限重试造成重复请求。用户切换会话、租户或取消输入后，旧请求结果不得覆盖新输入框。

识别不自动删除已登记的上传文件。文件仍遵循上传底座的生命周期与引用规则；本次识别成功不表示存储空间已释放，不要自行删除 COS 对象。

## 7. 验证范围与相关文档

本页核对当前源码的 TalkSearchExperienceController#askAudio → RegisteredFileResolver / FileUploadServiceImpl#readRegisteredFile → TalkAskAudioService#transcribe → ITalkAsrProvider，以及 AiInvocationAccess 和 TalkResponseAdvice。实际服务调用方为 askAudio 控制器；原生端存在 TalkAskAudioRecognition 响应模型，但本次未据此宣称已有完整客户端调用链。

本次为静态接入文档发布，未上传生产音频、调用厂商或消耗测试额度；格式兼容、真实识别质量与端到端用量需在授权环境验收。

- [文件上传与 COS](/ios-cos-upload/)
- [本人租户列表与切换](/user-tenants/)
- [AI 大模型对话](/ai-chat/)
