藏语实时语音识别 (算法编码:8005200033)
协议类型:WebSocket
一、接入点
| 环境 |
地址 |
| 公网 |
wss://api-maas.teleai.com.cn/aipaas/voice/v1/tibetanStreamingAsr/asr |
- API Path:
/aipaas/voice/v1/tibetanStreamingAsr/asr
- 请求方法:
WebSocket
- Content-Type:
application/json
二、鉴权
采用请求头携带鉴权信息,在建立 WebSocket 连接时通过 Header 传递 :
2.1 标准鉴权
Authorization: <鉴权信息>
| 请求头 |
必填 |
说明 |
Content-Type |
是 |
内容类型,固定 application/json |
X-APP-ID |
是 |
控制台 → 应用管理 → AppID |
Device-Uuid |
否 |
设备uuid |
Authorization |
是 |
鉴权信息 |
2.2 Bearer Token 鉴权
Authorization: Bearer <用户申请的API-KEY>
| 请求头 |
必填 |
说明 |
Content-Type |
是 |
内容类型,固定 application/json |
Device-Uuid |
否 |
设备uuid |
Authorization |
是 |
Bearer |
2.3 握手返回结果
| code |
说明 |
解决方法 |
101 |
成功 |
建链成功,开始语音识别 |
1000 |
成功 |
正常关闭 |
1002 |
失败 |
协议错误/联系服务台 |
1005 |
失败 |
异常断开 |
1006 |
失败 |
异常断开 |
4002 |
失败 |
服务异常,联系服务台 |
4004 |
失败 |
服务异常,联系服务台 |
---
三、能力简介
实时语音识别,用于实时音频流转换为文字场景,支持一边上传音频流,一边实时返回转写结果。
- 音频属性:采样率 8k/16k/其他常见采样率,位宽 16 bit,单声道
- 音频格式:PCM 音频流
3.1 修订历史
| 修订日期 |
算法版本号 |
修订内容 |
| 2026-02-09 |
V1.0.0 |
服务支持藏语流式识别 |
四、请求与响应
4.1 请求参数
4.1.1 顶层字段
| 字段 |
类型 |
必填 |
说明 |
req_id |
string |
是 |
请求全局唯一 id,记录该值便于排查问题(发送开始识别 rec_status=0 时必填) |
rec_status |
int |
是 |
识别状态:0 开始识别;1 发送语音流;2 结束语音流 |
audio_stream |
string |
否 |
语音流,采用 base64 编码(发送语音流时为必填) |
option |
object |
否 |
语音识别配置可选项,客户端发送开始识别请求时,根据具体需求配置该字段 |
4.1.2 识别配置 option
| 字段 |
类型 |
必填 |
说明 |
sample_rate |
int |
否 |
音频采样率,默认值 16000Hz |
enable_punctuation |
boolean |
否 |
是否加标点,默认 true,若开启,则在 rec_status=3 时给识别文本增加标点 |
enable_inverse_text_normalization |
boolean |
否 |
是否开启 ITN,默认 true,若开启,则在 rec_status=3 时对识别文本进行逆文本规范化 |
enable_emendation |
boolean |
否 |
是否开启校勘,默认 false,若开启,则在 rec_status=3 时对识别文本进行校准 |
enable_words |
boolean |
否 |
是否开启返回词信息,默认 false,若开启,则同时返回字级别时间戳 |
enable_s2t |
boolean |
否 |
是否返回繁体中文,默认值是 false |
province |
string |
否 |
仅对来自电信万号的业务开放(预留字段) |
hotwords |
array |
否 |
热词列表,string 数组 |
hotword_list_id |
string |
否 |
热词列表查询 ID(在星河热词服务创建热词表后得到热词列表查询 ID,ASR 服务使用此 ID 查询生效) |
banned_word_list_id |
string |
否 |
敏感词列表查询 ID(在星河敏感词服务创建敏感词列表后得到敏感词列表查询 ID,ASR 服务使用此 ID 查询生效) |
max_end_silence |
int |
否 |
句尾静音阈值,单位 ms(仅当服务使用普通 vad 时生效) |
4.2 响应体
4.2.1 顶层字段
| 字段 |
类型 |
说明 |
code |
int |
返回码 |
message |
string |
返回码描述 |
sid |
string |
会话全局唯一 id,用于记录本次会话 |
res_status |
int |
响应状态:0 识别就绪;1 识别到有效语音开始;2 返回中间识别结果(需开启中间结果);3 检测到一段有效语音结束,返回该段语音的识别结果;4 处理完所有音频数据,返回尚未返回的识别结果(如果有) |
data |
object |
识别结果数据 |
elps_time |
int |
当前识别结果所对应的已处理音频总时长,单位毫秒 |
4.2.2 识别结果 data
| 字段 |
类型 |
说明 |
sn |
int |
句子编号,从 0 开始 |
results |
array |
当前句子识别结果,如果开启 object.nbest,则返回多个结果 |
4.2.3 识别结果项 results[]
| 字段 |
类型 |
说明 |
text |
string |
句子识别结果 |
begin_time |
int |
句子开始时间,单位毫秒 |
end_time |
int |
句子结束时间,单位毫秒 |
loudness |
float |
句子音量,仅在 res_status=3 时返回 |
speed |
float |
句子语速,仅在 res_status=3 时返回 |
pitch |
float |
句子语调,仅在 res_status=3 时返回 |
lang |
string |
当前方言种类,仅在 Sensevoice 模型二刷时有效,仅在状态 3 有效 |
words |
array |
当前句子的词信息 |
4.2.4 词信息 words[]
| 字段 |
类型 |
说明 |
text |
string |
词信息 |
begin_time |
int |
词开始时间,单位毫秒 |
end_time |
int |
词结束时间,单位毫秒 |
4.3 交互流程
4.3.1 开始识别
客户端发送开始识别请求,需要通过请求 body 带语音识别过程中的可选配置参数,示例:
{
"option": {
"sample_rate": 16000,
"enable_punctuation": true,
"enable_inverse_text_normalization": true
},
"req_id": "aae36140-bc13-441f-81f9-6700fe7a5e96",
"rec_status": 0
}
响应结果:
{
"code": 10000,
"message": "success",
"sid": "aae36140-bc13-441f-81f9-6700fe7a5e96",
"res_status": 0
}
4.3.2 发送语音流
客户端接收到服务端发送的确认识别请求有效的响应后,开始发送语音流数据:
{
"rec_status": 1,
"audio_stream": "000asraae361406700fe7a5e9681f956210b5f1270"
}
接收识别结果示例:
{
"code": 10000,
"message": "success",
"sid": "aae36140-bc13-441f-81f9-6700fe7a5e96",
"res_status": 2,
"data": {
"sn": 1,
"results": [
{
"lang": "zh",
"text": "你好今天",
"begin_time": 1500,
"end_time": 2800,
"words": [
{ "text": "你", "begin_time": 50, "end_time": 70 },
{ "text": "好", "begin_time": 50, "end_time": 70 },
{ "text": "今", "begin_time": 50, "end_time": 70 },
{ "text": "天", "begin_time": 50, "end_time": 70 }
]
}
]
}
}
4.3.3 结束语音流
客户端语音流发送完成,结束语音流(rec_status=2):
{
"rec_status": 2
}
4.3.4 关闭连接
客户端如果不需要继续进行语音识别,则立即关闭 WebSocket 连接(避免占用资源)。如果需要继续进行语音识别(多轮对话场景),需要从开始识别状态开始,按照上述步骤依次执行。
五、状态码说明
5.1 算法状态码
| 状态码 |
说明 |
描述 |
解决方法 |
10000 |
success |
成功 |
执行下一步操作 |
20003 |
Banned word(s) detected in input |
敏感词命中 |
成功,并检测到敏感词 |
10001 |
parse request body fail |
URL body 格式不对 |
查看请求的 URL body 格式是否正确,参考接口文档 |
10002 |
session not found |
会话 id 查询失败 |
检查客户端发送的请求,通常是因为没有发送开始识别请求 |
10003 |
required parameter miss |
参数缺失 |
检查接口文档,补全入参 |
10004 |
duplicated session id |
会话 id 重复 |
检查客户端发送的请求,通常是因为重复发送开始识别请求 |
10005 |
worker pool overflow |
超并发 |
联系研发人员进行排查 |
10006 |
unknown error |
未知错误 |
联系研发人员进行排查 |
10007 |
Non-real-time audio data |
非实时音频数据 |
检查发送的音频数据是否与每次发送间隔的时间一致,比如每 200ms 发送 200ms 的音频数据 |
10008 |
Session not begun |
尚未发送开始识别标志 |
检查是否发送开始识别标志 |
10009 |
Session is running |
重复发送开始识别标志 |
检查是否重复发送开始识别标志,若重复,请先发送结束识别标志 |
10010 |
Hotword list load failed |
热词表查询失败 |
检查 X-APP-ID、热词表 ID 是否有错误,检查热词查询服务是否有错误 |
10011 |
Banned Word List Loads failed |
敏感词表查询失败 |
检查 X-APP-ID、敏感词 ID 是否有错误,检查敏感词查询服务是否有错误 |
5.2 公共状态码
- 接口响应的公共状态码由网关统一定义,一般用于标识鉴权失败、限流或服务异常,具体业务错误码、错误信息及排查建议请参考:开发指南-公共信息及状态码。
六、调用示例
Python
import asyncio
import websockets
import json
# 配置环境变量
X_APP_ID = "yourAppId"
AUTHORIZATION = "yourAuthorization"
# 请求的URL
URL = "wss://api-maas.teleai.com.cn/aipaas/voice/v1/tibetanStreamingAsr/asr"
# 请求数据
request_data = {
"req_id": "",
"rec_status": 0,
"audio_stream": "",
"option": {
"sample_rate": 0,
"enable_emendation": False,
"province": "",
"enable_inverse_text_normalization": False,
"hotwords": [],
"enable_words": False,
"enable_punctuation": False
}
}
async def connect_websocket():
headers = {
"Content-Type": "application/json",
"Device-Uuid": "2018619061498245122",
"X-APP-ID": X_APP_ID,
"Authorization": AUTHORIZATION
}
try:
async with websockets.connect(URL, extra_headers=headers) as websocket:
print("连接已建立")
message = json.dumps(request_data)
await websocket.send(message)
while True:
response = await websocket.recv()
print(f"接收: {response}")
except Exception as e:
print(f"连接异常: {e}")
# 运行异步客户端
if __name__ == "__main__":
asyncio.run(connect_websocket())
Java(使用 Java-WebSocket + FastJSON)
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSONObject;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
/**
* 依赖:
* <dependency>
* <groupId>org.java-websocket</groupId>
* <artifactId>Java-WebSocket</artifactId>
* <version>1.5.3</version>
* </dependency>
* <dependency>
* <groupId>com.alibaba</groupId>
* <artifactId>fastjson</artifactId>
* <version>1.2.83</version>
* </dependency>
*/
public class WebSocketClientCase {
public static void main(String[] args) throws Exception {
// 算法调用地址,请根据实际情况修改
URI uri = URI.create("wss://api-maas.teleai.com.cn/aipaas/voice/v1/tibetanStreamingAsr/asr");
// 设置请求头
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("Device-Uuid", "2018619061498245122");
headers.put("X-APP-ID", "你实际的AppId");
headers.put("Authorization", "你实际的Authorization");
// 设置请求参数,请根据实际情况修改
String requestParam = "{\n" +
" \"req_id\": \"\",\n" +
" \"rec_status\": 0,\n" +
" \"audio_stream\": \"\",\n" +
" \"option\": {\n" +
" \"sample_rate\": 0,\n" +
" \"enable_emendation\": false,\n" +
" \"province\": \"\",\n" +
" \"enable_inverse_text_normalization\": false,\n" +
" \"hotwords\": [],\n" +
" \"enable_words\": false,\n" +
" \"enable_punctuation\": false\n" +
" }\n" +
"}";
// 创建WebSocket客户端实例
WebSocketClient client = new WebSocketClient(uri, new Draft_6455(), headers, 5000) {
@Override
public void onOpen(ServerHandshake handshake) {
System.out.println("连接已建立");
// 连接成功后发送消息
send(JSONObject.toJSONString(requestParam));
}
@Override
public void onMessage(String message) {
System.out.println("收到消息: " + message);
}
@Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("连接关闭: " + reason);
}
@Override
public void onError(Exception ex) {
System.err.println("发生错误: " + ex.getMessage());
}
};
// 建立连接
client.connect();
// 保持程序运行
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭连接
client.close();
}
}