录音文件识别

最近更新时间:2019-08-09 18:58:37

接口描述

本接口服务对一小时之内的录音文件进行识别,异步返回识别全部结果,支持语音 URL 和本地语音文件两种请求方式。接口是 HTTP RESTful 形式,在使用该接口前,需要在 语音识别控制台 开通服务,并进入 API 密钥管理页面 新建密钥,生成 AppID、SecretID 和 SecretKey ,用于 API 调用时生成签名,签名将用来进行接口鉴权。

接口要求

集成录音文件识别 API 时,需按照以下要求。

内容 说明
请求协议 HTTP
请求地址 https://aai.qcloud.com/asr/v1/<appid>? {请求参数}
接口鉴权 签名机制,详见 签名生成
响应格式 统一采用 JSON 格式
开发语言 任意,只要可以向腾讯云服务发起HTTP请求的均可
音频属性 采样率16k或8k、位长16bits、单声道或双声道
音频格式 支持 wav、pcm、mp3、silk、speex、amr 等主流音频格式
数据长度 若采用直接上传音频数据方式,建议音频数据不能大于5MB;若采用上传音频 url 方式,建议音频时长不能大于1小时。
语言种类 中文普通话、带有一定方言口音的普通话

请求结构

请求结构主要由请求方法、请求 URL、请求头部、请求正文组成。
请求方法
HTTPS 请求方法,录音文件识别的请求方法为 POST
请求 URL
RESTful 形式的 URL 结构示例如下:

https://aai.qcloud.com/asr/v1/<appid>? 
projectid=xxx&
sub_service_type=xxx& 
engine_model_type=xxx& 
callback_url=xxx& 
channel_num=xxx& 
res_text_format=xxx&
res_type=xxx&  
source_type=xxx&
url=xxx&
secretid=xxx&
timestamp=xxx& 
expired=xxx& 
nonce=xxx

URL 中各字段含义如下:

参数名称 必选 类型 描述
appid Int 用户在腾讯云注册账号的 AppId,可以进入 API密钥管理页面 获取
projectid Int 腾讯云项目 ID,语音识别目前不区分项目,所以填0即可。
secretid String 用户在腾讯云注册账号 AppId 对应的 SecretId,可以进入 API 密钥管理页面 获取
sub_service_type Int 子服务类型。0:录音文件识别
engine_model_type String 引擎类型。8k_0:电话 8k 通用模型;16k_0:16k 通用模型;8k_6: 电话场景下单声道话者分离模型
res_text_format Int 识别结果文本编码方式。0:UTF-8;1:GB2312;2:GBK;3:BIG5
res_type Int 结果返回方式。 1:同步返回;0:尾包返回
callback_url String 回调 URL,用户自行搭建的用于接收识别结果的服务器地址, 长度小于2048字节
channel_num Int 语音声道数,1:单声道;2:双声道(仅在电话 8k 通用模型下支持)
source_type Int 语音数据来源。0:语音 URL;1:语音数据(post body)
url String 语音的URL地址,需要公网可下载。长度小于2048字节,当 source_type 值为 0 时须填写该字段,为 1 时不需要填写
timestamp Int 当前 UNIX 时间戳,可记录发起 API 请求的时间。如果与当前时间相差过大,会引起签名过期错误。可以取值为当前请求的系统时间戳即可
expired Int 签名的有效期,是一个符合 UNIX Epoch 时间戳规范的数值,单位为秒;Expired 必须大于 Timestamp 且 Expired - Timestamp 小于90天。
nonce Int 随机正整数。用户需自行生成,最长10位。

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

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

