- ···
- 产品服务
- ···
- 解决方案
- ···
- 文档中心
- ···
# 一、接口说明
实时语音转写服务(ASR, real-time)通过 WebSocket 协议,建立客户端与服务的长连接,开发者将连续的音频流内容发送给服务,服务返回对应的文字流内容。
支持的音频格式: 采样率为16K或者8k,采样深度为16bits,pcm,单通道音频
# 二、接口Demo
Java示例demo (opens new window)
python3示例demo (opens new window)
js示例demo (opens new window)
# 三、接口要求
集成实时语音转写流式API时,需按照以下要求:
内容 | 说明 |
---|---|
请求协议 | ws[s](为提高安全性,强烈推荐wss) |
请求地址 | ws[s]: //ws-rtasr.hivoice.cn/v1/ws 注:服务器IP不固定,为保证您的接口稳定,请勿通过指定IP的方式调用接口,使用域名方式调用 |
接口鉴权 | 签名机制,详情请参照下方接口鉴权 |
字符编码 | UTF-8 |
响应格式 | 统一采用JSON格式 |
开发语言 | 任意,只要可以向服务发起Websocket请求的均可 |
操作系统 | 任意 |
音频属性 | 采样率16k或8k,采样深度16bit、单声道 |
音频格式 | pcm |
音频长度 | 最长2小时 |
语言种类 | 中文普通话、英语 |
# 四、IP白名单
默认关闭IP白名单,即该服务不限制调用IP。 在调用该业务接口时
- 若关闭IP白名单,接口认为IP不限,不会校验IP。
- 若打开IP白名单,则服务端会检查调用方IP是否在开放平台配置的IP白名单中,对于没有配置到白名单中的IP发来的请求,服务端会拒绝服务。
- 若打开IP白名单,同时没有设置任何IP,接口会认为此时没有设置白名单,所以打开IP白名单时,请务必设置IP,否则无法生效。
IP白名单规则
- 登录 云知声AI开放平台控制台 (opens new window)
- 选择应用的查看详情
- IP白名单处编辑,保存后五分钟左右生效。
- 不同appkey的不同服务都需要分别设置IP白名单。
- IP白名单需设置为外网IP,请勿设置局域网IP。
# 五、热词
实时语音转写支持应用级个性化热词和用户级别个性话热词,具体设置方法参考设置热词
# 六、接口调用流程
- 通过接口密钥基于SHA256计算签名,向服务器端发送Websocket协议握手请求。详见接口鉴权。
- 握手成功后,客户端发送开始转写标记和识别参数,详见开始转写
- 客户端通过Websocket连接同时发送语音和接收转写识别结果。详见发送语音数据、接收转写结果
- 数据上传完毕,客户端需要发送结束标记,详见结束转写。
- 服务端返回全部结果后会主动断开Websocket连接
注: Websocket使用注意事项如下
- 服务端支持的Websocket-version 为13,请确保客户端使用的框架支持该版本。
- 服务端返回的所有的帧类型均为TextMessage,对应于原生Websocket的协议帧中opcode=1,请确保客户端解析到的帧类型一定为该类型,如果不是,请尝试升级客户端框架版本,或者更换技术框架。
- 如果出现分帧问题,即一个json数据包分多帧返回给了客户端,导致客户端解析json失败。出现这种问题大部分情况是客户端的框架对Websocket协议解析存在问题,如果出现请先尝试升级框架版本,或者更换技术框架。
- 客户端会话结束后如果需要关闭连接,尽量保证传给服务端的错误码为Websocket错误码1000(如果客户端框架没有提供关闭时传错误码的接口。则无需关注本条)。
# 1、接口鉴权
在握手阶段,请求方需要对请求进行签名,服务端通过签名来校验请求的合法性。
请求示例
ws[s]://ws-rtasr.hivoice.cn/v1/ws?time=1585047674022&appkey=xxxxxxxxxxx&sign=xxxxxxxxxx
1
# 1.1、鉴权方法
参数 | 描述 | 示例 | 备注 |
---|---|---|---|
appkey | 用户的appkey | *** | 必需 |
time | 访问时间戳,Unix时间戳(毫秒数) | 1585047674022 | 必需 |
sign | 签名 | *** | 必需 |
A)将上述参数按照appkey、time、secret secret查询 (opens new window) 顺序拼接字符串;
B)将A形成字符串获取SHA256摘要,形成一个64位的十六进制(字母大写)字符串,即为本次请求sign(签名)的值
# 1.2、鉴权代码示例
/**
* 热词签名获取方法
* @param appkey
* @param timestamp
* @param secret
* @return
*/
public String getSign(String appkey, String timestamp, String secret) {
String originalStr = appkey + timestamp + secret;
StringBuilder sign = new StringBuilder();
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] bytes = md.digest(originalStr.getBytes(StandardCharsets.UTF_8));
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
} catch (Exception unused) {
}
return sign.toString();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1.3、鉴权结果
如果握手成功,会返回HTTP 101状态码,表示协议升级成功;如果握手失败,则根据不同错误类型返回不同HTTP Code状态码,同时携带错误描述信息,详细错误说明如下:
HTTP Code | 说明 | 解决方法 |
---|---|---|
401 | 签名校验失败 | 签名验证失败,可能原因有多种。 1. 检查appkey,signature 是否正确 2.检查计算签名的参数appkey,timestamp,secret是否按照协议要求拼接。 |
403 | 时钟偏移校验失败 | 检查服务器时间是否标准,相差5分钟以上会报此错误 |
# 2、开始转写
通过Websocket文本传输,json格式数据
# 2.1、参数说明
参数名 | 类型 | 必传 | 描述 | 可选值 | 默认值 |
---|---|---|---|---|---|
type | string | 是 | 请求的阶段 | start | |
data.domain | string | 否 | 领域 | general(通用) law(司法) technology(科技) medical(医疗) | general |
data.sample | string | 否 | 采样率 | 16k,8k | 16k |
data.lang | string | 否 | 语言 | cn(中文) en(英文) cantonese(粤语) sichuanese(四川话) | cn |
data.punctuation | string | 否 | 是否开启标点符号添加 | true,false | true |
data.post_proc | string | 否 | 是否开启数字格式转为阿拉伯数字格式 | true,false | true |
data.user_id | string | 否 | 用户标识 | ||
data.vocab_id | string | 否 | 热词模型id,获取方法参考设置vocab热词 | ||
data.speaker_seperate | string | 否 | 是否开启说话人分离 | true,false | false |
# 2.2、请求参数示例
{
"type": "start",
"data": {
"domain":"general",
"sample": "16k",
"lang": "cn",
"punctuation": "true",
"post_proc": "true",
"user_id": "userid"
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 3、发送语音数据
通过Websocket发送二进制语音数据,建议每次发送音频间隔120ms
说明
整个会话时长最多持续2小时,或者超过10s未发送数据,服务端会主动断开连接
# 4、接收转写结果
接收转写的结果是通过Websocket的onMessage(String)方法
# 4.1、识别结果说明
参数 | 类型 | 描述 | 是否为空 |
---|---|---|---|
code | int | 错误码 | NO |
msg | string | 结果说明 | NO |
sid | string | 服务端生成的session id。申请服务端排查问题时需要提供此id | NO |
type | string | 结果类型:"variable":可变结果,"fixed":固定结果 | NO |
text | string | 识别结果 | NO |
start_time | string | 句子开始时间,单位ms(可变结果不返回此字段) | YES |
end_time | string | 句子结束时间,单位ms(可变结果不返回此字段) | YES |
end | boolean | 是否为最后一次识别结果,当发送完type=end消息时,返回end=true,否则end=false | YES |
speaker | String | 说话人id,从1开始,步长为1累加。 | NO |
注: end标识说明
- 当结束一次识别时,需要客户端主动发送结束转写消息,即{"type":"end"}消息。服务端处理完所有数据后会返回end=true的消息
- 当客户端收到end=true消息时,客户端可主动断开websocket连接,服务端不会主动断开连接,10秒未发送数据超时除外
- 当服务端返回错误码时,也会返回end=true消息
# 4.2、返回结果示例
{
"code": 0,
"msg": "success",
"sid": "requestid",
"type": "fixed",
"text": "不断提升自己,在学习的过程中,让他明白生命的本质是过活简单平凡而有意义的日子。另一个分享者是一名27岁的it男,2015年到朋友圈晒的都是打王者的战绩,而2018年却什么也没有发。",
"start_time": 58860,
"end_time": 70500,
"end":false
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 5、结束转写
# 5.1、参数说明
参数名 | 类型 | 必传 | 描述 | 可选值 | 默认值 |
---|---|---|---|---|---|
type | string | 是 | 请求的阶段 | end |
# 5.2、请求参数示例
{
"type": "end"
}
1
2
3
2
3
# 七、错误码
错误码 | 说明 | 解决方法 |
---|---|---|
0 | 正确 | |
20101 | Websocket连接空闲时间超过10s | 检查客户端代码 |
20102 | 参数错误 | 客户端检查参数是否正确 |
20103 | 内部错误 | 建议重试,或者提工单,工单详情请提供sid |
20104 | 资源不足 | 建议重试,或者提工单,工单详情请提供sid |
20105 | 音频长度超过120分钟 | 检查音频时长是否过长,减小音频长度 |
20106 | 非法的appkey | 检查appkey是否合法 |
20107 | 套餐时长使用完 | 购买时长套餐 |
20108 | 并发超限制 | 减小并发或者购买并发套餐 |
20109 | 客户端ip不在白名单内 | 检查是否开启白名单,同时检查客户端出口ip是否在ip白名单中 |