Skip to content

Latest commit

 

History

History
281 lines (248 loc) · 16.5 KB

File metadata and controls

281 lines (248 loc) · 16.5 KB

?此接口为 API 2.0 版本,在参数风格、错误码等方面有区别于 API 3.0 版本,请知悉。

接口描述

本接口服务对实时音频流进行识别,同步返回识别结果,达到“边说边出文字”的效果。接口是 HTTP RESTful 形式,在使用该接口前,需要在语音识别控制台开通服务,并进入 API 密钥管理页面 新建密钥,生成 AppID、SecretID 和 SecretKey,用于 API 调用时生成签名,签名将用来进行接口鉴权。

接口要求

集成实时语音识别 API 时,需按照以下要求。

内容 说明
支持语言 中文普通话、英语、粤语、韩语、日语、泰语、上海话、四川话、南京话、南昌话。其中,四川话、南京话、南昌话需填写 表单 申请
支持行业 通用、金融、游戏、教育、医疗
音频属性 采样率:16000Hz或8000Hz、采样精度:16bits、声道:单声道
音频格式 wav、pcm、opus、speex、silk、mp3、m4a、aac
数据长度 音频流中每个数据包的音频分片建议为200ms,8k采样率对应的音频分片大小为3200字节,16k采样率对应的音频分片大小为6400字节
请求协议 HTTP
请求地址 http://asr.cloud.tencent.com/asr/v1/<appid>?{请求参数}
接口鉴权 签名鉴权机制,详见 签名生成
响应格式 统一采用 JSON 格式
开发语言 任意,只要可以向腾讯云服务发起 HTTP 请求的均可
请求频率限制 50次/秒,如您有提高请求频率限制的需求,请提工单 进行咨询

请求结构

请求结构主要由请求方法、请求 URL、请求头部、请求正文组成。

请求方法

HTTPS 请求方法,实时语音识别的请求方法为 POST

请求 URL

RESTful 形式的 URL 结构示例如下:

http://asr.cloud.tencent.com/asr/v1/<appid>?
projectid=xxx&
sub_service_type=xxx&
engine_model_type=xxx&
result_text_format=xxx&
res_type=xxx&
voice_format=xxx&
secretid=xxx&
timestamp=xxx&
expired=xxx&
needvad=xxx&
nonce=xxx&
seq=xxx&
end=xxx&
source=xxx&
voice_id=xxx&
timeout=xxx

URL 中各字段含义如下:

