1. 简介
语音识别技术(Automatic Speech Recognition)简称 ASR,是一种将人的语音转换为文本的技术。语音识别是一个多学科交叉的领域,它与声学、语音学、语言学、数字信号处理理论、信息论、计算机科学等众多学科紧密相连。语音识别技术的应用包括语音拨号、语音导航、室内设备控制、语音文档检索、简单的听写数据录入等。语音识别技术与其他自然语言处理技术如机器翻译及语音合成技术相结合,可以构建出更加复杂的应用,例如语音到语音的翻译
灵云语音识别为开发者提供业界优质的语音服务,通过场景识别优化,为车载导航,智能家居和社交聊天等行业提供语音解决方案,准确率达到 90% 以上,让您的应用绘“声”绘色。语音识别客户端 SDK 是一种面向多平台的解决方案,开发者可根据需要进行相应选择。指南中定义了语法识别、自由说识别、意图识别、实时识别、实时反馈、双路识别等服务接口的使用。关于各服务接口更详细的说明,请参考灵云SDK开发手册。
本文档旨在让开发者快速集成 ASR 能力 SDK,如在集成过程中如有疑问,可登录灵云开发者论坛,查找答案或与其他开发者交流。
1.1 概念解释
为了更好地理解后续的内容,这里对文档中出现的若干专有名词进行解释说明。
更为详细的信息可查看官网文档。
- 根据应用场景的不同,捷通华声将ASR主要分为两类:语法识别和自由说识别,分别提供本地识别和云端识别两种调用模式
本地识别:
本地识别即离线识别模式,加载本地模型并调用本地识别引擎进行语音识别工作,使用的本地设备的计算能力。
云端识别:
云端识别即在线识别模式,调用云端引擎进行语音识别工作,使用的是云端服务的计算能力。
语法识别:
语法识别是指待识别的内容满足一定的规则,系统在语法文件(开发者提供)指定的规则范围内进行识别。有限命令词汇的识别我们也归为语法识别,可将这些命令词的集合看作是一种特殊的语法。常用于命令操作、简单的意图控制等。
自由说识别:
自由说识别则不限定用户说话的范围、方式和内容。但在实际使用时,一般会根据讲话内容的领域采用相应的语言模型作为支撑,以便获得更好的识别率。常用于输入短信、微博或比较随意的对话系统等。
- 根据识别过程的实时性,还可以分为非流式识别,实时识别和实时反馈
非流式识别:
非流式识别即非实时识别,音频数据在整体输入之后才会被进行识别,与实时识别相比响应速度会慢一些。一般用于识别音频数据文件。
实时识别:
实时识别则可以实现边录音边识别,用户可以将音频数据分段多次传入,在输入音频结束后返回最终的识别结果,这样能够获得更快的响应速度。
实时反馈:
实时反馈则在实时识别的基础上进一步优化用户体验,识别的中间过程中也可以反馈识别结果,并可以随着语音数据的增多,根据语境对已反馈的识别结果进行修正。
- 同时捷通华声 ASR 能力还提供意图识别和双路识别,由于篇幅有限,这里只做简要说明,如有需要请查阅相应文档
意图识别:
意图识别是在自由说的基础上,对于识别的文本进行意图获取和意图内容获取。例如天气,股票等不同领域的意图获取。意图识别是一种复合能力,它是结合 ASR 和语义理解(NLU)
双路识别:
双路识别是指同时使用本地识别和云端识别功能,双路识别只支持实时识别模式。详见双路识别集成指南
1.2 能力定义(capkey)
ASR 支持多种能力,通过 capkey 区分不同能力的调用和配置。其中常用 capkey 如下所示:
capkey | 说明 | 领域 | 所需资源文件 |
---|---|---|---|
asr.local.freetalk | 本地自由说 | model_carnav_common 通用模型 model_carnav_poi 导航模型 |
ft_decoder.conf ispk_dnn.dat ispk_hclg.dat ispk_blm.dat ispk_slm.dat |
asr.local.grammar.v4 | 本地语法识别 | model_carnav_common 通用模型 | grm_decoder.conf ispk_aux.dat ispk_dnn.dat ispk_g2p.dat |
asr.cloud.freetalk | 云端自由说 | ||
asr.cloud.grammar | 云端语法识别 |
PS:更多的其他 capkey 可以参考灵云SDK开发手册和灵云开发者社区使用指南中的相关介绍。
1.3 语言模型
ASR 还可以指定识别的领域,针对不同的领域使用其对应的模型进行识别,能够得到更为准确的识别结果。具体详见灵云SDK开发手册中hci_asr_recog函数的domain配置参数。
capkey | 语种 | 领域 |
---|---|---|
asr.local.freetalk | 中文 | 通用领域 |
asr.cloud.freetalk.cantonese | 粤语 | 通用模型 |
asr.cloud.freetalk.music | 中文 | 音乐歌曲 |
asr.cloud.freetalk.poi | 中文 | 地图导航 |
asr.cloud.freetalk.english | 英文 | 通用领域 |
asr.cloud.freetalk.uyghur | 维吾尔语 | 通用领域 |
asr.cloud.freetalk.taiwan | 台湾国语 | 通用领域 |
1.4 语法介绍
ASR 语法识别支持多种语法类型,其中包括jsgf,wordlist,wfst。
JSGF(Java Speetch Grammar Format)是 W3C 制定的标准语法格式,可以参考JSGF规范。JSGF语法示例
#JSGF V1.0 grammar call; public <call> = 打电话给 <contactname>; <contactname> = ( 张三 | 李四 );
wordlist 词条语法。wordlist 语法示例
播放 暂停 停止 上一首 下一首
- wfst
语法识别支持支持在语法文件中设置权重,权重可以是任意浮点数,后面不带数字,缺省值为 1。
JSGF语法文件权重示例
<size> = /10/ small | /2/ medium | /1/ large;
<action> = please (/20/save files |/1/delete all files);
<place> = /20/ <city> | /5/ <country>;
wordlist 语法文件权重示例
四川长虹 /2/
山西电力 /0.5/
1.5 调用流程
主要功能接口的调用过程,如下图所示
2. ASR能力使用说明
2.1 创建应用
在集成 ASR 之前,开发者需要在灵云开发者社区创建相关应用,并保存appkey,developerkey等信息。同时选择需要使用的能力 capkey,详见灵云开发者社区使用指南。
2.2 导入SDK
导入 SDK 与平台相关性较强,这里将根据语言/平台分别进行介绍
2.2.1 使用 Android 版SDK
2.2.1.1 下载SDK
下载语音识别SDK并解压缩。
2.2.1.2 动态库目录介绍
开发者可以根据自身需求组合所需要的动态库。
必选模块
- hcicloud-5.0.jar
- libhci_sys.so
- libhci_sys_jni.so
- libhci_curl.so
- libhci_asr_jni.so
- libhci_asr.so
- libstlport_shared.so
云端识别
- libhci_asr_cloud_recog.so
- libjtspeex.so
- libjtopus.so
本地语法识别
- libhci_asr_local_recog.so
- libiSpeakGrmDNNLite.so
本地自由说识别
- libhci_asr_local_ft_recog.so
- libiSpeakDNNLite.so
2.2.1.3 导入动态库
在 SDK 解压目录下的 libs 文件夹中包含 ASR 能力所需要的动态库,开发者可以根据集成需要进行选择。
请在您的工程目录结构中,添加语音识别(ASR)SDK,下载的 SDK 中libs 目录下有 armeabi,armeabi-v7a,x86,x86_64 等相应平台的库目录。选择需要的动态库放到您的工程目录libs下。
Eclipse:
Android代码Studio 同时将 hcicloud-5.0.jar 放到 app ==> libs 目录下
2.2.1.4 添加用户权限
在工程 AndroidManifest.xml 文件中添加如下权限。
<!—通常需要设置一些sd卡路径(例如日志路径)为可写,因此需要能够写外部存储 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!—以下访问网络的权限均需要打开-->
<!--连接网络权限,用于执行云端能力 -->
<uses-permission android:name="android.permission.INTERNET" />
<!--获取手机录音机使用权限,听写、识别、语义理解需要用到此权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--读取网络信息状态 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!--获取当前wifi状态 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!--允许程序改变网络连接状态 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<!--读取手机信息权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!—以下访问权限可选-->
<!--手机定位信息-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
2.2.2 使用C++版SDK
2.2.2.1 下载SDK
下载语音识别SDK并解压缩。
2.2.2.2 库目录介绍
开发者可以根据自身需求组合所需要的库。
必选模块
- libhci_curl.dll
- hci_sys.dll
- hci_asr.dll
云端识别
- hci_asr_cloud_recog.dll
- jtspeex.dll 或者 jtopus.dll (根据所使用的编解码格式进行选择)
本地语法识别
- iSpeakGrmDNNLite.dll
- hci_asr_local_recog.dll
本地自由说识别
- iSpeakDNNLite.dll
- hci_asr_local_recog.dll
意图识别(在ASR识别库的基础上还需要下边三个库)
- hci_nlu.dll
- hci_nlu_local_recog.dll
- iThinkDialog.dll
2.2.2.3 导入头文件和静态库
将语音识别(ASR)SDK的头文件引入您的工程include目录中
- hci_sys.h
- hci_asr.h
将语音识别(ASR)SDK的静态库文件引入您的工程lib目录中
- hci_asr.lib
- hci_sys.lib
2.2.3 使用ios版SDK
2.2.3.1 下载SDK
下载语音识别SDK并解压缩。
2.2.3.2 库目录介绍
开发者可以根据自身需求组合所需要的库。
必选模块
- libcurl_device_simulator_iOS5.1.1.a
- libhci_sys_device_simulator_iOS5.1.1.a
- libhci_asr_device_simulator_iOS5.1.1.a
云端识别
- libhci_asr_cloud_recog_device_simulator_iOS5.1.1.a
- libjtopus_device_simulator_iOS5.1.1.a
- libjtspeex_recog_device_simulator_iOS5.1.1.a
本地语法识别
- libhci_asr_local_recog_device_simulator_iOS5.1.1.a
本地自由说识别
- libhci_asr_local_ft_recog_device_simulator_iOS5.1.1.a
适配器选择(只选其一)
- libhci_asr_only_cloud_adapter_device_simulator_iOS5.1.1.a(只使用云端识别)
- libhci_asr_only_local_adapter_device_simulator_iOS5.1.1.a(只使用本地语法识别)
- libhci_asr_only_local_ft_adapter_device_simulator_iOS5.1.1.a(只使用本地自由说识别)
- libhci_asr_cloud_local_recog_device_simulator_iOS5.1.1.a(既使用云端识别,又使用本地语法识别和本地自由说识别)
本地意图识别
- libhci_nlu_only_local_adapter_device_simulator_iOS5.1.1.a
- libhci_nlu_device_simulator_iOS5.1.1.a
- libhci_nlu_local_recog_device_simulator_iOS5.1.1.a
PS:开发者如果不使用本地意图识别能力,则需要选择去掉 NLU 依赖的 libhci_asr_device_simulator_iOS5.1.1.a 库文件。
2.2.3.3 导入静态库
在 SDK 解压目录下的 libs 文件夹中包含 ASR 能力所需要的静态库,开发者可以根据集成需要进行选择。
请在工程目录结构中,添加语音识别(ASR)SDK,在选项TARGETS--> Build Phases-->Link Binary With Libraries-->Add Other,选择相应静态库文件并确认。
添加系统依赖框架(Framework)和编译器选项 TARGETS-->Build Phases-->Link Binary With Libraries--> + -->'UIKit','Foundation','SystemConfiguration','Accelerate','CoreLocation','libstdc++'
将语音识别(ASR)SDK的头文件引入您的工程中
- hci_sys.h
- hci_asr.h
最后语音识别(ASR)SDK的编译环境是 stdc++,在选项TARGETS--> Build Settings-->C++ Standard Library,选择libstdc++(GNU C++ standard library)。
同时设置bitcode选项为No,在选项TARGETS--> Build Settings-->Enable Bitcode,选择No。
2.3 导入资源文件
开发者若需调用本地识别能力,则必须将其依赖的资源文件导入工程中。
本地语法模型现提供两种
- model_carnav_common 通用模型
- model_carnav_embeded 车载模型
本地自由说模型现提供三种
- model_carnav_common 通用模型
- model_carnav_embeded 车载模型
- model_carnav_poi 导航模型
请针对不同场景,自行选择。
2.3.1 下载资源
如果需要使用本地语法识别,本地自由说识别或本地意图理解时,请下载相应资源包并解压缩。
2.3.2 资源导入
下图为左侧为本地语法识别的通用模型文件,右侧为本地自由说识别的通用小模型(60M)文件
![]() |
![]() |
从上面的资源图片可以看到本地语法识别和本地自由说识别所依赖的资源文件,存在同名的情况。如果同时导入工程目录中,会存在冲突问题。为了解决这个问题,灵云SDK中可以配置资源前缀参数(resPrefix),详见本地语法加载。
2.4 语法上传
如果是云端语法识别,需要开发者通过开发者社区自行上传语法文件,并获得可以使用的 ID。详情请咨询捷通华声。
3. ASR能力集成
本节主要讲述 ASR 能力的集成过程,开发者可根据本章节内容完成 ASR 能力的简单调用。本章节主要以语法识别为例讲述 ASR 能力的集成调用流程,调用顺序参考调用流程。其他使用场景的调用,可参见场景分类
3.1 通用模块初始化
在调用语音识别(ASR)能力之前,需要初始化灵云SDK的SYS通用模块。详见灵云SDK开发手册
- Android代码
//授权文件路径 默认在文件缓存
String authDirPath = this.getFilesDir().getAbsolutePath();
// 前置条件:无
InitParam initparam = new InitParam();
// 授权文件所在路径,此项必填
initparam.addParam(InitParam.AuthParam.PARAM_KEY_AUTH_PATH, authDirPath);
// 灵云云服务的接口地址,此项必填
initparam.addParam(InitParam.AuthParam.PARAM_KEY_CLOUD_URL, "test.api.hcicloud.com:8888");
// 开发者Key,此项必填,开发者社区申请所得
initparam.addParam(InitParam.AuthParam.PARAM_KEY_DEVELOPER_KEY, "7dafh5eb2dcdb5a1ab78af0000000000");
// 应用Key,此项必填,开发者社区申请所得
initparam.addParam(InitParam.AuthParam.PARAM_KEY_APP_KEY, "60665666");
// 配置日志参数
String sdcardState = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(sdcardState)) {
String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
String packageName = this.getPackageName();
String logPath = sdPath + File.separator + "sinovoice" + File.separator
+ packageName + File.separator + "log" + File.separator;
// 日志文件地址
File fileDir = new File(logPath);
boolean exit= fileDir.exists();
if (!exit) {
fileDir.mkdirs();
}
// 日志的路径,可选,如果不传或者为空则不生成日志
initparam.addParam(InitParam.LogParam.PARAM_KEY_LOG_LEVEL, "5");
initparam.addParam(InitParam.LogParam.PARAM_KEY_LOG_FILE_PATH, logPath);
}
// 初始化 errocode可从开发手册查询到
int errCode = HciCloudSys.hciInit(initparam.getStringConfig(), this);
- C++代码
HCI_ERR_CODE err_code = HCI_ERR_NONE;
//配置串是由"字段=值"的形式给出的一个字符串,多个字段之间以','隔开。字段名不分大小写。
string init_config = "";
//灵云应用 appkey,开发者社区申请所得
init_config += "appKey=1234abcd";
//灵云开发者密钥, 开发者社区申请所得
init_config += ",developerKey=1234567890";
//灵云云服务的接口地址
init_config += ",cloudUrl=http://test.api.hcicloud.com:8888";
//授权文件所在路径,保证可写
init_config += ",authpath=../../bin";
//日志的路径
init_config += ",logfilepath=../../bin";
//日志的等级
init_config += ",loglevel=5";
//日志文件的大小
init_config += ",logfilesize=512";
//其他配置使用默认值,不再添加,如果想设置可以参考开发手册
err_code = hci_init( init_config.c_str() );
- iOS代码
HCI_ERR_CODE errCode = HCI_ERR_NONE;
//appkey, developerKey, cloudUrl, authPath为必填项。其他可配置信息请查询灵云SDK开发手册hci_init函数说明。
NSString *appkey = @""; //开发者社区申请所得
NSString *developerKey = @""; //开发者社区申请所得
NSString *cloudUrl = @""; //开发者社区申请所得
NSString *authPath = @""; //授权文件所在路径,一般设置为沙盒Document路径
NSString *config = [NSString stringWithFormat:@"appkey=%@,developerKey=%@,cloudUrl=%@,authPath=%@", appkey, developerKey, cloudUrl, authPath];
errCode = hci_init(config.UTF8String);
if (errCode != HCI_ERR_NONE &&
errCode != HCI_ERR_SYS_ALREADY_INIT) {
NSLog(@"hci_init failed, error: %@", errCode);
}else{
NSLog(@"hci_init success");
}
常见errcode,详见灵云SDK开发手册
3.2 授权检测
在初始化灵云SDK的SYS通用模块后,还需要调用授权检测函数去云端获取授权。
- Android代码
// 获取授权
private int checkAuthAndUpdateAuth() {
// 获取系统授权到期时间
int initResult;
AuthExpireTime objExpireTime = new AuthExpireTime();
initResult = HciCloudSys.hciGetAuthExpireTime(objExpireTime);
if (initResult == HciErrorCode.HCI_ERR_NONE) {
// 显示授权日期,如用户不需要关注该值,此处代码可忽略
Date date = new Date(objExpireTime.getExpireTime() * 1000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd",Locale.CHINA);
Log.i(TAG, "expire time: " + sdf.format(date));
if (objExpireTime.getExpireTime() * 1000 > System.currentTimeMillis()) {
// 已经成功获取了授权,并且距离授权到期有充足的时间(>7天)
Log.i(TAG, "checkAuth success");
return initResult;
}
}
// 获取过期时间失败或者已经过期
initResult = HciCloudSys.hciCheckAuth();
if (initResult == HciErrorCode.HCI_ERR_NONE) {
Log.i(TAG, "checkAuth success");
return initResult;
} else {
Log.e(TAG, "checkAuth failed: " + initResult);
return initResult;
}
}
- C++代码
// 获取过期时间
int64 expire_time;
int64 current_time = (int64)time( NULL );
HCI_ERR_CODE err_code = hci_get_auth_expire_time( &expire_time );
if( err_code == HCI_ERR_NONE )
{
// 获取成功则判断是否过期
if( expire_time > current_time )
{
//没有过期
printf( "auth can use continue\n" );
return true;
}
}
// 获取过期时间失败或已经过期,手动调用更新授权
err_code = hci_check_auth();
if( err_code == HCI_ERR_NONE )
{
// 更新成功
printf( "check auth success \n" );
return true;
}
else
{
// 更新失败
printf( "check auth return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
return false;
}
- iOS代码
//获取过期时间
int64 expireTime;
int64 currentTime = (int64)time(NULL);
HCI_ERR_CODE errCode = hci_get_auth_expire_time(&expireTime);
if (errCode == HCI_ERR_NONE) {
if (expireTime < currentTime) {
errCode = hci_check_auth();
if(errCode == HCI_ERR_NONE){
NSLog(@"check auth success");
return YES;
}else{
NSLog(@"check auth failed, error: %@", errCode);
return NO;
}
}else{
//没有过期
NSLog(@"auth can use continue");
return YES;
}
}
//读取授权文件出现错误
else if(errCode == HCI_ERR_SYS_AUTHFILE_INVALID){
errCode = hci_check_auth();
if(errCode == HCI_ERR_NONE){
NSLog(@"check auth success");
return YES;
}else{
NSLog(@"check auth failed, error: %@", errCode);
return NO;
}
}else{
NSLog(@"check auth failed, error: %@", errCode);
return NO;
}
常见错误码(errcode)定义,详见灵云SDK开发手册
3.3 ASR 初始化
在初始化灵云SDK的SYS通用模块和授权检测成功后,需调用 ASR 初始化函数。详见灵云SDK开发手册。
注意: 初始化 ASR 之前,需要导入资源文件。若使用本地能力,SDK 需要相应的资源文件用于识别。dataPath 参数所传入的值就是 SDK 所依赖本地资源的文件夹路径。
- Android代码
AsrInitParam asrInitParam = new AsrInitParam();
String dataPath = Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator + "sinovoice"
+ File.separator + this.getPackageName() + File.separator + "data";
// 将assets资源文件夹下 data/目录的资源拷贝至SD卡目录,开发者可自行实现该拷贝方法,也可与预先将资源放置该目录
// copyAssetsFiles(this,dataPath);
// 资源文件所在目录,从灵云开发者社区下载该capkey asr.local.grammar.v4所需的本地资源文件放至该目录
asrInitParam.addParam(AsrInitParam.PARAM_KEY_DATA_PATH, dataPath);
//初始化capkey
asrInitParam.addParam(AsrInitParam.PARAM_KEY_INIT_CAP_KEYS, "asr.local.grammar.v4");
int errCode = HciCloudAsr.hciAsrInit(asrInitParam.getStringConfig());
- C++代码
string asr_init_config = "";
//建议在initcapkeys中添加需要使用的所有能力以提高第一次识别的效率
asr_init_config += "initcapkeys=asr.local.grammar.v4";
//如果是本地能力,此处指定本地能力依赖资源路径
asr_init_config += ",datapath=../../data";
err_code = hci_asr_init(asr_init_config.c_str());
if (err_code != HCI_ERR_NONE)
{
printf("hci_asr_init return (%d:%s) \n",err_code,hci_get_error_info(err_code));
return;
}
- iOS代码
//initCapKeys为必填项,如果为本地语法识别或本地自由说识别dataPath为必填项。其他可配置信息请查询开发手册hci_asr_init函数说明。
NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil]; //本地语法识别或本地自由说识别所需本地资源所在路径
NSString *initCapKeys = @"asr.local.grammar.v4"; //语音识别(ASR)所需使用的能力列表,可以包含多种能力,用';'分号隔开
NSString *config = [NSString stringWithFormat:@"dataPath =%@, initCapKeys =%@", dataPath, initCapKeys];
HCI_ERR_CODE errCode = HCI_ERR_NONE;
errCode = hci_asr_init(config.UTF8String);
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_init failed, error:%@", errCode);
eturn NO;
}
NSLog(@"hci_asr_init success");
return YES;
常见errcode,详见灵云SDK开发手册
3.4 开启会话(session)
ASR 是通过会话(session)来管理识别过程的。在ASR能力初始化成功之后,需要通过开启识别会话来完成识别。详见灵云SDK开发手册
本地实时语法识别示例,如果是本地语法识别,在会话(session)开启前可以进行本地语法加载:
- Android代码
AsrConfig config = new AsrConfig();
// 启动 ASR Session
int errCode = -1;
//系统初始化可以添加多个能力,但每次对话session开启只能指定一个能力
config.addParam(AsrConfig.SessionConfig.PARAM_KEY_CAP_KEY, "asr.local.grammar.v4");
//设置音频编码格式 和传入识别的音频文件编码格式保持一致
config.addParam(AsrConfig.AudioConfig.PARAM_KEY_ENCODE, AsrConfig.AudioConfig.VALUE_OF_PARAM_ENCODE_SPEEX);
//会话开启的字符串配置
String sSessionConfig = config.getStringConfig();
Session nSessionId = new Session();
errCode = HciCloudAsr.hciAsrSessionStart(sSessionConfig, nSessionId);
- C++代码
int nSessionId = -1;
string strSessionConfig = "capkey=asr.local.grammar.v4";
//此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值
err_code = hci_asr_session_start( strSessionConfig.c_str(), &nSessionId );
if( err_code != HCI_ERR_NONE )
{
printf( "hci_asr_session_start return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
return false;
}
- iOS代码
// 开启session
HCI_ERR_CODE errCode = HCI_ERR_NONE;
NSString *config = @"capKey=asr.local.grammar.v4,realtime=yes";
int sessionID; // 开启会话成功后,会返回的会话ID
errCode = hci_asr_session_start(config.UTF8String, &sessionID);
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_session_start failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_session_start success");
return YES;
常见errcode,详见灵云SDK开发手册
3.5 语音识别
在启动会话(session)成功后,即可可以进行 ASR 识别过程。识别功能通过调用识别函数完成,如果是流式识别/实时反馈,则需要多次调用识别函数将语音数据送入 SDK。。配置参数详见灵云SDK开发手册
- Android代码
String audioFile = "sinovoice.pcm";
// 从assets资源目录获取sinovoice.pcm 语音数据文件
byte[] voiceData = Tools.getAssetFileData(this,audioFile);
if (null == voiceData) {
// ShowMessage("Open input voice file" + audioFile + " error!");
return;
}
if (HciErrorCode.HCI_ERR_NONE != errCode) {
// ShowMessage("hciAsrSessionStart error:" + HciCloudSys.hciGetErrorInfo(errCode));
return;
}
ShowMessage("hciAsrSessionStart Success");
// 识别结果
AsrRecogResult asrResult = new AsrRecogResult();
// 识别方法 此处的两个参数( 语音识别配置串,识别语法数据)在SessionStart的时候已经传入了,此处省略
errCode = HciCloudAsr.hciAsrRecog(nSessionId, voiceData, null, null, asrResult);
if (HciErrorCode.HCI_ERR_NONE == errCode) {
// 输出识别结果
printAsrResult(asrResult);
}
// 输出识别结果的方法
private void printAsrResult(AsrRecogResult recogResult) {
if (recogResult.getRecogItemList().size() < 1) {
ShowMessage("recognize result is null");
}
for (int i = 0; i < recogResult.getRecogItemList().size(); i++) {
if (recogResult.getRecogItemList().get(i).getRecogResult() != null) {
String utf8 = recogResult.getRecogItemList().get(i).getRecogResult();
ShowMessage("result index:" + String.valueOf(i) + " result:" + utf8);
} else {
ShowMessage("result index:" + String.valueOf(i) + " result: null");
}
}
}
- C++代码
//以语法识别为例
ASR_RECOG_RESULT asrResult;
string recog_config = "pcm16k16bit,encode=none,grammarType=id,grammarId=1";
err_code = hci_asr_recog( nSessionId, voiceData.buff_, voiceData.buff_len_, recog_config.c_str(), NULL, &asrResult );
if( err_code == HCI_ERR_NONE )
{
printf( "hci_asr_recog success\n" );
// 输出识别结果
PrintAsrResult( asrResult );
// 释放识别结果
hci_asr_free_recog_result( &asrResult );
}
else
{
printf( "hci_asr_recog return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
}
- iOS代码
// 以语法识别为例
HCI_ERR_CODE errCode = HCI_ERR_NONE;
ASR_RECOG_RESULT asrResult; // 识别结果保存
NSString *config = @"audioFormat=pcm16k16bit,encode=none,grammarType=id,grammarId=100";
// _sessionID:为开启会话(session)后获得的sessionID
// _voiceData:为音频数据文件,数据类型为NSData
errCode = hci_asr_recog(_sessionID, (void *)_voiceData.bytes, (unsigned int)_voiceData.length, config.UTF8String, NULL, &asrResult);
if (errCode != HCI_ERR_NONE) {
NSLog(@"hci_asr_recog failed, error:%@"errCode);
}else{
NSLog("hci_asr_recog success");
NSString *strResult = nil;
if (asrResult.psResultItemList > 0) {
if (asrResult.psResultItemList[0].pszResult!= NULL){
strResult = [NSString stringWithUTF8String:asrResult.psResultItemList[0].pszResult];
}
}
if (strResult && strResult.length) {
// 识别结果
}else{
}
hci_asr_free_recog_result(&asrResult);
}
常见errcode,详见灵云SDK开发手册
3.6 结束识别
最后我们需要反初始化,依次关闭会话,终止 ASR 能力,关闭灵云系统。
- Android代码
// 终止session
HciCloudAsr.hciAsrSessionStop(nSessionId);
//反初始化ASR
HciCloudAsr.hciAsrRelease();
//ShowMessage("hciAsrRelease");
HciCloudSys.hciRelease();
- C++代码
HCI_ERR_CODE errCode = HCI_ERR_NONE;
//关闭会话
errCode = hci_asr_session_stop(sessionID); //sessionID:已经开启的会话的sessionID
//终止ASR能力
errCode = hci_asr_release();
//关闭灵云系统
errCode = hci_release();
- iOS代码
//结束session后,调用hci_asr_release和hci_release函数结束能力调用
HCI_ERR_CODE errCode = HCI_ERR_NONE;
errCode = hci_asr_session_stop(sessionID); //sessionID:已经开启的会话的sessionID
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_session_stop failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_session_stop success");
errCode = hci_asr_release();
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_release failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_release success");
errCode = hci_release();
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_release failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_release success");
return YES;
常见errcode,详见灵云SDK开发手册
4 场景分类
前面已介绍过,ASR 可根据不同的使用场景划分语法识别和自由说识别,同时还可以根据实时性分为非流式识别,实时识别和实时反馈。
根据不同场景配置参数的不同,语音识别(ASR)又可以分为意图识别,实时识别和实时反馈。
双路识别,是一种特殊的配置模式。可以赋予语音识别(ASR)同时使用本地和云端的能力。
4.1. 语法识别
语法识别可以分为本地语法识别(asr.local.grammar.v4)和云端语法识别(asr.cloud.grammar)。系统根据开发者提供的语法文件在指定的语法范围内进行识别。这种识别计算资源消耗少,识别率较高,但是要求用户的说话内容必须符合指定的语法。 详见灵云SDK开发手册。
Android代码
使用语法识别需要导入相应的库,详见2.2.1.2 动态库目录介绍
AsrGrammarId grammarId = new AsrGrammarId();
AsrConfig loadConfig = new AsrConfig();
// 语法类型 jsgf类型
loadConfig.addParam(AsrConfig.GrammarConfig.PARAM_KEY_GRAMMAR_TYPE, AsrConfig.GrammarConfig.VALUE_OF_PARAM_GRAMMAR_TYPE_JSGF);
// 语法是否是本地文件
loadConfig.addParam(AsrConfig.GrammarConfig.PARAM_KEY_IS_FILE, AsrConfig.VALUE_OF_NO);
// 设置capkey
loadConfig.addParam(AsrConfig.SessionConfig.PARAM_KEY_CAP_KEY, "asr.local.grammar.v4");
// assets资源目录下的stock_10001.gram 语法文件
String fileName="stock_10001.gram";
// 表示的直接是内存中的语法数据
String strGrammarData = "?#JSGF V1.0;grammar stock_1001;public <stock_1001> = " +
" 万东医疗 | 云天化 | 亚盛集团 | 人福科技 | 北京捷通华声科技股份有限公司 | 光彩建设; ";
/*
本地语法识别加载语法 这里加载本地语法与session无关,多个session可以共享这里加载的语法
参数:
config - 语法配置串,可以通过AsrConfig类辅助生成 设置(AsrConfig.SessionConfig.PARAM_KEY_CAP_KEY ,AsrConfig.GrammarConfig)
grammarData - 语法数据
grammarId - 输出的语法id
*/
int errCode = HciCloudAsr.hciAsrLoadGrammar(loadConfig.getStringConfig(), strGrammarData, grammarId);
语音识别同时只能加载一个语法文件,再次加载语法文件,将自动卸载上次加载的语法文件。或者可以通过下面的方法显示卸载已加载的语法文件。
private void unloadGrammar() {
if(grammarId.isValid()){
HciCloudAsr.hciAsrUnloadGrammar(grammarId);
}
//反初始化ASR
HciCloudAsr.hciAsrRelease();
}
C++代码
使用语法识别需要导入相应平台的库,详见2.2.1.2 动态库目录介绍
// 本地语法识别前的语法加载过程
unsigned int grammar_id = -1;
// 语法文件
string grammar_file = "../../data/stock_10001.gram";
// 传入语法是否为文件类型
string load_config = "isFile=yes";
// 语音识别能力
load_config += ",capkey=asr.local.grammar.v4";
// 资源加载前缀,不涉及多能力调用情况下,该配置可忽略。
load_config += ",resPrefix=grm_";
// 语法类型
load_config += “,grammartype=jsgf”;
err_code = hci_asr_load_grammar(load_config.c_str(),grammar_file.c_str(),&grammar_id);
if (err_code != HCI_ERR_NONE)
{
printf("hci_asr_load_grammar return (%d:%s) \n",err_code,hci_get_error_info(err_code));
hci_asr_release();
return;
}
语音识别同时只能加载一个语法文件,再次加载语法文件,将自动卸载上次加载的语法文件。或者可以通过下面的方法显示卸载已加载的语法文件。
HCI_ERR_CODE errCode = hci_asr_unload_grammar(grammarId); // grammarId为已加载过的语法ID
iOS代码
使用语法识别需要导入相应平台的库,详见2.2.1.2 动态库目录介绍
//本地语法识别前的语法加载过程
NSString *dataPath = [[NSBundle mainBundle] pathForResource:@"data" ofType:Nil];
NSString *capKey = @"asr.local.grammar.v4"; //语音识别能力
NSString *resPrefix = @"grm_"; //资源加载前缀,不涉及多能力调用情况下,该配置可忽略。
NSString *grammarType = @"jsgf"; //语法类型
NSString *isFile = @"yes"; //传入语法是否为文件类型
NSString *grammarPath = [NSString stringWithFormat:@"%@/stock_10001.jsgf",dataPath]; //语法文件路径
NSString *config = [NSString stringWithFormat:@"capKey=%@, resPrefix=%@, grammarType=%@, isFile=%@", capKey, resPrefix, grammarType, isFile];
int grammarId; //加载语法成功后,会返回的语法ID
HCI_ERR_CODE errCode = hci_asr_load_grammar(config.UTF8String, grammarPath.UTF8String, &grammarId);
if(errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_load_grammar, errcode:%@", errCode);
return NO;
}
NSLog(@"hci_asr_load_grammar success");
return YES;
语音识别同时只能加载一个语法文件,再次加载语法文件,将自动卸载上次加载的语法文件。或者可以通过下面的方法显示卸载已加载的语法文件。
HCI_ERR_CODE errCode = hci_asr_unload_grammar(grammarId); //grammarId为已加载过的语法ID
if(errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_unload_grammar failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_unload_grammar success");
return YES;
PS:本地语法识别和本地自由说识别所需本地资源文件存在同名的情况,所以需要配置resPrefix项,如图:
常见errcode,详见灵云SDK开发手册
4.2 自由说识别
自由说识别分为本地自由说识别(asr.local.freetalk)和云端自由说识别(asr.cloud.freetalk)。不限定用户说话的范围、方式和内容。自由说识别常常需要较大的语言模型作为支撑,因此消耗计算资源较大。但这种识别可以用于输入短信、微博或比较随意的对话系统等。针对某些特定领域,也可以采用针对这一领域的语言模型作为支撑,因此对于说话集中在这个领域的内容会获得更好的识别率。例如可以针对歌曲歌手的名称专门建立“音乐”领域的自由说模型。
- Android代码
String sSessionConfig="capkey=asr.cloud.freetalk";
SessionId nSessionId=new SessionId();
//开启session
HciCloudAsr.hciAsrSessionStart(sSessionConfig, nSessionId)
AsrRecogResult asrResult = new AsrRecogResult();
/*
* hciAsrRecog(Session session, 会话
* byte[] recogVoiceData, 音频数据
* String recogConfig, 识别配置串
* String grammarData, 语法文件
* AsrRecogResult outRecogResult) 识别结果
*/
int errCode = HciCloudAsr.hciAsrRecog(nSessionId, voiceData, null, null, asrResult);
if (HciErrorCode.HCI_ERR_NONE == errCode) {
Log.i(TAG, "HciCloudAsr hciAsrRecog Success");
// 输出识别结果
printAsrResult(asrResult);
}
else{
// ShowMessage("hciAsrRecog error:" + HciCloudSys.hciGetErrorInfo(errCode));
}
- C++代码
//开启session
int nSessionId = -1;
string strSessionConfig = "capkey=asr.local.freetalk";
//此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值
err_code = hci_asr_session_start( strSessionConfig.c_str(), &nSessionId );
if( err_code != HCI_ERR_NONE )
{
printf( "hci_asr_session_start return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
return false;
}
- iOS代码
//开启session
HCI_ERR_CODE errCode = HCI_ERR_NONE;
NSString *config = @"capKey=asr.local.freetalk";
int sessionID; //开启会话成功后,会返回的会话ID
errCode = hci_asr_session_start(config.UTF8String, &sessionID);
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_session_start failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_session_start success");
return YES;
4.3 实时识别
启动会话时可通过设置 realtime=yes 来启用实时识别模式,之后可以持续调用识别函数传入语音数据。在识别过程中,如果返回HCI_ERR_ASR_REALTIME_WAITNG,表示未检测到语音活动结束(静音超过指定时长);如果返如HCI_ERR_ASR_REALTIME_END,则表示检测到语音活动结束或者缓冲区满,此时需要调用识别函数传入 NULL 来获取识别结果。C++ 中对应的是 pvVoiceData 传入NULL 和 uiVoiceDataLen为0。
使用者也可以直接传入 NULL 完成识别并获取结果。。
调用识别函数 ,返回除 HCI_ERR_ASR_REALTIME_WATING 或 HCI_ERR_ASR_REALTIME_END 错误码则表示实时识别过程出错,此时 SDK 将取消该次实时识别, 如果用户继续调用该接口传输数据则自动开启一次新的实时识别。 其他情况,如果返回非 HCI_ERR_ASR_REALTIME_WATING 并且非 HCI_ERR_ASR_REALTIME_END 的结果时, 该次调用发送的数据不会被使用,实时识别任务不取消,下次再调用 recog函数发送的数据作为 前一次发送的延续。 实时识别只使用每次新开启时的pszConfig和pszGrammarData数据,在实时识别过程中再传入的pszConfig和pszGrammarData 总是会被忽略。
- Android代码
//每次获取音频文件后都可以传入hciAsrRecog进行识别,这里只是用while循环演示不断调用hciAsrRecog
HString seesionConfig="capkey=asr.cloud.freetalk,realtime=yes";
//开启session
Session nSessionId = new Session();
int errCode = HciCloudAsr.hciAsrSessionStart(seesionConfig, nSessionId);
int nPerLen = 6400; // pcm16k16bit 下对应 200ms 长度的音频
while (1) {
byte[] subVoiceData = new byte[nPerLen];
// 调用识别方法,将音频数据不段的传入引擎
errCode = HciCloudAsr.hciAsrRecog(nSessionId, subVoiceData, null, null, asrResult);
if (errCode == HciErrorCode.HCI_ERR_ASR_REALTIME_END) {
// 检测到末端点,将传一段空数据在识别一遍表示数据传送完毕
errCode = HciCloudAsr.hciAsrRecog(nSessionId, null, null, null, asrResult);
if (HciErrorCode.HCI_ERR_NONE == errCode) {
ShowMessage("hciAsrRecog Success");
// 输出识别结果
printAsrResult(asrResult);
}
else{
ShowMessage("hciAsrRecog error:" + HciCloudSys.hciGetErrorInfo(errCode));
}
}else if (errCode == HciErrorCode.HCI_ERR_ASR_REALTIME_WAITING
|| errCode == HciErrorCode.HCI_ERR_ASR_REALTIME_NO_VOICE_INPUT) {
//在连续识别的场景,忽略这两个情况,继续识别后面的音频。
//HCI_ERR_ASR_REALTIME_WAITING (实时识别等待音频)含义是:还没有数据,或者是需要更多数据。
//HCI_ERR_ASR_REALTIME_NO_VOICE_INPUT 含义是:没有检测到音频起点,即超过了vadHead的范围(此时可以让设备进入休眠状态)
//设置下一段音频;
nextinputFile();
}
else {
// 识别失败
ShowMessage("hciAsrRecog error:" + HciCloudSys.hciGetErrorInfo(errCode));
break;
}
}
// 若未检测到端点,但数据已经传入完毕,则需要告诉引擎数据输入完毕
if (errCode == HciErrorCode.HCI_ERR_ASR_REALTIME_END
|| errCode == HciErrorCode.HCI_ERR_ASR_REALTIME_WAITING) {
errCode = HciCloudAsr.hciAsrRecog(nSessionId, null, recogConfig.getStringConfig(), null, asrResult);
if (HciErrorCode.HCI_ERR_NONE == errCode) {
Log.i(TAG, "HciCloudAsr hciAsrRecog Success");
// 输出识别结果
printAsrResult(asrResult);
}
else{
ShowMessage("hciAsrRecog error:" + HciCloudSys.hciGetErrorInfo(errCode));
}
}
- C++代码
//开启session
int nSessionId = -1;
string strSessionConfig = "capkey=asr.local.freetalk,realtime=yes";
//此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值
err_code = hci_asr_session_start( strSessionConfig.c_str(), &nSessionId );
if( err_code != HCI_ERR_NONE )
{
printf( "hci_asr_session_start return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
return false;
}
//每次获取音频文件后都可以传入hci_asr_recog进行识别,这里只是用while循环演示不断调用hci_asr_recog
char * pszRecogConfig = "audioFormat=pcm16k16bit,encode=none,grammarType=id,grammarId=10";
while (true){
// 每次得到的数据放在 pBuf中,长度为 nLen
...
ASR_RECOG_RESULT asrResult;
//hci_asr_recog参数中,由于是采用语法ID进行识别,所以pszGrammarData语法数据传值为NULL
errCode = hci_asr_recog(nSessionId, pBuf, nLen, pszRecogConfig, NULL, &asrResult);
if (errCode == HCI_ERR_ASR_REALTIME_END)
{
// 正常检测到端点 ,传入NULL和0,获取识别结果,退出循环
errCode = hci_asr_recog(nSessionId, NULL , 0 ,pszRecogConfig, NULL, &asrResult);
break;
}
else if (errCode == HCI_ERR_ASR_REALTIME_WAITING)
{
// 等待数据,继续循环
continue;
}
else
{
// 其它错误,一般不会出现,出现很可能是由于输入数据无效,或实时识别过程错误。
// 如果实时识别过程错误,则自动取消该次实时识别
// 否则可以手动终止本次实时识别, 然后退出循环
// 也可以继续循环,则下次hci_asr_recog()发送的数据会作为前次数据的延续
break;
}
}
- iOS代码
//开启session
HCI_ERR_CODE errCode = HCI_ERR_NONE;
NSString *config = @"capKey=asr.cloud.freetalk,realtime=yes";
int sessionID; //开启会话成功后,会返回的会话ID
errCode = hci_asr_session_start(config.UTF8String, &sessionID);
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_session_start failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_session_start success");
return YES;
//每次获取音频文件后都可以传入hci_asr_recog进行识别,这里只是用while循环演示不断调用hci_asr_recog
HCI_ERR_CODE errCode = HCI_ERR_NONE;
ASR_RECOG_RESULT asrResult; //识别结果保存
NSString *config = @"audioFormat=pcm16k16bit,encode=none,grammarType=id,grammarId=100";
//_sessionID:为开启会话(session)后获得的sessionID
//voiceData:每次获取的音频数据文件,数据类型为NSData
while (1){
//hci_asr_recog参数中,由于是采用语法ID进行识别,所以pszGrammarData语法数据传值为NULL
errCode = hci_asr_recog(_sessionID, (void *) voiceData.bytes, (unsigned int) voiceData.length, config.UTF8String, NULL, &asrResult);
if (errCode == HCI_ERR_ASR_REALTIME_END) {
//正常检测到端点,传入NULL和0,获取识别结果,退出循环
errCode = hci_asr_recog(_sessionID,NULL,0, config.UTF8String, NULL, &asrResult);
break;
}else if (errCode == HCI_ERR_ASR_REALTIME_WAITING){
//等待识别数据,继续循环
continue;
}else{
// 其它错误,一般不会出现,出现很可能是由于输入数据无效,或实时识别过程错误。
// 如果实时识别过程错误,则自动取消该次实时识别
// 否则可以手动终止本次实时识别, 然后退出循环
// 也可以继续循环,则下次hci_asr_recog()发送的数据会作为前次数据的延续
break;
}
}
常见errcode,详见灵云SDK开发手册
4.4 实时反馈
实时反馈即在实时识别的基础上并不只在最后一次获取结果时反馈识别结果,在中间返回过程中也会返回识别结果,此时需要开发者根据返回的识别结果的结构体中的字段进行判断,如果uiResultItemCount > 0则存反馈结果。实时反馈结果不同于实时识别结果,实时反馈结果会分段返回结果。
- Android代码
String seesionConfig="capkey=asr.cloud.freetalk,realtime=rt";
//开启session
Session nSessionId = new Session();
int errCode = HciCloudAsr.hciAsrSessionStart(seesionConfig, nSessionId);
if( err_code != HCI_ERR_NONE )
{
ShowMessage("hciAsrSessionStart failed!");}
}
- C++代码
//开启session
int nSessionId = -1;
string strSessionConfig = "capkey=asr.cloud.freetalk,realtime=rt";
//此处也可以传入其他配置,参见开发手册,此处其他配置采用默认值
err_code = hci_asr_session_start( strSessionConfig.c_str(), &nSessionId );
if( err_code != HCI_ERR_NONE )
{
printf( "hci_asr_session_start return (%d:%s)\n", err_code ,hci_get_error_info(err_code));
return false;
}
- iOS代码
//开启session
HCI_ERR_CODE errCode = HCI_ERR_NONE;
NSString *config = @"capKey=asr.cloud.freetalk,realtime=rt";
int sessionID; //开启会话成功后,会返回的会话ID
errCode = hci_asr_session_start(config.UTF8String, &sessionID);
if (errCode != HCI_ERR_NONE){
NSLog(@"hci_asr_session_start failed, error:%@", errCode);
return NO;
}
NSLog(@"hci_asr_session_start success");
return YES;
识别完成结果示例:
{
"SegmentCount": 1,
"Segment": [{
"SegmentIndex": 1,
"Text": "北京",
"Score": 408,
"StartTime": 0,
"EndTime": 1600
}]
}
{
"SegmentCount": 1,
"Segment": [{
"SegmentIndex": 1,
"Text": "北京捷通华声",
"Score": 2980,
"StartTime": 0,
"EndTime": 1800
}]
}
{
"SegmentCount": 1,
"Segment": [{
"SegmentIndex": 1,
"Text": "北京捷通华声科技",
"Score": 596,
"StartTime": 0,
"EndTime": 2600
}]
}
{
"SegmentCount": 1,
"Segment": [{
"SegmentIndex": 1,
"Text": "北京捷通华声科技股份",
"Score": 1071,
"StartTime": 0,
"EndTime": 3200
}]
}
{
"SegmentCount": 1,
"Segment": [{
"SegmentIndex": 1,
"Text": "北京捷通华声科技股份有限公司",
"Score": 1361,
"StartTime": 0,
"EndTime": 3800
}]
}
获取到识别结果后,需要根据SegmentIndex分段序号来进行分段结果显示,分段序号从1开始,SegmentIndex改变或已经获取到下一个分段则表明前一个分段结果已经完整。
常见errcode,详见灵云SDK开发手册
4.5 意图识别
详见意图识别集成指南
4.6 双路识别
5. FAQ
Q: resPrefix 参数有哪些作用?
A: resPrefix 的参数作用是,当调用本地能力时(本地语法,本地自由说或本地意图识别)时,本地识别引擎需要加载一些必要的本地资源文件用于识别。这时当工程目录中需要同时添加多种本地能力时,文件名存在重名状况会出现文件覆盖的情况,这是不被允许的。由于SDK中默认从工程目中读取文件的文件名时固定的,这时可以通过 resPrefix 参数来通知 SDK,需要读取的文件名在原有的基础上需要添加前缀读取,这时多种能力间文件名就解决了冲突问题。
Q: 我用你们的 ASR 流式识别,java console 控制台一直在打印 211:ASR REALTIME WAITING, 这是个什么错误?
A: 这个不是错误,ASR 流式识别,音频数据块是分片传入的,打印211是说明流式识别还没有检测到末端点,也就是未检测到足够长度的静音,还有音频在传输。
Q: 你们对每次传入的音频片段长度有什么要求?我调用你们的接口,返回了217号错误:HCI_ERR_ASR_VOICE_DATA_TOO_LARGE?
A: 每次传入的音频片段长度应在(0,32K),否则会返回此错误。SDK流式识别,默认是会对音频做切分的。
Q: 你们的实时反馈模式,是否支持本地自由说和本地语法能力?
A: realtime=rt,实时反馈识别结果,仅云端自由说asr.cloud.freetalk支持,其它能力均不支持。
Q: 能否详细说明下端点检测参数vadhead,vadtail,vadthreshold这几个参数的用途?端点检测是否影响识别时间?
A:
- vad head是静音检测头部参数,是指一定时间内没有检测到有效语音就会返no-input-timeout错误,一般设置为10-30s,设置为0代表不检测头部静音超时。vad head不影响识别响应时间。
- vad tail是静音检测尾部参数,实时识别时,识别过程中 检测到连续vad tail时长的静音,认为一句话说完,返回本句的识别结果,一般设置为400-800ms。vad tail会对识别响应时间有影响。
- vad threshold仅影响端点检测灵敏度,越小越灵敏。
Q: 你们的ASR是否支持speex,opus,amr压缩格式?
A: SDK目前还没有开放对AMR格式的支持,后续会开放。云端如果直接通过http接口调用,是可以传amr格式的音频文件进行识别的。我们支持将音频以speex,opus两种方式进行压缩,默认是以speex格式。但是我们的speex,opus是自定义的jt-speex,jt-opus封包格式,和标准的ogg-speex,ogg-opus封包格式有区别。
Q: 你们的ASR对于单次输入的音频时长是否有限制?
A: 通过maxseconds参数控制,默认值为30S。如果输入的声音超过此长,非实时识别返回(HCI_ERR_DATA_SIZE_TOO_LARGE)实时识别返回(HCI_ERR_ASR_REALTIME_END)端点检测认为超过maxseconds为缓冲区满。 例外:云端非实时识别由于网速原因,暂时限定不能超过256k。
Q: 你们对语法文件大小是否有限制?我这边报错:HCI_ERR_ASR_GRAMMAR_DATA_TOO_LARGE?
A: 有限制,语法文件默认的大小范围是(0,64K] 。超出此范围会返回错误。
Q:我的需求是实时识别,外接麦克风,说话就出结果,这个你们可以实现吗?
A: android,ios,windows c++版本,都有recorder的示例程序,在我们asr基础接口上,又封装了一层录音机。windows java版本的SDK,目前没有实现对录音机的封装。
Q: 你们的ASR都支持录入哪些音频格式?
A:
本地识别支持:pcm16k16bit
云端grammar语法识别支持:pcm16k16bit,ulaw16k8bit,alaw16k8bit
云端freetalk和dialog支持:pcm16k16bit,pcm8k16bit,ulaw16k8bit,ulaw8k8bit,alaw16k8bit,alaw8k8bit
注意,实时识别的端点检测暂不支持:alaw, ulaw