请求正文
语音数据,当 SourceType 值为1(语音数据上传)时必须填写,当 SourceType 值为0(语音 URL 上传)可不写。要使用base64编码(采用 Python 语言时注意读取文件应该为 string 而不是 byte,以 byte 格式读取后要 decode()。编码后的数据不可带有回车换行符)。音频数据要小于5MB。
请求示例
请求示例如下,示例生成请参考下面 PHP 代码
示例1
用户通过语音 url 地址方式请求。
用户通过 签名生成 的签名 5Zb1hKd8uo4H+AgpMbktZhHqqjY=,通过语音 url(https://xuhai2-1255824371.cos.ap-chengdu.myqcloud.com/test.wav) 的方式请求录音文件识别服务,服务的引擎模型为8k_0,识别的录音文件为单声道,采样率为8k。

curl -sv -H 'Authorization:5Zb1hKd8uo4H+AgpMbktZhHqqjY=' 'https://aai.qcloud.com/asr/v1/1259228442?callback_url=http://test.qq.com&channel_num=1&engine_model_type=8k_0&expired=1561464926&nonce=6666&projectid=0&res_text_format=0&res_type=1&secretid=AKIDoQq1zhZMN8dv0psmvud6OUKuGPO7pu0r&source_type=0&sub_service_type=0&timestamp=1561461326&url=https://xuhai2-1255824371.cos.ap-chengdu.myqcloud.com/test.wav'

示例2
用户通过本地语音上传方式请求。
用户通过 签名生成 的签名 j8AY1RkedGSoDxCjAEtT2pq/r1w=,通过本地上传语音(voicedata 为用户实际上传的从音频文件读取的音频数据)的方式请求录音文件识别服务,服务的引擎模型为8k_0,识别的录音文件为单声道,采样率为8k。

curl -sv -H 'Authorization:j8AY1RkedGSoDxCjAEtT2pq/r1w=' 'https://aai.qcloud.com/asr/v1/1259228442?callback_url=http://test.qq.com&channel_num=1&engine_model_type=8k_0&expired=1561465286&nonce=6666&projectid=0&res_text_format=0&res_type=1&secretid=AKIDoQq1zhZMN8dv0psmvud6OUKuGPO7pu0r&source_type=1&sub_service_type=0&timestamp=1561461686' -d 'voicedata'


签名生成
这里以 Appid = 1259228442, SecretId = AKIDoQq1zhZMN8dv0psmvud6OUKuGPO7pu0r 为例拼接签名原文,则拼接的签名原文为:

POSTaai.qcloud.com/asr/v1/1259228442?callback_url=http://test.qq.com&channel_num=1&engine_model_type=8k_0&expired=1561464926&nonce=6666&projectid=0&res_text_format=0&res_type=1&secretid=AKIDoQq1zhZMN8dv0psmvud6OUKuGPO7pu0r&source_type=0&sub_service_type=0&timestamp=1561461326&url=https://xuhai2-1255824371.cos.ap-chengdu.myqcloud.com/test.wav

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

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

最终得到签名串为:

5Zb1hKd8uo4H+AgpMbktZhHqqjY=

返回结构

返回结果
录音文件识别的 RESTful API 请求返回结果如下表所示:

参数名称 类型 描述
code Int 服务器错误码,0 为成功
message String 服务器返回的信息
requestId Int 如果成功,返回任务 ID

返回示例
返回消息示例如下:

 { "code":0, "message":"success", "requestId":500 }

结果回调

当语音识别系统完成识别后,会将结果通过 HTTP POST 请求的形式通知到用户,用户需要在自身业务服务器上搭建服务接收回调。
服务端返回结果
语音识别系统通过回调接口形式将识别结果回调通知客户,接口 Body 各字段说明如下:

字段 类型 描述
code Int 服务器错误码,0 为成功,其他:失败
message String 成功或者失败原因文字描述
requestId Int 请求 ID,与后台任务 ID 一一对应
appid Int 腾讯云应用 ID
projectid Int 腾讯云项目 ID
audioUrl String 语音下载 ur。如果语音源非公网可下载 URL,则不包含该字段
text String 识别出的结果文本。对于双声道文件,左声道标记为1,右声道标记为0
audioTime Double 语音总时长

注意:

为了防止某些字段中,出现诸如 “&” 等特殊字符,导致解包失败,所有字段的 value 值都将进行 url_encode 之后发送给用户业务服务器,在获取 value 之后,需要先对 value 进行 url_decode 以获取原始 value 值。

客户端确认返回
用户业务服务器在接收到语音识别系统发起的 HTTP POST 回调请求后,需要按照如下约定,返回结果:

参数名称 类型 描述
code Int 错误码,0 为成功,其他值代表失败
message String 失败原因说明,例如业务服务器过载。 如果业务服务器返回失败,会间隔一段时间重新通知

回调示例

服务端返回 JSON 示例:

{ "code":0, "message":"success", "requestId":500, "appid": 12000001, "projectid": 0, "audioUrl":"http://test.qq.com/voice_url", "text":"您好", "audioTime":2.5 }

语音识别系统发起请求,收到请求后,用户侧需要以 JSON 格式回以响应:

{ "code" : 0, "message" : "成功" }

请求错误码

数值 返回码 说明
1000 ERROR_BAD_REQ 请求的参数不符合要求
1001 ERROR_PARSE_DATA_FAILED 解析请求参数时失败
1002 ERROR_HAS_NO_VALID_PROJECTID 没有提供 projectid,或者值不合法
1003 ERROR_HAS_NO_VALID_RES_TEXT_FORMAT 没有提供 res_text_format,或者值不合法
1004 ERROR_HAS_NO_VALID_SUB_SERVICE_TYPE 没有提供 sub_service_type,或者值不合法
1005 ERROR_HAS_NO_VALID_ENGINE_MODEL_TYPE 没有提供 engine_model_type,或者值不合法
1006 ERROR_HAS_NO_VALID_CALLBACK_URL 没有提供 callback_url,或者值不合法
1007 ERROR_HAS_NO_VALID_RES_TYPE 没有提供 res_type,或者值不合法
1008 ERROR_HAS_NO_VALID_SOURCE_TYPE 没有提供 source_type,或者值不合法
1009 ERROR_HAS_NO_VALID_URL 没有提供下载语音的 url,或者值不合法
1010 ERROR_HAS_NO_VALID_SECRET_ID 没有提供 SecretId,或者值不合法
1011 ERROR_HAS_NO_VALID_TIMESTAMP 没有提供 timestamp,或者值不合法
1012 ERROR_HAS_NO_VALID_EXPIRED 没有提供 expired,或者值不合法
1013 ERROR_HAS_NO_VALID_NONCE 没有提供 nonce,或者值不合法
1014 ERROR_HAS_NO_VALID_TEMPLATENAME 提供的 template_name 不合法
1015 ERROR_HAS_NO_BUCKET 没有提供 bucket,或者值不合法
1016 ERROR_HAS_NO_AMOUNT 没有剩余的免费用量
1017 ERROR_URL_TOO_LONG 提供的 url 长度大于 2048
1018 ERROR_FILEID_TOO_LONG 提供的文件名长度大于 2048
1019 ERROR_APPID_NOT_REGISTER 提供的 APPID 未注册
1020 ERROR_APPID_PROJECTID_TEMPLATENAME_MISMATCH 提供的 APPID,ProjectId 与 template_name 不匹配
1021 ERROR_PROCESS_FAILED 服务端处理出现内部错误
1022 ERROR_PROXY_BAD_AUTH 签名不符合规则
1024 ERROR_PROXY_AUTH_TOO_LONG_EXPIRED 签名的有效期设置太长
1025 ERROR_PROXY_AUTH_EXPIRED 签名过期
1026 ERROR_PROXY_AUTH_PROJECTID_NOEXIST 签名中的 ProjectId 错误
1027 ERROR_PROXY_AUTH_SECRETID_NOEXIST 签名中的 SecretId 错误
1028 ERROR_PROXY_AUTH_PROJECTID_MISMATCH 签名中的 ProjectId 不匹配
1029 ERROR_PROXY_AUTH_REPLAY_ATTACK 重放攻击
1030 ERROR_PROXY_AUTH_FAILED 签名验证不通过
1032 ERROR_AUDIO_TOO_LARGE 发送的语音数据过大(大于 5M)
1034 ERROR_UNKNOWN 其他未知错误

回调错误码

数值 说明
10000 语音非标准格式,转码失败
10001 识别不成功
10002 语音时长过长
10003 语音时长过长
10004 无效的语音文件
10005 其他失败
10006 音轨个数不匹配

PHP 代码示例

//filepath 音频文件路径
//callBackUrl 回调地址
//sourceUrl 语音 URL,只有filepath为空时生效
function sendvoice($filepath, $callBackUrl, $sourceUrl) {
    if (empty ($filepath) && empty ($sourceUrl)) {
        echo "filepath and sourceUrl can not be empty at the same time";
        return -1;
    }
    $reqArr = array ();
    $reqArr['appid'] = Config :: $APPID;
    $reqArr['secretid'] = Config :: $SECRET_ID;
    $reqArr['projectid'] = 0;
    $reqArr['sub_service_type'] = 0; //表示为录音文件识别
    $reqArr['engine_model_type'] = Config :: $ENGINE_MODEL_TYPE;
    $reqArr['callback_url'] = $callBackUrl;
    $reqArr['channel_num'] = Config :: $CHANNEL_NUM;
    $reqArr['res_text_format'] = Config :: $RESULT_TEXT_FORMAT;
    $reqArr['res_type'] = Config :: $RES_TYPE;
    $voicedata = '';
    if (empty ($filepath)) {
        $reqArr['source_type'] = 0; // 语音 URL;
        $reqArr['url'] = $sourceUrl;
    } else {
        $reqArr['source_type'] = 1; // 语音数据(post body)
        $voicedata = file_get_contents($filepath);
    }
    $reqArr['timestamp'] = time();
    $reqArr['expired'] = time() + 24 * 60 * 60;
    $reqArr['nonce'] = rand(1, 10000);

    $serverUrl = "http://aai.qcloud.com/asr/v1/";
    $serverUrl .= $reqArr['appid'] . "?";
    $serverUrl .= "secretid=" . $reqArr['secretid'] . "&";
    $serverUrl .= "projectid=" . $reqArr['projectid'] . "&";
    $serverUrl .= "sub_service_type=" . $reqArr['sub_service_type'] . "&";
    $serverUrl .= "engine_model_type=" . $reqArr['engine_model_type'] . "&";
    $serverUrl .= "callback_url=" . urlencode($reqArr['callback_url']) . "&";
    $serverUrl .= "channel_num=" . $reqArr['channel_num'] . "&";
    $serverUrl .= "res_text_format=" . $reqArr['res_text_format'] . "&";
    $serverUrl .= "res_type=" . $reqArr['res_type'] . "&";
    $serverUrl .= "source_type=" . $reqArr['source_type'] . "&";
    if ($reqArr['source_type'] == 0) {
        $serverUrl .= "url=" . urlencode($reqArr['url']) . "&";
    }
    $serverUrl .= "timestamp=" . $reqArr['timestamp'] . "&";
    $serverUrl .= "expired=" . $reqArr['expired'] . "&";
    $serverUrl .= "nonce=" . $reqArr['nonce'];

    $autho = createSign($reqArr, "POST", "aai.qcloud.com", "/asr/v1/", Config :: $SECRET_KEY);

    $header = array (
        'Authorization: ' . $autho,
        'Content-Length: ' . strlen($voicedata),
    );

    $rsp_str = "";
    $http_code = -1;

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