参数名称 必选 类型 描述
AppId Int 用户在腾讯云注册账号的 AppId,可以进入 API 密钥管理页面 获取。
projectid Int 腾讯云项目 ID,语音识别目前不区分项目,所以填0即可。
secretid String 用户在腾讯云注册账号 AppId 对应的 SecretId,可以进入 API 密钥管理页面 获取。
sub_service_type Int 子服务类型。1:实时流式识别。
engine_model_type String 引擎模型类型。
电话场景:
• 8k_en:电话 8k 英语;
• 8k_zh:电话 8k 中文普通话通用;
• 8k_zh_finance:电话 8k 金融领域模型;
非电话场景:
• 16k_zh:16k 中文普通话通用;
• 16k_en:16k 英语;
• 16k_ca:16k 粤语;
• 16k_ko:16k 韩语;
• 16k_zh-TW:16k 中文普通话繁体;
• 16k_ja:16k 日语;
• 16k_wuu-SH:16k 上海话方言;
• 16k_zh_medical 医疗;
• 16k_en_game 英文游戏;
• 16k_zh_court 法庭;
• 16k_en_edu 英文教育;
• 16k_zh_edu 中文教育;
• 16k_th 泰语。
hotword_id String 热词 id。用于调用对应的热词表,如果在调用语音识别服务时,不进行单独的热词 id 设置,自动生效默认热词;如果进行了单独的热词 id 设置,那么将生效单独设置的热词 id。
customization_id String 自学习模型 id。用于调用对应的自学习模型,如果在调用语音识别服务时,不进行单独的自学习模型 id 设置,自动生效默认自学习模型;如果进行了单独的自学习模型 id 设置,那么将生效单独设置的自学习模型 id。
result_text_format Int 识别结果文本编码方式。0:UTF-8。
res_type Int 结果返回方式,默认值0。0:同步返回;1:尾包返回。
voice_format Int 语音编码方式,可选,默认值为4。1:pcm;4:speex(sp);6:silk;8:mp3;10:opus(opus 格式音频流封装说明);12:wav;14:m4a(每个分片须是一个完整的 m4a 音频);16:aac。
needvad Int 0:关闭 vad,1:开启 vad。
如果音频流总时长超过60秒,用户需开启 vad,默认值0。
vad_silence_time Int 语音断句检测阈值,静音时长超过该阈值会被认为断句(多用在智能客服场景,需配合 needvad = 1 使用),取值范围:240-2000,单位 ms,此参数建议不要随意调整,可能会影响识别效果,目前仅支持 8k_zh、8k_zh_finance、16k_zh 引擎模型。
seq Int 语音分片的序号,序号从0开始,每次请求递增1, 两个 seq 之间间隔不能超过6秒。
end Int 是否为最后一片,最后一片语音片为1,其余为0。
source Int 默认值为0。
voice_id String 16位 String 串作为每个音频的唯一标识,用户自己生成。
timestamp Int 当前 UNIX 时间戳,可记录发起 API 请求的时间。如果与当前时间相差过大,会引起签名过期错误。可以取值为当前请求的系统时间戳即可。
expired Int 签名的有效期,是一个符合 UNIX Epoch 时间戳规范的数值,单位为秒;Expired 必须大于 Timestamp 且 Expired - Timestamp 小于90天。
nonce Int 随机正整数。用户需自行生成,最长10位。
filter_dirty Integer 是否过滤脏词(目前支持中文普通话引擎)。默认为0。0:不过滤脏词;1:过滤脏词;2:将脏词替换为 * 。
filter_modal Integer 是否过滤语气词(目前支持中文普通话引擎)。默认为0。0:不过滤语气词;1:部分过滤;2:严格过滤 。
filter_punc Integer 是否过滤标点符号(目前支持中文普通话引擎)。0:不过滤,1:过滤句末标点,2:过滤所有标点。默认为0。
convert_num_mode Int 是否进行阿拉伯数字智能转换(目前支持中文普通话引擎)。0:不转换,直接输出中文数字,1:根据场景智能转换为阿拉伯数字,3: 打开数学相关数字转换。默认值为1。
word_info Int 是否显示词级别时间戳。0:不显示;1:显示,不包含标点时间戳,2:显示,包含标点时间戳。支持引擎 8k_en,8k_zh,8k_zh_finance,16k_zh,16k_en,16k_ca,16k_zh-TW,16k_ja,16k_wuu-SH,默认为0。

请求头部

请求头部,包括 Host,Authorization,Content-Type,Content-Length 四个参数。

参数名称 必选 类型 描述
Host String 语音识别服务域名,固定为 asr.cloud.tencent.com
Authorization String 用户的有效签名,用于鉴权。对应签名鉴权中得到的签名字符串
Content-Type String application/octet-stream
Content-Length Int 请求长度,此处对应语音数据字节数,单位:字节

请求正文

请求正文主要包含实时语音识别的数据,每个数据包的音频分片最大不能超过200KB。

请求示例

用户通过 签名生成 的签名为 qPHg2LZkMRZyC5pyVD8egRqxPc0=,上传语音分片 @/mnt/d/1.silk_down,分片为流式语音的第一个分片(seq=0),采样率为16k,请求实时语音识别服务16k通用(engine_model_type = 16k_0)引擎模型,结果返回方式为同步返回。具体的示例生成方式请参考下面 PHP 代码

curl --data "@/mnt/d/1.silk_down" -H "Authorization:qPHg2LZkMRZyC5pyVD8egRqxPc0=" -X POST "http://asr.cloud.tencent.com/asr/v1/1259228442?end=0&engine_model_type=16k_0&expired=1561548973&needvad=0&nonce=1561&projectid=1013976&res_type=0&result_text_format=0&secretid=AKIDoQq1zhZMN8dv0psmvud6OUKuGPO*****&seq=0&source=0&sub_service_type=1&timeout=100&timestamp=1561462573&voice_format=1&voice_id=yp1fifJmEx4Lh3OX"

签名生成

这里以 Appid=1259228442, SecretId=AKIDoQq1zhZMN8dv0psmvud6OUKuGPO***** 为例拼接签名原文,则拼接的签名原文为:

POSTasr.cloud.tencent.com/asr/v1/1259228442?end=1&engine_model_type=16k_0&expired=1561022467&needvad=1&nonce=52811334&projectid=0&res_type=1&result_text_format=0&secretid=AKIDoQq1zhZMN8dv0psmvud6OUKuGPO*****&seq=0&source=0&sub_service_type=1&timeout=5000&timestamp=1561016467&voice_format=4&voice_id=f658c689c3b4db74

对签名原文和 SecretKey=kFpwoX5RYQ2SkqpeHgqmSzHK7h3A2fni,使用 HmacSha1 算法进行加密处理:

签名串=Base64Encode(HmacSha1(签名原文,SecretKey))

最终得到签名串为:

LsgT3TbVPb2nS3ac1U34stZ/D5k=

Opus 音频流封装说明

压缩 FrameSize 固定640,即一次压缩640 short,否则解压会失败。传到服务端可以是多帧的拼接组合,每一帧需满足下面格式。 每一帧压缩数据封装如下:

OpusHead(4字节) 帧数据长度(2字节) Opus 一帧压缩数据
opus 长度 len 对应 len 长的 opus decode data

返回结构

返回结果

实时语音识别的 RESTfulAPI 请求返回结果如下表所示:

参数名称 描述
code 0:正常,其他,发生错误
message 0:success;不为0:其他
voice_id 表示这通音频的标记,同一个音频流这个标记一样
seq 语音分片序号,与请求时设置的 seq 相同
text 语音分片的识别结果
如果请求参数 needvad 为0的话,text 为完整识别结果。
如果请求参数 needvad 为1的话,text 为空,需要从 result_list 字段中获取分片识别结果。
result_number 表示后面的 result_list 里面有几段结果,如果是0表示没有结果,遇到中间是静音。
如果是1表示 result_list 有一个结果, 在发给服务器分片很大的情况下可能会出现多个结果,正常情况下都是1个结果。
result_list slice_type:返回分片类型标记, 0表示一小段话开始,1表示在小段话的进行中,2表示小段话的结束
index 表示第几段话
start_time 这个分片在整个音频流中的开始时间
end_time 这个分片在整个音频流中的结束时间
voice_text_str 识别结果
final 0 表示还在整个音频流的中间部分
1 表示是整个音频流的最后一个包。
主要是在电信场景中,客户端发送完了之后,要知道是否返回的是最后一个包。
word_size 表示后面的 word_list 的长度,即有多少个词。
word_list 词时间戳列表:
word 表示这个词的内容,
start_time 表示该词在整个音频中的起始时间,
end_time 表示该词在整个音频中的结束时间,
stable_flag 表示词的稳态结果,0:该词在后续识别中可能发生变化,1:表示该词在后续识别过程中不会变化。

返回示例

第一个分片:

{"code":0,"message":"success","voice_id":"8qiS3yeVnwHHbQ9F","seq":0,"text":"","result_number":1,"result_list":[{"slice_type":0,"index":1,"start_time":0,"end_time":256,"voice_text_str":""}],"final":0}

中间某个分片:

{"code":0,"message":"success","voice_id":"8qiS3yeVnwHHbQ9F","seq":2,"text":"吃饭了。","result_number":1,"result_list":[{"slice_type":0,"index":1,"start_time":512,"end_time":768,"voice_text_str":"吃饭了。"}],"final":0}

最后一个分片:

{"code":0,"message":"success","voice_id":"K3lRwC6tWkKjvnCL","seq":6,"text":"吃饭了吗。","result_number":1,"result_list":[{"slice_type":0,"index":1,"start_time":3072,"end_time":3093,"voice_text_str":"吃饭了吗。"}],"final":1}

错误码

数值 说明
100 获取语音分片信息失败
101 语音分片过大
102 参数不合法,具体详情参考 message
103 访问数据库失败
104 AppID 服务未开通,请在控制台开通服务
105 模板不存在
106 模板停用
107 鉴权失败
108 拼接签名串失败
109 l5获取 IP、port 失败
110 后台识别服务器故障,请从 seq=0重传
111 后台识别模块回包格式错误
112 语音分片为空
113 后台服务器识别超时
114 引擎编号不合法
115 时长计算时音频类型不合法
116 无可使用的免费额度
117 禁止访问
118 请求限流
119 账户欠费停止服务,请及时充值
120 获取 rpcClient 错误
121 后台识别服务器错误,请从seq=0重传
122 后台识别服务器收到的包格式错误
123 后台识别服务器音频解压失败,请从seq=0重传
124 后台识别服务器识别失败,请从seq=0重传
125 后台识别服务器识别失败,请重新尝试
126 后台识别服务器音频分片等待超时,请从seq=0重传
127 后台识别服务器音频分片重复

PHP 代码示例

//filepath 音频文件路径
//printCutResponse 是否打印返回结果
function sendvoice($filepath, $printCutResponse) {
	if (empty ($filepath)) {
		echo "filepath can not be empty";
		return -1;
	}

	$reqArr = array ();
	$reqArr['appid'] = Config :: $APPID;
	$reqArr['projectid'] = 0;
	$reqArr['sub_service_type'] = 1;
	$reqArr['engine_model_type'] = Config :: $ENGINE_MODEL_TYPE;
	$reqArr['res_type'] = Config :: $RES_TYPE;
	$reqArr['result_text_format'] = Config :: $RESULT_TEXT_FORMAT;
	$reqArr['voice_id'] = randstr(16);
	$reqArr['needvad'] = 0;
	$reqArr['timeout'] = 20000;
	$reqArr['source'] = 0;
	$reqArr['secretid'] = Config :: $SECRET_ID;
	$reqArr['timestamp'] = time();
	$reqArr['expired'] = time() + 24 * 60 * 60;
	$reqArr['nonce'] = rand(1, 10000);
	$reqArr['voice_format'] = Config :: $VOICE_FORMAT;
	$secretKey = Config :: $SECRET_KEY;
	$voicedata = file_get_contents($filepath);
	$datalen = strlen($voicedata);
	$cutlegth = Config :: $CUTLENGTH;
	$seq = 0;
	while ($datalen > 0) {
		$end = 0;
		if ($datalen < $cutlegth)
			$end = 1;
		$serverUrl = "http://asr.cloud.tencent.com/asr/v1/";
		$reqArr['end'] = $end;
		$reqArr['seq'] = $seq;
		$serverUrl .= $reqArr['appid'] . "?";
		$serverUrl .= "projectid=" . $reqArr['projectid'] . "&";
		if (isset ($reqArr['template_name'])) {
			$serverUrl .= "template_name=" . $reqArr['template_name'] . "&";
		}
		$serverUrl .= "sub_service_type=" . $reqArr['sub_service_type'] . "&";
		$serverUrl .= "engine_model_type=" . $reqArr['engine_model_type'] . "&";
		$serverUrl .= "res_type=" . $reqArr['res_type'] . "&";
		$serverUrl .= "result_text_format=" . $reqArr['result_text_format'] . "&";
		$serverUrl .= "voice_id=" . $reqArr['voice_id'] . "&";
		$serverUrl .= "seq=" . $seq . "&";
		$serverUrl .= "end=" . $end . "&";
		$serverUrl .= "timeout=" . $reqArr['timeout'] . "&";
		$serverUrl .= "source=" . $reqArr['source'] . "&";
		$serverUrl .= "secretid=" . $reqArr['secretid'] . "&";
		$serverUrl .= "timestamp=" . $reqArr['timestamp'] . "&";
		$serverUrl .= "expired=" . $reqArr['expired'] . "&";
		$serverUrl .= "nonce=" . $reqArr['nonce'] . "&";
		$serverUrl .= "needvad=" . $reqArr['needvad'] . "&";
		$serverUrl .= "voice_format=" . $reqArr['voice_format'];

		$autho = createSign($reqArr, "POST", "asr.cloud.tencent.com", "/asr/v1/", $secretKey);
		if ($datalen < $cutlegth) {
			$data = file_get_contents($filepath, NULL, NULL, $seq * $cutlegth, $cutlegth);
		} else {
			$data = file_get_contents($filepath, NULL, NULL, $seq * $cutlegth, $cutlegth);
		}
		$seq = $seq +1;
		$datalen = $datalen - $cutlegth;
	
		$header = array (
			'Authorization: ' . $autho,
			'Content-Length: ' . strlen($data),
		);

		$rsp_str = "";
		$http_code = -1;
		$ret = http_curl_exec($serverUrl, $data, $rsp_str, $http_code, 'POST', 10, array(), $header);
		if ($ret != 0) {
			echo "http_curl_exec failed \n";
			return false;
		}
		
		if($printCutResponse)
			echo "rsp_str : \n" . $rsp_str . "\n";
	}
	return $rsp_str;
}