Android SDK集成
一. 集成准备
1.1 获取产品ID
集成SDK之前,您首先需要到DUI控制台创建产品,获取如下的产品ID。
1.2 下载和导入SDK
目前Android SDK只支持Android Studio开发环境
javadoc详见SDK包
Android Demo 码云源码地址:https://gitee.com/szaispeech/dui-dds-android-sdk-samples
1.2.1 手动集成
集成SDK要求Android 4.0及其以上的系统且/data分区剩余空间至少200MB
可以前往SDK下载页下载最新的SDK包。
如需SDK历史版本,请前往Android_SDK下载页。
将SDK包中的aar文件( 如lib-dds-1.0.2.1.aar )导入到现有的工程中,放入到libs目录下,并添加配置:
build.gradle
repositories{
flatDir{
dirs 'libs'
}
}
在build.gradle中配置引用sync工程即可。
build.gradle
dependencies {
compile(name:'lib-dds-1.1.11.1', ext:'aar')
compile 'com.google.android.exoplayer:exoplayer-core:2.6.0'
compile 'com.squareup.okhttp3:okhttp:3.9.0'
compile 'com.squareup.okio:okio:1.13.0'
}
二. 初始化SDK
使用以下方法来初始化SDK:
初始化
DDS.getInstance().init(
getApplicationContext(),
new DDSConfig()
.addConfig(DDSConfig.K_DEVICE_ID, deviceId)
.addConfig(DDSConfig.K_PRODUCT_ID, productId)
.addConfig(DDSConfig.K_USER_ID, userId)
.addConfig(DDSConfig.K_ALIAS_KEY, aliasKey)
.addConfig(DDSConfig.K_API_KEY, apiKey)
.addConfig(DDSConfig.K_PRODUCT_KEY, productKey)
.addConfig(DDSConfig.K_PRODUCT_SECRET, productSecret)
.addConfig(DDSConfig.K_DUICORE_ZIP, "duicore.zip")//该配置的用法详见下方"注意"
.addConfig(DDSConfig.K_USE_UPDATE_DUICORE, "false"),
new DDSInitListener() {
@Override
public void onInitComplete(boolean isFull) {
AILog.d(TAG, "onInitComplete: " + isFull);
}
@Override
public void onError(int what, String msg) {
AILog.d(TAG, "onError: " + what + ", error: " + msg);
}
}, new DDSAuthListener() {
@Override
public void onAuthSuccess() {
AILog.d(TAG, "onAuthSuccess");
}
@Override
public void onAuthFailed(String errId, String error) {
AILog.d(TAG, "onAuthFailed: " + errId + ", error:" + error);
}
});
注意:
• addConfig(DDSConfig.K_DUICORE_ZIP, "duicore.zip")这行配置的使用规则:
1)如果duicore.zip的放置位置在assets目录下,那么就可以使用如代码中的写法,直接使用文件名:duicore.zip;
2)如果duicore.zip没有放置在assets目录下,就必须使用duicore.zip文件的绝对路径;
3)在duicore.zip所在的文件夹中,必须配置与duicore.zip文件名相匹配的md5文件;举例:名为duicore.zip的资源文件放置在assets目录下,那么在assets中必须存在duicore.zip.md5sum文件;
在收到 onInitComplete 回调之后,就可以使用DDS来完成对应的操作。
isFull参数如果为false,则表示不完全初始化,缺失资源包,您需要等待资源包的更新下载完成或者内置一份资源包; 如果为true,则表示完全初始化,所有功能就绪。
除了通过监听onInitComplete回调外,还可以直接通过判断DDS.getInstance().getInitStatus()的返回值来检查初始化是否完毕。
/**
* 获取当前初始化的状态
*
* @return DDS.INIT_COMPLETE_NONE 还未初始化完成,表示DDS正在初始化
* DDS.INIT_COMPLETE_NOT_FULL 部分初始化完成,表示DDS已经初始化完成,但还没有完成更新
* DDS.INIT_COMPLETE_FULL 完全初始化完成,已经完成更新
*/
DDS.getInstance().getInitStatus();
注意:
• DDS.getInstance().init()和DDS.getInstance().release()方法不会阻塞应用程序的主线程,也不会影响应用程序性能。
• 当未初始化完成时,尝试调用一些方法时,会抛出 DDSNotInitCompleteException 异常。
• 当调用DDS.getInstance().release()之后,之前注册的observers会失效,再次DDS.getInstance().init()后,您需要对之前的observers重新注册。
使用以下方法来释放SDK:
DDS.getInstance().release();
2.1 参数与配置
需要由开发者在DDSConfig中填写的配置项为:
参数名 | 取值 | 说明 | 是否必须 | 默认值 |
---|---|---|---|---|
DDSConfig.K_PRODUCT_ID | 产品ID字符串 | 产品ID | 必须 | 无 |
DDSConfig.K_ALIAS_KEY | prod/test/(自定义分支) | 产品分支 | 必须 | 无 |
DDSConfig.K_USER_ID | 用户ID字符串 | 用户ID,预留字段 | 必须 | 无 |
DDSConfig.K_API_KEY | apikey字符串 | 限制一个API Key只被指定的客户端使用,来源:DUI控制台-产品接入-授权管理 | 必须 | 无 |
DDSConfig.K_PRODUCT_KEY | 产品Product Key | 用于设备注册请求签名,来源:DUI控制台-产品接入-授权管理 | 必须 | 无 |
DDSConfig.K_PRODUCT_SECRET | 产品Product Secret | 用于设备注册请求签名,来源:DUI控制台-产品接入-授权管理 | 必须 | 无 |
DDSConfig.K_DEVICE_ID | 设备ID | 用于授权认证的原始设备ID,请务必确保设备ID唯一。若不填,则SDK自己收集设备ID。可以通过DDS.getInstance().getDeviceName()获取授权认证后的唯一ID | 可选 | IMEI |
2.2 处理授权
SDK在初始化完毕之后,必须进行有效的授权后方可正常使用。
2.2.1 Profile文件授权
适用于一般产品的授权,请在产品的授权管理中申请API Key:授权操作说明
在DDSConfig中设置以下授权参数。
// 将API key、Product Key、Product Secret填入到产品配置中
config.addConfig(DDSConfig.K_API_KEY, "f09dd3xxxxxxxxxxxxxx2d2292");
config.addConfig(DDSConfig.K_PRODUCT_KEY, "89eb8daf750799a16dc24e18c12xxxxx");
config.addConfig(DDSConfig.K_PRODUCT_SECRET, "c803c737c665a1facccfa0b4abexxxxx");
在SDK初始化时,可以设置 DDSAuthListener 来监听授权的情况。
SDK初始化完毕后,您可以使用 DDS.getInstance().isAuthSuccess() 来判断当前是否授权成功。第一次使用SDK,需要主动调用DDS.getInstance().doAuth()的方法做一次授权。
授权操作需要连接到互联网。
授权成功会回调DDSAuthListener.onAuthSuccess,授权失败会收到回调DDSAuthListener.onAuthFailed,需要重新调用DDS.getInstance().doAuth()。
Profile文件的错误码范围从 "070601“ – "070622",处理流程请参考对应的描述(详见第五节:错误码描述)。
2.3 处理更新
如果您想对发布的产品持续进行免安装的更新和升级,您需要做以下几个操作:
2.3.1 请求更新
您可以选择在合适的时候发起更新请求。当sdk在检查到有更新后,会自动下载资源并进行热更新,结果会以回调的方式通知。
DDS.getInstance().getUpdater().update(new DDSUpdateListener() {
@Override
public void onUpdateFound(String detail) {
AILog.d(TAG, "onUpdateFound");
}
@Override
public void onUpdateFinish() {
AILog.d(TAG, "onUpdateFinish");
}
@Override
public void onDownloadProgress(float progress) {
AILog.d(TAG, "onDownloadProgress :" + progress);
}
@Override
public void onError(int what, String error) {
AILog.d(TAG, "onError :" + what + ", error: " + error);
}
@Override
public void onUpgrade(String version) {
AILog.d(TAG, "onUpgrade :" + version);
}
};
2.3.2 处理更新推送
在您成功发布产品之后,若您已经订阅了消息sys.resource.updated,则会收到资源更新的推送,此时您可以选择直接请求更新,以保持产品一直处于最新状态(推荐)。
DDS.getInstance().getAgent().subscribe("sys.resource.updated", new MessageObserver() {
@Override
public void onMessage(String message, String data) {
try {
DDS.getInstance().getUpdater().update(ddsUpdateListener);
} catch (DDSNotInitCompleteException e) {
e.printStackTrace();
}
}
});
SDK中内置一套资源更新时的通知的UI实现,您可以在DDSConfig中设置 DDSConfig.K_USE_UPDATE_NOTIFICATION 来开启或关闭。
2.4 权限说明
SDK需要的权限如下表,请在AndroidManifest.xml 文件中添加。
权限 | 用途 |
---|---|
android.permission.INTERNET | 允许接入互联网,以便访问我们的云服务 |
android.permission.RECORD_AUDIO | 允许采集音频 |
android.permission.READ_PHONE_STATE | 允许读取必要的设备数据 |
android.permission.ACCESS_WIFI_STATE | 获取WIFI状态 |
android.permission.ACCESS_NETWORK_STATE | 获取网络状态 |
android.permission.WRITE_EXTERNAL_STORAGE | 写入外部存储数据,用于存储一些缓存文件 |
android.permission.READ_EXTERNAL_STORAGE | 读取外部存储数据 |
2.5 代码混淆
如果您的应用使用了混淆, 请添加:
proguard-rules.pro
-dontwarn com.aispeech.**
-keep public class com.aispeech.lasa{*;}
-keep public class com.aispeech.dui.dds.luaBug{ *; }
三. 功能列表
3.1 响应command
3.1.1 客户端动作的执行
详细的command编写说明,请参见客户端动作(command)编写说明
3.1.2 快捷唤醒中的命令响应
当您在DUI平台上定制了command之后,可以使用如下的方式在您的工程中做实现。
类似于Android的广播接收器,您可以在需要的地方注册和注销CommandObserver,同一个CommandObserver可以处理多个commands。
command
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"open_window", "increase.volume"}, commandObserver);
// 注销
DDS.getInstance().getAgent().unSubscribe(commandObserver);
private CommandObserver commandObserver = new CommandObserver() {
@Override
public void onCall(final String command, final String data) {
if (command.equals("open_window")){
JSONObject jsonData = new JSONObject(data);
String intentName = jsonData.optString("intentName");
String w = jsonData.optString("w");
// TODO 依据w的值,执行打开窗户操作
}else if (command.equals("increase.volume")) {
// TODO 处理调大音量的快捷唤醒指令
}
}
};
3.2 响应native api
当您在DUI平台上定制了native api之后,可以使用如下的方式在您的工程中做实现。
类似于Android的广播接收器,您可以在需要的地方注册和注销NativeApiObserver,同一个NativeApiObserver可以处理多个native api。
command
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"query_battery"}, nativeApiObserver);
// 注销
DDS.getInstance().getAgent().unSubscribe(nativeApiObserver);
private NativeApiObserver nativeApiObserver = new NativeApiObserver() {
@Override
public void onQuery(final String nativeApi, final String data) {
if (nativeApi.equals("query_battery")){
JSONObject jsonData = new JSONObject(data);
String intentName = jsonData.optString("intentName");
// 执行查询电量操作
String battery = DeviceUtil.getBattery();
DDS.getInstance().getAgent().feedbackNativeApiResult(nativeApi, new TextWidget().setText(battery));
}
}
};
注:
• 每个onQuery方法执行时,需要调用feedbackNativeApiResult来向DUI平台返回执行结果,表示一个native api执行结束。
• native api的执行超时时间为10s。
更多详细使用请查看: https://www.duiopen.com/docs/skill_FAQ
3.3 响应内置消息
内置消息列表:
message | data | 说明 |
---|---|---|
sys.kernel.ready | 无 | SDK加载完成,所有功能就绪 |
sys.dialog.start | { reason:"wakeup.major",//唤醒词触发对话 } |
对话开始,及开始原因: 1.wakeup.major,唤醒词唤醒 2.wakeup.command,快捷命令唤醒 3.api.startDialog,调用startDialog接口 4.api.sendText,调用sendText接口(对话Idle时) 5.api.triggerIntent,调用triggerIntent接口(对话Idle时) 6.api.avatarClick,调用avatarClick接口(对话Idle时) 7.api.avatarPress,调用avatarPress接口(对话Idle时) |
sys.dialog.error | { errId:071304, errMsg:"asr null" recordId:"70dcef50b8b31a6c02dbac1acee31de7" } |
对话中发生的错误 |
sys.dialog.end | { reason:"normal",//对话正常结束 skillId:"100001246" } { reason:"error",//对话发生错误; errId:071304, errMsg:"asr null", skillId:"100001246" } { reason:"interrupt",//对话被打断。强制结束对话时出现。 skillId:"100001246" } |
对话结束,及结束原因: 1.normal,对话正常结束 2.error,对话发生错误退出 3.interrupt,对话被打断退出 |
sys.dialog.continue | 无 | 对话恢复 |
sys.resource.updated | 无 | 收到线上资源变更的推送 |
sys.wakeup.result | { "type": "major", "word": "你好小驰", "greeting":"主人你好" } |
语音唤醒 |
sys.vad.begin | 无 | VAD触发 |
sys.vad.end | 无 | VAD结束 |
sys.upload.result | { "result":false, "reqId":"xxxx", "errId":71801, "errMsg":"Network Invalid" } |
上传词库、设备信息的结果 |
类似于Android的广播接收器,您可以在需要的地方注册和注销MessageObserver,同一个MessageObserver可以处理多个message。
您可以通过注册消息接收器来接收需要UI展示的数据,具体UI消息数据见:
UI事件及数据定义
command
// 注册
DDS.getInstance().getAgent().subscribe(new String[]{"sys.dialog.start","sys.dialog.end","context.input.text"}, messageObserver);
// 注销
DDS.getInstance().getAgent().unSubscribe(messageObserver);
private MessageObserver messageObserver = new MessageObserver() {
@Override
public void onMessage(final String message, final String data) {
if (message.equals("sys.dialog.start")){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "对话开始了", Toast.LENGTH_LONG).show();
}
});
}else if(message.equals("context.input.text")){
final JSONObject dataJson = new JSONObject(data);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, dataJson.optString("text"), Toast.LENGTH_LONG).show();
}
});
}
}
};
3.4 开启/终止对话
您可以在任何时刻主动开启/终止对话,通过以下接口实现。
dialog
// 开启对话。如果当前已经在对话中,则重新开启新一轮对话。
DDS.getInstance().getAgent().startDialog();
// 关闭对话
DDS.getInstance().getAgent().stopDialog();
// 支持在开启对话时传入一个播报文本, 先播报文本,后开启对话
Agent.startDialog(JSONObject jsonObject)
// 支持在关闭对话时传入一个播报文本, 文本播报结束后自动结束对话
Agent.stopDialog(JSONObject jsonObject)
使用示例:
JSONObject jsonObject = new JSONObject();
jsonObject.put("speakText", "播报文本");
DDS.getInstance().getAgent().startDialog(jsonObject);
// 多模态事件同步,该接口用于客户端给对话中控发送一个事件
DDS.getInstance().getAgent().updateDispatchEvent(JSONObject obj)
使用示例:
JSONObject obj = new JSONObject();
obj.put("endSkill", "true");
DDS.getInstance().getAgent().updateDispatchEvent(obj);
3.5 按键事件
如果您有相关的软硬件按键,您需要关注以下接口,将用户的行为反馈给SDK。
avatar
// 点击唤醒/停止识别/打断播报 操作接口
DDS.getInstance().getAgent().avatarClick();
// 点击唤醒/停止识别/打断播报 操作接口 , 并附带一则欢迎语,当此次是唤醒时,播报这则欢迎语
DDS.getInstance().getAgent().avatarClick("有什么可以帮你");
// 按下按键接口(调用此接口需关闭VAD,VAD在创建产品时可配置)
DDS.getInstance().getAgent().avatarPress();
// 释放按键接口(调用此接口需关闭VAD,VAD在创建产品时可配置)
DDS.getInstance().getAgent().avatarRelease();
3.6 语音播报
参数说明:
1)text 播报文本,支持SSML。
2)priority 优先级
提供4个优先级播报。
①优先级0:保留,与DDS语音交互同级,仅限内部使用;
②优先级1:正常,默认选项,同级按序播放;
③优先级2:重要,可以插话<优先级1>,同级按序播放,播报完毕后继续播报刚才被插话的<优先级1>;
④优先级3:紧急,可以打断当前正在播放的<优先级1|优先级2>,同级按序播放,播报完毕后不再继续播报刚才被打断的<优先级1|优先级2>。
3)ttsId 用于追踪该次播报的id,建议使用UUID。
4)audioFocus 该次播报的音频焦点,默认值:
①优先级0:android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
②优先级非0:android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
tts
// 请求语音播报
DDS.getInstance().getAgent().getTTSEngine().speak("这是一段测试文本", 1, "100", AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
停止播报接口如下:
1)ttsId与speak接口的ttsId一致,则停止或者移除该播报;
2)ttsId为空, 停止所有播报;
3)ttsId为"0",停止当前播报。
tts
// 停止播报
DDS.getInstance().getAgent().getTTSEngine().shutup("100");
3.7 内置H5
您如果使用和上传了h5资源,可以通过以下方法来获取h5资源包的index.html文件的路径用来在webview中加载。
H5
// 获取资源包中h5的index.html文件的绝对路径
DDS.getInstance().getAgent().getValidH5Path();
3.8 外部录音机拾音
您如果有自己的录音机,可以通过以下方法将录音数据传给DDS。
external recorder
// 注意:需要将DDSConfig.K_RECORDER_MODE设置为"external",用来关闭DDS内置录音机,该接口才会生效
// 音频长度:无限制。内置录音机是3200(单麦)
// 调用间隔:无限制。内置录音机是100ms
// 调用时机:无限制。DDS会根据对话状态将接受的音频送入识别或者丢弃。
DDS.getInstance().getAgent().feedPcm(byte[] pcm);
3.9 外部TTS引擎
您如果使用第三方的TTS引擎,可以通过以下方法来将第三方TTS引擎注册到DDS中。
External TTS Engine
// 注意:需要将DDSConfig.K_TTS_MODE设置为"external",用来声明使用第三方TTS引擎,该接口才会生效。
// 注册
DDS.getInstance().getAgent().setTTSRequestListener(listener)
// 播报结束通知
DDS.getInstance().getAgent().notifyTTSEnd();
private TTSRequestListener listener = new TTSRequestListener() {
@Override
public void onStart(String type, String content) {
Log.d(TAG, "tts start," + type + ":" + content);
int code = mExternelTts.startSpeaking(content, mTtsListener);
if (code != ErrorCode.SUCCESS) {
Log.d(TAG, "语音合成失败,错误码: " + code);
}
}
@Override
public void onStop() {
Log.d(TAG, "tts stop");
mExternelTts.stopSpeaking();
}
};
3.10 场景模式
SDK提供了一些场景(如TTS播报/拾音距离)的切换,您可以在需要的时候调用下面的接口。
DDSMode
//TTS场景切换
DDS.getInstance().getAgent().setDDSMode(DDSMode.TTS_SILENCE); //在静音模式下,所有TTS播报将会被静音。
DDS.getInstance().getAgent().setDDSMode(DDSMode.TTS_NORMAL); //默认值。
//拾音场景切换。仅在"电视助手"解决方案中生效。
DDS.getInstance().getAgent().setDDSMode(DDSMode.PICKUP_NEAR); //在近场模式下,将加载产品配置页中的近场配置
DDS.getInstance().getAgent().setDDSMode(DDSMode.PICKUP_FAR); //在远场模式下,将加载产品配置页中的远场配置
3.11 触发指定意图
如果您期望主动触发某个意图的对话,可以在需要的时候调用下面的接口。
参数说明:
1)skill 技能名称,必填。
2)task 任务名称,必填。
3)intent 意图名称,必填。
4)slots 语义槽的key-value Json,可选。
triggerIntent
//跳过识别和语义,直接进入指定的意图对话。即:DDS主动向用户发起一轮对话。
DDS.getInstance().getAgent().triggerIntent("我是技能名称", "我是任务名称", "我是意图名称", new JSONObject().put("语义槽名称一", "语义槽取值一").put("语义槽名称二", "语义槽取值二").toString());
根据skillid触发意图:
SkillIntent skillIntent = new SkillIntent("我是技能id",
"我是任务名称", "我是意图名称",
new JSONObject().put("语义槽名称一", "语义槽取值一").put("语义槽名称二", "语义槽取值二").toString());
DDS.getInstance().getAgent().triggerIntent(skillIntent);
3.12 更新用户词库
如果您期望更新用户的词库,使其能在技能中使用,可以在需要的时候调用下面的接口。上传结果可以通过sys.upload.result消息来获取。
注意:更新的词库仅在该设备下有效,不会影响其他设备。
参数说明:
vocabIntent: 词库intent。包含词库名name,操作action,词条列表contents。
注1:若词库名是sys.联系人,则会自动做分词处理。
注2:若需要上传带同义词的词条,格式如下:"${词条取值}:${同义词1},${同义词2}"
返回值:请求ID,用于追踪sys.upload.result。
updateVocabs
//实时更新用户词库
/*
//增加词条
DDS.getInstance().getAgent().updateVocab("设备词库", new String[]{"空调", "电视:电视机", "电灯:电灯泡,灯泡"}, true);
DDS.getInstance().getAgent().updateVocab("sys.联系人", new String[]{"张三", "李四"}, true);
//删除词条
DDS.getInstance().getAgent().updateVocab("设备词库", new String[]{"空调", "电视:电视机,彩电"}, false);
//删除所有词条
DDS.getInstance().getAgent().updateVocab("设备词库", null, false);
*/
//向指定词库中添加词条
final String reqId = DDS.getInstance().getAgent().updateVocabs(
new VocabIntent()
.setName("应用列表")
.setAction(VocabIntent.ACTION_INSERT)
.setContents(Arrays.asList("淘宝", "支付宝:支护宝,付款码"))
);
//清空之前上传到该词库的所有词条,然后添加词条
DDS.getInstance().getAgent().updateVocabs(
new VocabIntent()
.setName("设备词库")
.setAction(VocabIntent.ACTION_CLEAR_AND_INSERT)
.setContents(Arrays.asList("空调", "电视:电视机"))
);
//删除该词库的词条
DDS.getInstance().getAgent().updateVocabs(
new VocabIntent()
.setName("歌手名")
.setAction(VocabIntent.ACTION_REMOVE)
.addContent("刘德华")
);
//清空之前上传到该词库的所有词条
DDS.getInstance().getAgent().updateVocabs(
new VocabIntent()
.setName("歌曲")
.setAction(VocabIntent.ACTION_CLEAR_ALL)
);
//批量更新词库
DDS.getInstance().getAgent().updateVocabs(
//向指定词库中添加词条
new VocabIntent()
.setName("sys.联系人")
.setAction(VocabIntent.ACTION_INSERT)
.addContent("董芳芳")
.addContent("王强"),
//清空之前上传到该词库的所有词条,然后添加词条
new VocabIntent()
.setName("设备词库")
.setAction(VocabIntent.ACTION_CLEAR_AND_INSERT)
.setContents(Arrays.asList("空调", "电视:电视机")),
//删除该词库的词条
new VocabIntent()
.setName("歌手名")
.setAction(VocabIntent.ACTION_REMOVE)
.addContent("刘德华"),
//清空之前上传到该词库的所有词条
new VocabIntent()
.setName("歌曲")
.setAction(VocabIntent.ACTION_CLEAR_ALL)
);
//关注更新词库的结果
DDS.getInstance().getAgent().subscribe("sys.upload.result", new MessageObserver() {
@Override
public void onMessage(String message, String data) {
Log.e(TAG, message + ":" + data);
try {
JSONObject obj = new JSONObject(data);
if (reqId.equals(obj.optString("reqId", ""))) {
Log.d(TAG, "updateVocabs result:" + obj.optBoolean("result", false));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
3.13 开启/终止识别
如果您期望仅开启识别并获取识别结果,可以在需要的时候调用下面的接口。
ASREngine
//获取识别引擎
ASREngine asrEngine = DDS.getInstance().getAgent().getASREngine();
//开启识别
asrEngine.startListening(new ASREngine.Callback() {
@Override
public void beginningOfSpeech() {
AILog.i(TAG, "检测到用户开始说话");
}
/**
* @buffer 音频数据属性:单声道 16bit
*/
@Override
public void bufferReceived(byte[] buffer) {
AILog.i(TAG, "用户说话的音频数据");
}
@Override
public void endOfSpeech() {
AILog.i(TAG, "检测到用户结束说话");
}
/**
* @results. eof 为 0 代表识别过程中的结果, 为 1 代表识别结束的最终结果
* {"var":"今","sessionId":"0b48c0d086efc42d55bbf1068137655d","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":0}
* {"var":"今天 天气","sessionId":"0b48c0d086efc42d55bbf1068137655d","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":0}
* {"sessionId":"0b48c0d086efc42d55bbf1068137655d","pinyin":"jin tian tian qi","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":1,"text":"今天 天气"}
*/
@Override
public void partialResults(String results) {
AILog.i(TAG, "实时识别结果反馈");
}
/**
* @results. {"sessionId":"0b48c0d086efc42d55bbf1068137655d","recordId":"6b3ccb1ee745d42fa6ddb74330b1c059","eof":1,"text":"今天天气","pinyin":"jin tian tian qi"}
*/
@Override
public void finalResults(String results) {
AILog.i(TAG, "最终识别结果反馈");
}
@Override
public void error(String error) {
AILog.i(TAG, "识别过程中发生的错误");
}
@Override
public void rmsChanged(float rmsdB) {
AILog.i(TAG, "用户说话的音量分贝");
}
});
//主动结束此次识别
asrEngine.stopListening();
//取消此次识别
asrEngine.cancel();
3.13.1 设置实时回传音量
// 设置实时回传音量大小, 默认为true
// 设置false之后, ASREngine.Callback.rmsChanged()不再回传音量变化值
DDS.getInstance().getAgent().getASREngine().enableVolume(boolean enable);
3.14 VAD相关设置
3.14.1设置VAD后端停顿时间
如果您期望修改VAD后端检测的时间,可以在需要的时候调用下面的接口。
参数说明
millis 后端检测时间,单位毫秒,默认500毫秒。即若VAD在用户说话时停顿超过一定的时间,则认为用户已经说完,发出sys.vad.end消息,结束录音。
setVadPauseTime
//设置VAD后端停顿时间 DDS.getInstance().getAgent()
.getASREngine().setVadPauseTime(1000);//获取VAD后端停顿时间 DDS.getInstance().getAgent()
.getASREngine().getVadPauseTime();
3.14.2 设置VAD前端静音检测超时时间
如果您期望修改VAD前端静音检测超时时间,可以在需要的时候调用下面的接口。设置成功后,vad再次启动生效。
参数说明:
millis 前端静音检测超时时间,单位毫秒,默认8000毫秒。若VAD启动,一直未检测到用户说话,超过一定时间,发出sys.vad.timeout消息,结束录音。
setVadTimeout
//设置VAD前端静音检测超时时间
DDS.getInstance().getAgent().getASREngine().setVadTimeout(1000);
//获取VAD前端静音检测超时时间
DDS.getInstance().getAgent().getASREngine().getVadTimeout();
3.15 输入文本
如果您期望跳过识别直接输入文本进行对话,可以在需要的时候调用下面的接口。
若当前没有在对话中,则以文本作为首轮说法,新发起一轮对话请求。
若当前正在对话中,则跳过识别,直接发送文本。
参数说明
text 输入的文本内容
sendText
//输入文本
DDS.getInstance().getAgent().sendText("帮我选择第一个");
3.16 TTS相关设置
3.16.1 TTS事件回调
如果您想在TTS播报的相关时间节点收到通知,如:开始播报,播报结束。可以使用如下的方式:
OnTTSListener
DDS.getInstance().getAgent().getTTSEngine().setListener(new TTSEngine.Callback() {
/**
* 开始合成时的回调
* @param ttsId 当前TTS的id, 对话过程中的播报ttsid默认为0,通过speak接口调用的播报,ttsid由speak接口指定。
*/
@Override
public void beginning(String ttsId) {
Log.d(TAG, "TTS开始播报");
}
/**
* 合成的音频数据的回调,可能会返回多次,data长度为0表示音频结束
* @param data 音频数据属性:单声道 16bit, pcm
*/
@Override
public void received(byte[] data) {
Log.d(TAG, "收到音频,此方法会回调多次,直至data为0,音频结束");
}
/**
* TTS播报完成的回调
* @param status 播报结束的状态。
* 正常播报结束为0
* 播报中途被打断结束为1
*/
@Override
public void end(String ttsId, int status) {
Log.d(TAG, "TTS播报结束");
}
/**
* 合成过程中出现错误的回调
* @param error 错误信息
*/
@Override
public void error(String error) {
Log.d(TAG, "出现错误,"+error);
}
});
3.16.2 TTS参数设置
如果您想通过SDK定制不同的合成音类型,可以在需要的时候调用下面的接口。
setTTS
* 设置TTS播报类型的接口
* 调用此接口则云端配置的合成音类型失效,此后的合成音类型都将由此接口来托管
* @param speaker 取值如:zhilingf, gdgm等,若取为null,则表示随机改为一个不同的类型
*/
DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingf");
/**
* 设置TTS播报类型的接口
* 调用此接口则云端配置的合成音类型失效,此后的合成音类型都将由此接口来托管
* @param speaker 取值如:zhilingf, gdgm等
* @param path 取值如:"sdcard/tts/zhilingf.bin",自定义合成间类型的全路径
*/
DDS.getInstance().getAgent().getTTSEngine().setSpeaker("zhilingf","sdcard/tts/zhilingf.bin");
/**
* 设置TTS播报语速的接口
* 调用此接口则云端配置的合成音语速失效,此后的合成音语速都将由此接口来托管
*
* @param speed 语速,取值0.5-2.0,0.5语速最快,2.0语速最慢,对应控制台上合成音倍率值
*/
DDS.getInstance().getAgent().getTTSEngine().setSpeed(1.0f);
/**
* 设置TTS播报音量的接口
* 调用此接口则云端配置的合成音音量失效,此后的合成音音量都将由此接口来托管
*
* @param volume 音量大小,取值1-100
*/
DDS.getInstance().getAgent().getTTSEngine().setVolume(50);
/**
* 设置TTS引擎为本地或者云端
*
* @param mode 取值 TTSEngine.LOCAL(本地合成),TTSEngine.CLOUD(云端合成)
*/
DDS.getInstance().getAgent().getTTSEngine().setMode(TTSEngine.LOCAL);
/**
* 设置TTS播报的通道
* @param streamType AudioManager.STREAM_*的取值
* @throws DDSNotInitCompleteException
*/
DDS.getInstance().getAgent().getTTSEngine().setStreamType(int streamType);
/**
* 设置TTS播报的通道(安卓7.0版本以上支持,并且需要配置K_AUDIO_USAGE和K_CONTENT_TYPE)
* @param usage 取值: AudioAttributes.USAGE_*
* @param contentType 取值: AudioAttributes.CONTENT_TYPE_*
* @throws DDSNotInitCompleteException
*/
DDS.getInstance().getAgent().getTTSEngine().setUsage(int usage, int contentType);
/**
* 设置TTS播报自定义录音
* @param customAudioList 自定义播报音频列表
* @throws DDSNotInitCompleteException
*/
DDS.getInstance().getAgent().getTTSEngine().setCustomAudio(List<CustomAudioBean> customAudioList);
/**
* 设备抢焦点,默认为抢焦点
* @param enable true/false true: 抢焦点 false: 不抢焦点
*/
DDS.getInstance().getAgent().getTTSEngine().enableFocus(boolean enable);
/**
* 设置TTS人设
* @param style 风格,humor:幽默;calm:沉稳;common:普通;简短:short;
*/
DDS.getInstance().getAgent().getTTSEngine().setStyle(String style);
/**
* 清除TTS人设
*/
DDS.getInstance().getAgent().getTTSEngine().removeStyle();
/**
* 设置TTS结束后延迟时间,单位ms
* @param afterTime
* @throws DDSNotInitCompleteException
*/
public void setPlayAfterTime(int afterTime);
3.16.3 TTS参数获取
如果您想获取当前TTS配置的接口,可以调用如下接口:
getTTS
//返回String 当前使用的合成音类型,如:"zhilingf",获取失败返回null
DDS.getInstance().getAgent().getTTSEngine().getSpeaker();
//返回float 当前合成音语速,返回值0.5-2.0,0.5语速最快,2.0语速最慢,获取失败返回 0
DDS.getInstance().getAgent().getTTSEngine().getSpeed();
//返回int 当前合成音音量,返回值1-100,获取失败返回 0
DDS.getInstance().getAgent().getTTSEngine().getVolume();
//返回List<CustomAudioBean> 当前自定义播报音频的列表
DDS.getInstance().getAgent().getTTSEngine().getCustomAudio();
//获取当前TTS人设
DDS.getInstance().getAgent().getTTSEngine().getStyle();
3.17 唤醒相关设置
唤醒词介绍:当前除了主唤醒,唤醒词的类型还包括了 副唤醒词、命令唤醒词(快捷唤醒词)、打断唤醒词、快速唤醒词。
副唤醒词:如果您期望为设备增加一个别名,可以通过设置该类型唤醒词来完成。
命令唤醒词(快捷唤醒词): 如果您期望在唤醒的时候执行一条指令,可以通过设置该类型唤醒词来完成。
打断唤醒词:如果您期望在唤醒的时候能同时打断语音播报,可以通过设置该类型唤醒词来完成。
快速唤醒词:您想通过代码来控制快速唤醒,QuickStart词为类似“导航去”、“我想听”等,此类唤醒词只在oneshot模式下生效,作用为在未唤醒状态下语音输入“导航去天安门”,可直接进入对话流程。
3.17.1 开关唤醒
默认SDK加载后不会启动语音唤醒,您可以通过以下接口对需对语音唤醒进行控制。
wakeup
// 开启语音唤醒
DDS.getInstance().getAgent().getWakeupEngine().enableWakeup();
// 关闭语音唤醒
DDS.getInstance().getAgent().getWakeupEngine().disableWakeup();
// 获取主唤醒词列表
DDS.getInstance().getAgent().getWakeupEngine().getWakeupWords();
3.17.2 更新副唤醒词
如果您期望为设备增加一个副唤醒词,可以在需要的时候调用下面的接口。
参数说明:
1)word 副唤醒词,若设置null,则清空当前的副唤醒词。
2)pinyin 副唤醒词的拼音,形如:ni hao xiao chi。
3)threshold 副唤醒词的阈值,形如:0.120(取值范围:0-1)。若设置null,则自动估算。
4)greetings 副唤醒词的欢迎语,若设置null,则与主唤醒词保持一致。
updateMinorWakeupWord
// 实时更新副唤醒词(1.1.2.1版本及以上支持)
WakeupWord minorWord = new WakeupWord()
.setPinyin("ni hao xiao chi")
.setWord("你好小迟")
.setThreshold("0.15")
.addGreeting("我在");
DDS.getInstance().getAgent().getWakeupEngine().updateMinorWakeupWord(minorWord);
//获取当前的副唤醒词
DDS.getInstance().getAgent().getWakeupEngine().getMinorWakeupWord();
3.17.3 更新命令唤醒词(快捷唤醒词)
如果您期望在唤醒的时候执行一条指令,可以在需要的时候调用下面的接口。命令唤醒词和DUI控制台所设置的快捷唤醒词是相同的功能,且互不影响,可同时存在,根据需求来选择设置方式。
参数说明:
1)actions 命令唤醒词指令,为string数组,不为null。
2)words 命令唤醒词,为string数组,不为null。
3)pinyins 命令唤醒词的拼音,形如:ni hao xiao chi,为string数组, 不为null。
4)thresholds 命令唤醒词的阈值,形如:0.120(取值范围:0-1),为string数组,不为null。
5)greetings 命令唤醒词的欢迎语,为string二维数组,不为null,每维对应一个唤醒词的欢迎语。
updateCommandWakeupWord
// 实时更新命令唤醒词-更新一条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
.setPinyin("xia yi shou")
.setWord("下一首")
.setThreshold("0.18")
.addGreeting("我在")
.setAction("sys.next");
DDS.getInstance().getAgent().getWakeupEngine().updateCommandWakeupWord(commandWord);
// 实时更新命令唤醒词-更新多条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
.setPinyin("xia yi shou")
.setWord("下一首")
.setThreshold("0.18")
.addGreeting("我在")
.setAction("sys.next");
WakeupWord commandWord1 = new WakeupWord()
.setPinyin("shang yi shou")
.setWord("上一首")
.addGreeting("我在")
.setThreshold("0.20")
.setAction("sys.play");
List<WakeupWord> commandList = new ArrayList<>();
commandList.add(commandWord);
commandList.add(commandWord1);
DDS.getInstance().getAgent().getWakeupEngine().updateCommandWakeupWords(commandList);
//清空当前设置的命令唤醒词
DDS.getInstance().getAgent().getWakeupEngine().clearCommandWakeupWord();
3.17.4 更新打断唤醒词
如果您期望在唤醒的时候能同时打断语音播报,可以在需要的时候调用下面的接口。打断唤醒词暂不支持在DUI控制台设置。(说明:打断需要设备开启回声消除)
参数说明:
1)words 打断唤醒词,为string数组,不为null。
2)pinyins 打断唤醒词的拼音,形如:ni hao xiao chi,为string数组,不为null。
3)thresholds 打断唤醒词的阈值,形如:0.120(取值范围:0-1)为string数组,不为null。
updateShortcutWakeupWord
//实时更新打断唤醒词-更新一条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
.setPinyin("da duan")
.setWord("打断")
.setThreshold("0.18");
DDS.getInstance().getAgent().getWakeupEngine().updateShortcutWakeupWord(fixWord);
//实时更新打断唤醒词-更新多条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
.setPinyin("da duan")
.setWord("打断")
.setThreshold("0.18");
WakeupWord fixWord1 = new WakeupWord()
.setPinyin("da duan ba")
.setWord("打断吧")
.setThreshold("0.16");
List<WakeupWord> fixList = new ArrayList<>();
fixList.add(fixWord);
fixList.add(fixWord1);
DDS.getInstance().getAgent().getWakeupEngine().updateShortcutWakeupWords(fixList);
//清空当前设置的打断唤醒词
DDS.getInstance().getAgent().getWakeupEngine().clearShortCutWakeupWord();
3.17.5 添加/删除指定的命令唤醒词(快捷唤醒词)
如果您期望添加或者移除一些命令唤醒词而保留之前的命令唤醒词(即控制台上的快捷唤醒词),可以调用下面的接口。
add remove
// 实时添加命令唤醒词-添加一条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
.setPinyin("xia yi shou")
.setWord("下一首")
.setThreshold("0.18")
.addGreeting("我在")
.setAction("sys.next");
DDS.getInstance().getAgent().getWakeupEngine().addCommandWakeupWord(commandWord);
// 实时添加命令唤醒词-添加多条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord()
.setPinyin("xia yi shou")
.setWord("下一首")
.setThreshold("0.18")
.addGreeting("我在")
.setAction("sys.next");
WakeupWord commandWord1 = new WakeupWord()
.setPinyin("shang yi shou")
.setWord("上一首")
.addGreeting("我在")
.setThreshold("0.20")
.setAction("sys.play");
List<WakeupWord> commandList = new ArrayList<>();
commandList.add(commandWord);
commandList.add(commandWord1);
DDS.getInstance().getAgent().getWakeupEngine().addCommandWakeupWords(commandList);
// 实时移除命令唤醒词-移除一条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord().setWord("下一首");
DDS.getInstance().getAgent().getWakeupEngine().removeCommandWakeupWord(commandWord);
// 实时移除命令唤醒词-移除多条命令唤醒词(1.1.2.1版本及以上支持)
WakeupWord commandWord = new WakeupWord().setWord("下一首");
WakeupWord commandWord1 = new WakeupWord().setWord("上一首");
List<WakeupWord> commandList = new ArrayList<>();
commandList.add(commandWord);
commandList.add(commandWord1);
DDS.getInstance().getAgent().getWakeupEngine().removeCommandWakeupWords(commandList);
3.17.6 添加/删除指定的打断唤醒词
如果您期望添加或者移除一些打断唤醒词而保留之前的打断唤醒词,可以在需要的时候调用下面的接口。
add remove
//实时添加打断唤醒词-添加一条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
.setPinyin("da duan")
.setWord("打断")
.setThreshold("0.18");
DDS.getInstance().getAgent().getWakeupEngine().addShortcutWakeupWord(fixWord);
//实时添加打断唤醒词-添加多条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord()
.setPinyin("da duan")
.setWord("打断")
.setThreshold("0.18");
WakeupWord fixWord1 = new WakeupWord()
.setPinyin("da duan ba")
.setWord("打断吧")
.setThreshold("0.16");
List<WakeupWord> fixList = new ArrayList<>();
fixList.add(fixWord);
fixList.add(fixWord1);
DDS.getInstance().getAgent().getWakeupEngine().addShortcutWakeupWords(fixList);
//实时移除打断唤醒词-移除一条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord().setWord("打断");
DDS.getInstance().getAgent().getWakeupEngine().removeShortcutWakeupWord(fixWord);
//实时移除打断唤醒词-移除多条打断唤醒词(1.1.2.1版本及以上支持)
WakeupWord fixWord = new WakeupWord().setWord("打断");
WakeupWord fixWord1 = new WakeupWord().setWord("打断吧");
List<WakeupWord> fixList = new ArrayList<>();
fixList.add(fixWord);
fixList.add(fixWord1);
DDS.getInstance().getAgent().getWakeupEngine().removeShortcutWakeupWords(fixList);
3.17.7 添加/删除指定的主唤醒词
如果您想通过代码来控制主唤醒词,可以调用下面的接口。
注意:通过此接口添加的主唤醒词会屏蔽控制台添加的主唤醒词。
主唤醒词
//实时添加主唤醒词-添加一条主唤醒词(1.1.2.1版本及以上支持)
//更新多条主唤醒词的接口,覆盖原有的主唤醒词
WakeupWord mainWord = new WakeupWord() .setPinyin("ni hao xiao chi") .setWord("你好小迟") .addGreeting("我在") .setThreshold("0.15"); DDS.getInstance().getAgent().getWakeupEngine().addMainWakeupWord(mainWord); //实时添加主唤醒词-添加多条主唤醒词(1.1.2.1版本及以上支持)
WakeupWord mainWord = new WakeupWord() .setPinyin("ni hao xiao chi") .setWord("你好小迟") .addGreeting("我在") .setThreshold("0.15"); WakeupWord mainWord2 = new WakeupWord() .setPinyin("ni hao xiao le") .setWord("你好小乐") .addGreeting("我在") .setThreshold("0.15"); List<WakeupWord> mainWordList = new ArrayList<>(); mainWordList.add(mainWord); mainWordList.add(mainWord2); DDS.getInstance().getAgent().getWakeupEngine().addMainWakeupWords(mainWordList); //实时移除主唤醒词-移除一条主唤醒词(1.1.2.1版本及以上支持)
WakeupWord mainWord = new WakeupWord().setWord("你好小迟"); DDS.getInstance().getAgent().getWakeupEngine().removeMainWakeupWord(mainWord); //实时移除主唤醒词-移除多条主唤醒词(1.1.2.1版本及以上支持)
WakeupWord mainWord = new WakeupWord().setWord("你好小迟"); WakeupWord mainWord2 = new WakeupWord().setWord("你好小乐"); List<WakeupWord> mainWordList = new ArrayList<>(); mainWordList.add(mainWord); mainWordList.add(mainWord2); DDS.getInstance().getAgent().getWakeupEngine().removeMainWakeupWords(mainWordList);
WakeupWord mainWord = new WakeupWord() .setPinyin("ni hao xiao le") .setWord("你好小乐") .setThreshold("0.15") .addGreeting("我在");
WakeupWord mainWord2 = new WakeupWord() .setPinyin("ni hao xiao chi") .setWord("你好小迟") .setThreshold("0.15") .addGreeting("我在");
List<WakeupWord> mainWordList = new ArrayList<>();
mainWordList.add(mainWord);
mainWordList.add(mainWord2);
DDS.getInstance().getAgent().getWakeupEngine().updateMainWakeupWords(mainWordList);
3.17.8 添加/删除指定的快速唤醒词
如果您想通过代码来控制快速唤醒,可以调用下面的接口。
QuickStart词为类似“导航去”、“我想听”等,此类唤醒词只在oneshot模式下生效,作用为在未唤醒状态下语音输入“导航去天安门”,可直接进入对话流程。
quickStart
//添加多条QuickStart词 WakeupWord quickStartWord = new WakeupWord() .setPinyin("dao hang qu") .setWord("导航去") .setThreshold("0.15"); List<WakeupWord> quickStartWordList = new ArrayList<>(); quickStartWordList.add(quickStartWord); DDS.getInstance().getAgent().getWakeupEngine().addQuickStartWords(quickStartWordList); //实时移除一条QuickStart词 WakeupWord quickStartWord = new WakeupWord().setWord("导航去"); DDS.getInstance().getAgent().getWakeupEngine().removeQuickStartWord(quickStartWord); //实时移除多条QuickStart词 WakeupWord quickStartWord = new WakeupWord().setWord("导航去"); List<WakeupWord> quickStartWordList = new ArrayList<>(); quickStartWordList.add(quickStartWord); DDS.getInstance().getAgent().getWakeupEngine().removeQuickStartWords(quickStartWordList); //更新多条QuickStart词的接口,覆盖原有的QuickStart词 WakeupWord quickStartWord = new WakeupWord() .setPinyin("dao hang qu") .setWord("导航去") .setThreshold("0.15"); List<WakeupWord> quickStartWordList = new ArrayList<>(); quickStartWordList.add(quickStartWord); DDS.getInstance().getAgent().getWakeupEngine().updateQuickStartWords(quickStartWordList); //清空QuickStart词 DDS.getInstance().getAgent().getWakeupEngine().clearQuickStartWords();
3.17.9 oneshot开关
如果您想动态更改唤醒模式,可以在需要的时候调用下面的接口。
oneshot
//开启oneshot DDS.getInstance().getAgent().getWakeupEngine().enableOneShot(); //关闭oneshot DDS.getInstance().getAgent().getWakeupEngine().disableOneShot();
3.17.10 设置环麦增强角度
// 如果您想动态指定环麦增强角度,可以在需要的时候调用下面的接口。
DDS.getInstance().getAgent().getWakeupEngine().setWakeupDoa(int doa);
3.17.11 设置车载双麦模式
// 如果您想动态指定车载双麦的驾驶模式,可以在需要的时候调用下面的接口。
// 0:全模式, 1:主驾模式
DDS.getInstance().getAgent().getWakeupEngine().setWakeupMode(int mode);
3.17.12 获取当前唤醒内核的版本号
如果您想获取当前唤醒内核的版本号,可以在需要的时候调用下面的接口。
DDS.getInstance().getAgent().getWakeupEngine().getWakeupVersion();
3.17.13 设置是否允许识别过程中响应唤醒
如果您想设置是否允许识别过程中响应唤醒,可以在需要的时候调用下面的接口。
//enable: true. 允许识别过程中响应唤醒, false. 不允许识别过程中响应唤醒
DDS.getInstance().getAgent().getWakeupEngine().enableWakeupWhenAsr(boolean enable);
3.17.14 设置自定义欢迎语回调
如果您想设置自定义欢迎语,可以在需要的时候调用下面的接口, 该方法是阻塞方法,不建议在该方法内部做耗时操作。
DDS.getInstance().getAgent().getWakeupEngine().setWakeupCallback(WakeupCallback wakeupCallback);
DDS.getInstance().getAgent().getWakeupEngine().setWakeupCallback(new WakeupCallback() {
/**
*
* @param wakeupResult 唤醒状态
* <p>
* wakeupResult.optString("word");// 唤醒词
* <p>
* wakeupResult.optString("type");// 唤醒状态: major: 正常唤醒 command: 命令唤醒 interrupt: 打断唤醒
* <p>
* wakeupResult.optString("gender");// 性别: male / female
* <p>
* wakeupResult.optString("action");// 命令唤醒的动作
* <p>
* @return
*/
@Override
public JSONObject onWakeup(JSONObject wakeupResult) {
JSONObject result = new JSONObject();
try {
result.put("greeting", "你好");
} catch (JSONException e) {
e.printStackTrace();
}
return result;
});
3.17.15 获取主唤醒词列表
获取主唤醒词列表,默认返回WakeupEngine所设置的主唤醒词,如果没有设置过则返回产品配置的主唤醒词。
DDS.getInstance().getAgent().getWakeupEngine().getMainWakeupWords();
3.17.16 设置Beamforming监听器
设置Beamforming监听器, 实时回调Beamforming音频
DDS.getInstance().getAgent().getWakeupEngine().setBfListener(BfListener listener);
3.17.17 设置唤醒模块的模式/低功耗模式
设置唤醒模块的模式(信号处理模块不变,环麦中暂不支持)
// 设置唤醒模块的模式(信号处理不变,环麦中暂不支持)
DDS.getInstance().getAgent().getWakeupEngine().setWakeupSwitch(boolean mode);
// 开启低功耗模式后, 唤醒功能不可用, cpu会降低(此方法已被废弃)
DDS.getInstance().getAgent().getWakeupEngine().setLpSwitch(boolean lpSwitch);
3.17.18 就近唤醒
如果你有使用就近唤醒的需求, 可以参照下面的配置与设置(目前支持线性双麦/线性四麦的就近唤醒, 1.2.12.1-1.2.15.1的版本暂不支持就近唤醒)
1. 设置major参数为true (从1.2.8.1版本开始, 不再需要此配置)
config.addConfig("MAJOR", "true");
2. 设置K_USE_NEAR_WAKEUP为true, 表示使用就近唤醒
config.addConfig(DDSConfig.K_USE_NEAR_WAKEUP, "true");
3. 在设置唤醒词的时候设置major字段
WakeupWord minorWord = new WakeupWord()
.setPinyin("ni hao xiao chi")
.setWord("你好小驰")
.setThreshold("0.25")
.setMajor("1")(从1.2.8.1版本开始, 不再需要此配置)
.addGreeting("小驰回来了");
DDS.getInstance().getAgent().getWakeupEngine().addMainWakeupWord(minorWord);
3.18 数据上传接口
开发者调用此接口来上传一些设备的信息,这些信息可以在本地使用,也可以在对话中获取,作为对话决策的一部分。
数据点
/**
* 更新设备状态,产品级的配置。比如:定位信息,设备硬件状态等
* 更新结果可以通过sys.upload.result消息来获取
*
* @param intent 请求的ContextIntent对象,包括key和value
* 如:ContextIntent intent = new ContextIntent("status","{\"platform\":\"Android\"}");
* updateProductContext(intent);
* 技能里通过$context.system.settings.status.platform$即可获取到"Android"
* @return 请求的ID,用于追踪sys.upload.result
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().updateProductContext(ContextIntent intent);
/**
* 更新技能配置,需要调用ContextIntent.setSkillId设置技能ID
* 更新结果可以通过sys.upload.result消息来获取
*
* @param intent 请求的ContextIntent对象,包括key、value、skillId。
* 如:ContextIntent intent = new ContextIntent("status","{\"platform\":\"Android\"}");
* intent.setSkillId("xxxxxxxxxxxxxxxxx");
* updateSkillContext(intent);
* 该技能里通过$context.skill.settings.status.platform$即可获取到"Android",其他技能则无法使用。
* @return 请求的ID,用于追踪sys.upload.result
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().updateSkillContext(ContextIntent intent);
/**
* 获取产品的配置信息
*
* @param inputKey 配置项名称
* @return 配置项值
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().getProductContext(String inputKey);
/**
* 获取技能的配置信息
*
* @param skillId 技能ID
* @param inputKey 配置项名称
* @return 配置项值
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().getSkillContext(String skillId, String inputKey);
/**
* 更新热词识别接口(请求级别)
* 每次请求都会带上热词词库, 例如: [{"type": "vocab", "name": "sys.联系人", "data":["章大樵"]}]
* 本接口为覆盖式接口,以最新设置为准,如需要清除请求空参数即可
*
* @param phraseHints 需要更新的热词识别列表
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().updatePhraseHints(PhraseHintsIntent... phraseHints);
3.19 获取性别/年龄信息
在初始化DDS SDK的时候加入如下配置:
config.addConfig(DDSConfig.K_USE_GENDER, "true");
config.addConfig(DDSConfig.K_USE_AGE, "true");
然后订阅message:sys.dialog.start
内容为:{"gender":"male","age":"youth","reason":"wakeup.major"}
gender就是性别字段,age就是年龄字段,性别年龄信息只有在主唤醒词唤醒后,才会发出。
3.20 动态更新云端识别模型
/**
* 更新云端识别的模型名字,
* 在调用完该接口后,下一次对话开始时生效,并一直用该模型,除非客户端再调用该接口设置为其他的模型
*
* @param asrModel 云端识别的模型名字,有aihome, airobot等,
* 默认为dui控制台配置的模型资源,
* 如果填null,则表示清除之前本地配置的模型名,之后会使用dui控制台配置的模型资源
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().getASREngine().updateAsrModel("aihome");
/**
* 获取当前使用的云端识别的模型
*
* @return asrModel 当前使用的云端识别的模型, 如果失败会返回null,或者抛出DDSNotInitCompleteException
* @throws DDSNotInitCompleteException 如果DDS没有初始化完成,会抛出exception
*/
DDS.getInstance().getAgent().getASREngine().getAsrModel();
3.21 快捷指令
订阅 sys.dm.inspire 消息,用于接收快捷指令。
DDS.getInstance().getAgent().subscribe(new String[]{..., "sys.dm.inspire", ...}, new MessageObserver() {
@Override
public void onMessage(String message, String data) {
if("sys.dm.inspire".equals(message)) {
try {
JSONObject obj = new JSONObject(data);
JSONArray inspire = obj.getJSONArray("inspire");
...
} catch (JSONException e) {
e.printStackTrace();
} catch (DDSNotInitCompleteException e) {
e.printStackTrace();
}
}
}
});
inspire 即为快捷指令的集合数组,通过解析 inspire 来处理指令。inspire 数据结构如下:
inspire:[
{
speak:{
"type":"text",
"text":"123"
},
widget:{
"type":"text",
...
}
},
{
speak:{
"type":"text",
"text":"抱歉由于设备离线,操作失败,请再试一次"
},
widget:{
"type":"list",
...
}
},
...
]
上述结构中,speak 并不是必须的字段, widget 是必须的。
widget即为需要需要展示出来的控件样式,其中 type 字段代表控件样式的类型,有 text/list/web/image/media...
关于 widget 不同控件样式的不同数据结构,可参考: https://www.duiopen.com/docs/ct_UI 。举例:list 对应这 context.widget.list,以此类推
3.22 全双工模式
3.22.1 模式切换
// 设置dds模式
DDS.getInstance().getAgent().setDuplexMode(Agent.DuplexMode.HALF_DUPLEX);// 半双工,一问一答模式
DDS.getInstance().getAgent().setDuplexMode(Agent.DuplexMode.FULL_DUPLEX);// 全双工模式
注意: 在切换全双工时如需要唤醒还请调用: DDS.getInstance().getAgent().getWakeupEngine().enableWakeup();
// 获取dds模式
DDS.getInstance().getAgent().getDuplexMode();
3.22.2 全双工不支持接口与功能
1. 由于全双工模式的特性不再需要vad来做音频的切割, 所以设置vad前端与后端停顿时间无效 @4.5 识别配置项
2. 由于全双工模式为全程识别状态, 所以开启识别时startListening不可用 @3.13 开启/终止识别
3. 由于全双工模式为全程识别状态, 在模拟半双工下的打断唤醒由识别代替,主唤醒词正常开启下一轮对话
4. 由于全双工模式下暂时没有快捷指令的使用场景, 所以快捷指令在全双工模式下不可用 @3.21 快捷指令
5. 基于全双工模式下性能优化的考虑, 目前在全双工模式下默认禁用vad功能, 如有oneshot需求请添加配置K_USE_VAD_IN_FULLDUPLEX打开vad
3.22.3 全双工下跳过Vad超时检测
// 在全双工模式下, 如果你想跳过Vad的检测直接进入识别状态则可以调用下面的接口
DDS.getInstance().getAgent().getASREngine().killVadTimeoutInFullDuplex();
3.23 对话结果支持内容修改
此接口支持修改对话中的语音播报,修改文本展示等功能
// 此接口由于有死锁的风险, 从1.2.8.1开始废弃, 代替此接口的为setDMTaskCallback
DDS.getInstance().getAgent().setDMCallback(new DMCallback() {
@Override
public JSONObject onDMResult(JSONObject dmResult) {
// 这里可以对dmResult做一些修改
return dmResult;
}
});
// 从1.2.8.1版本开始支持
DDS.getInstance().getAgent().setDMTaskCallback(new DMTaskCallback() {
@Override
public JSONObject onDMTaskResult(JSONObject dmTaskResult, Type type) {
if (type == DMTaskCallback.Type.DM_OUTPUT) {// 处理dm的消息
// 显示
String display = dmTaskResult.optString("display");
// 播报
String nlg = dmTaskResult.optString("nlg");
Log.d(TAG, "display = " + display);
Log.d(TAG, "nlg = " + nlg);
try {
dmTaskResult.put("display", "修改之后的显示");
dmTaskResult.put("nlg", "修改之后的播报");
} catch (JSONException e) {
e.printStackTrace();
}
} else if (type == DMTaskCallback.Type.CDM_ERROR) {// // 处理对话异常的消息
// 播报
String nlg = dmTaskResult.optString("nlg");
Log.d(TAG, "nlg = " + nlg);
try {
dmTaskResult.put("nlg", "修改之后的播报");
} catch (JSONException e) {
e.printStackTrace();
}
}
return dmTaskResult;
}
});
3.24 声纹
3.24.1 声纹接口设置
// 注册声纹监听器
VprintEngine.getInstance().setVprintListener(new VprintListener() {
@Override
public void onState(String state) {
Log.e(TAG, "onState = " + state);
}
@Override
public void onResults(String result) {
Log.e(TAG, "onResults = " + result);
}
@Override
public void onError(String error) {
Log.e(TAG, "onError = " + error);
}
});
// 注册声纹
VprintIntent intent = new VprintIntent.Builder()
.setAction(VprintIntent.Action.REGISTER)
.setTrainNum(3)
.setOutChannelNum(2)
.setSnrThresh(8.67f)
.setUserId("userId")
.setVprintWord("ni hao xiao chi")
.create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 更新声纹
VprintIntent intent = new VprintIntent.Builder()
.setAction(VprintIntent.Action.UPDATE)
.setTrainNum(3)
.setOutChannelNum(2)
.setSnrThresh(8.67f)
.setUserId("userId")
.setVprintWord("ni hao xiao chi")
.create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 追加声纹
VprintIntent intent = new VprintIntent.Builder()
.setAction(VprintIntent.Action.APPEND)
.setTrainNum(3)
.setOutChannelNum(2)
.setSnrThresh(8.67f)
.setUserId("userId")
.setVprintWord("ni hao xiao chi")
.create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 删除一条声纹
VprintIntent intent = new VprintIntent.Builder()
.setAction(VprintIntent.Action.UNREGISTER)
.setTrainNum(3)
.setOutChannelNum(2)
.setUserId("userId")
.setVprintWord("ni hao xiao chi")
.create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 删除所有声纹
VprintIntent intent = new VprintIntent.Builder()
.setAction(VprintIntent.Action.UNREGISTER_ALL)
.create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 使用声纹
VprintIntent intent = new VprintIntent.Builder()
.setAction(VprintIntent.Action.TEST)
.setOutChannelNum(2)
.create();
DDS.getInstance().getAgent().getVprintEngine().start(intent);
// 获取声纹模型
String result = VprintEngine.getInstance().getMode();
// 停止使用声纹
VprintEngine.getInstance().stop();
四、高级配置项
4.1 资源更新配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DSConfig.K_CUSTOM_ZIP | 文件名字符串 | 预置在指定目录下的DUI产品配置资源包名 (参考提前预置资源包 ) | N/A |
DDSConfig.K_DUICORE_ZIP | 文件名字符串 | 预置在指定目录下的DUI内核资源包名(参考提前预置资源包) | N/A |
DDSConfig.K_USE_UPDATE_DUICORE | true/false | 设置为false可以关闭dui内核的热更新功能,可以配合内置dui内核资源使用 | true |
DDSConfig.K_USE_UPDATE_NOTIFICATION | true/false | 是否使用内置的资源更新通知栏 | true |
4.2 录音配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_RECORDER_MODE | external/internal | 录音机模式: external(使用外置录音机,需主动调用拾音接口) internal(使用内置录音机AudioRecord,DDS自动录音) |
internal |
DDSConfig.K_AEC_MODE | external | AEC模式:external(DDS会认为宿主设备已经完成了AEC回声消除,选择默认模组也可以支持唤醒打断) | N/A |
DDSConfig.K_AUDIO_SOURCE | AudioSource的取值 | 内置录音机数据源类型 | AudioSource.DEFAULT |
DDSConfig.K_IS_REVERSE_AUDIO_CHANNEL | true/false | 是否反转内置录音机通道 | false |
DDSConfig.K_AUDIO_BUFFER_SIZE | 数值型字符串 | 内置录音机读buffer的大小 | 通道数 * 16/8 * 16000 * 100/1000 B |
4.3 TTS配置项
参数名 | 取值 | 说明 | 默认值 | 备注 |
---|---|---|---|---|
DDSConfig.K_TTS_MODE | external/internal | TTS模式: external(使用外置TTS引擎,需主动注册TTS请求监听器) internal(使用内置DUI TTS引擎) |
internal | |
DDSConfig.K_STREAM_TYPE | AudioManager.STREAM_*的取值 | 内置播放器的STREAM类型 | AudioManager.STREAM_ALARM | K_AUDIO_USAGE与K_CONTENT_TYPE为7.0以后新版本参数, 同时设置时替换原先的K_STREAM_TYPE参数 |
DDSConfig.K_AUDIO_USAGE | AudioAttributes.USAGE_*的取值 | 内置播放器的USAGE类型,兼容7.0以后的新版本参数 | 无 | |
DDSConfig.K_CONTENT_TYPE | AudioAttributes.CONTENT_TYPE_*的取值 | 内置播放器的contenttype类型,兼容7.0以后的新版本参数 | 无 | |
DDSConfig.K_CUSTOM_TIPS | json字符串 | 指定对话错误码的TTS播报。若未指定,则使用产品配置。 { "71304":"这是识别结果为空的自定义播报", "71305":"这是语义结果为空的自定义播报", "71308":"这是进入闲聊技能的自定义播报", "713**":"*****" } |
产品配置 | |
DDSConfig.K_CUSTOM_AUDIO | JSONArray字符串 | 用预置音频来代替指定的TTS播报。 [ { "name":"我在", "type":"wav", "path":"/sdcard/x.pcm" }, { "name":"好的,再见", "type":"mp3", "path":"/sdcard/y.mp3" } ] |
无 | |
DDSConfig.K_TTS_OPTIMIZATION | true/false | 是否TTS开启内存优化 | false |
4.4 唤醒配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_WAKEUP_ROUTER | partner/dialog | 唤醒路由: partner(唤醒后不会主动进入对话,开发者可以通过注册sys.wakeup.result来接收唤醒消息) dialog(唤醒后主动进入对话) |
dialog |
DDSConfig.K_WAKEUP_BIN | 唤醒资源的磁盘绝对路径,比如/sdcard/wakeup.bin | 商务定制版唤醒资源的路径。如果开发者对唤醒率有更高的要求,请联系商务申请定制唤醒资源。 | 内置通用唤醒资源 |
DDSConfig.K_ONESHOT_MIDTIME DDSConfig.K_ONESHOT_ENDTIME |
数值型字符串,毫秒 |
OneShot配置: 5.若MIDTIME=-1&ENDTIME=-1, 唤醒后进入识别; 若第一次识别结果为空, 则再次进入识别 |
500,2000 |
DDSConfig.K_NR_ENABLE | true/false | 是否开启降噪功能 | false |
DDSConfig.K_NR_BIN | 降噪库的磁盘绝对路径,比如/sdcard/nr.bin | 商务定制版降噪资源的路径 | 内置能用降噪资源 |
DDSConfig.K_HIGH_VOLUME_CHECK | true/false | 是否开启大音量检测 如果配置为true,则调用:WakeupWord.setThreshold(String threshold, String threshold2) 设置唤醒词阈值 |
false |
DDSConfig.K_USE_AGE | true/false | 是否开启使用年龄识别 | false |
DDSConfig.K_USE_GENDER | true/false | 是否开启使用性别识别 | false |
DDSConfig. K_USE_NEAR_WAKEUP | true/false | 是否开启就近唤醒 | false |
DDSConfig. K_WAKEUP_DISABLE_CUSTOM_GREETING |
true/false |
是否禁止自定义欢迎语功能 |
false |
4.5 识别配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_ASR_ROUTER | partner/dialog | 识别路由: partner(将识别结果传递给partner,不会主动进入对话) dialog(将识别结果传递给dui,会主动进入对话) |
dialog |
DDSConfig.K_ASR_ENABLE_PUNCTUATION | true/false | 识别结果是否带标点符号 | false |
DDSConfig.K_ASR_ENABLE_TONE | true/false | 识别结果的拼音是否带音调 | false |
DDSConfig.K_VAD_TIMEOUT | 数值型字符串,毫秒 | VAD静音检测超时时间,默认8000毫秒 | 8000 |
DDSConfig.K_VAD_BIN | VAD资源的磁盘绝对路径,比如/sdcard/vad.bin | 商务定制版VAD资源的路径。如果开发者对VAD有更高的要求,请联系商务申请定制VAD资源。 | 内置通用VAD资源 |
DDSConfig.K_ASR_TIPS | true/false | 识别完成是否播报提示音 | false |
DDSConfig.K_ASR_ENABLE_NUMBER_CONVERT | true/false | 中文数据转阿拉伯数字 | false |
DDSConfig.K_ASR_NOT_DROP_WAKEUP | true/false | 识别时不要过滤唤醒词 | false |
注: DDSConfig.K_ASR_ENABLE_PUNCTUATION 开关同时控制识别和语义,开启后,语义解析结果也会带标点符号,且不建议在oneshot、中英文连用、轻音的情况下使用。
4.6 麦克风阵列配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_MIC_TYPE | 0、1、2、3、4、5、6、7、8 |
设置硬件采集模组的类型 7:新车载双麦(2路音频)-- 替换原有车载双麦方案 8:线性六麦(6路音频) |
线上的采集模组配置 |
DDSConfig.K_MIC_ARRAY_AEC_CFG | 麦克风阵列aec资源的磁盘绝对路径,比如/data/aec.bin | 麦克风阵列aec资源的磁盘绝对路径 1. 麦克风阵列的AEC默认做在ROM里。若需SDK做AEC,请配置此项。 2.需要开发者确保在这个路径下这个资源存在。 3.需要开发者在外部实现录音机(参考K_RECORDER_MODE)。 |
无 |
DDSConfig.K_MIC_ARRAY_BEAMFORMING_CFG | 麦克风阵列beamforming资源的磁盘绝对路径,比如/data/beamforming.bin | 麦克风阵列beamforming资源的磁盘绝对路径 1.需要开发者确保在这个路径下这个资源存在。 2.默认的双麦/四麦/六麦内置资源为35mm/35mm/72mm。 |
内置资源 |
DDSConfig.K_WAKEUP_BIN | 麦克风阵列wakeup配置资源的磁盘绝对路径,比如/data/wakeup_cfg.bin | 麦克风阵列wakeup配置资源的磁盘绝对路径 1.需要开发者确保在这个路径下这个资源存在 |
内置资源 |
4.7 调试配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_ASR_DEBUG | true|false | 将会自动保存ASR音频 | 无 |
DDSConfig.K_CACHE_PATH | 调试信息保存路径,比如/sdcard/... | 调试信息保存路径 | AppCacheDir(/sdcard/Android/data/com.xxx.xxx/cache/) |
DDSConfig.K_TTS_DEBUG | true|false | 将会自动保存TTS音频 | 无 |
DDSConfig.K_VAD_DEBUG | true|false | 将会自动保存VAD音频 | 无 |
DDSConfig.K_WAKEUP_DEBUG | true|false | 将会自动保存唤醒音频 | 无 |
4.8 性别识别配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_USE_GENDER | true/false | 是否使用性别识别 | false |
4.9 全双工配置项
参数名 | 取值 | 说明 | 默认值 |
---|---|---|---|
DDSConfig.K_DUPLEX_MODE | HALF_DUPLEX|FULL_DUPLEX |
配置当前的使用模式 HALF_DUPLEX:对话模式 FULL_DUPLEX:全双工模式 |
HALF_DUPLEX |
DDSConfig.K_USE_VAD_IN_FULLDUPLEX | true/false | 全双工中是否使用vad功能 | false |
4.10 声纹配置项
参数名 | 取值 | 说明 | 默认值 |
DDSConfig.K_VPRINT_ENABLE | true/false | 是否开启声纹功能 | false |
DDSConfig.K_VPRINT_BIN | 声纹资源的磁盘绝对路径,比如/data/vprint.bin | 声纹资源的磁盘绝对路径 | 内置资源 |
DDSConfig.K_USE_VPRINT_IN_WAKEUP | true/false | 是否开启声纹功能并在唤醒中使用声纹判断 | false |
五. 错误码描述
error id | 错误描述 | 原因及解决办法 |
---|---|---|
1 | 解压dds.bin失败 | 系统IO错误 |
2 | 内核执行出错 | 请检查配置是否正确,或者联系DUI客服 |
3 | 系统启动超时 | 请检查配置是否正确,或者联系DUI客服 |
4 | 存储空间不足 | 请检查/data/目录剩余大小是否充足 |
070302 | 解码失败 | 联系DUI客服 |
070303 | 未发现新的版本 | 略 |
070304 | 请先升级您的客户端(SDK) | 因为产品选择的dui内核和sdk不匹配,需要升级sdk |
070305 | 网络异常, 无法连接至服务器 | 请检查网络是否正常或者配置是否正确 |
070306 | 解码失败 | 联系DUI客服 |
070307 | 补丁安装失败 | 存储空间不够 |
070308 | 备份压缩文件不存在 | 用户手动删掉了app私有空间的文件 |
070309 | 提取压缩文件失败 | 存储空间不够 |
070310 | 未设置产品ID | 需要设置产品id |
070311 | 无效客户端版本 | 请检查配置是否正确 |
070312 | 无效用户ID | 需要设置用户id |
070313 | 无效设备ID | 设备id不正确 |
070314 | 资源地址无效 | 请检查配置是否正确 |
070315 | 无效的产品分支 | 需要设置产品分支 |
070316 | 无法找到资源 | 服务端资源生成有问题,请尝试重新发布一下,或者请提供产品id反馈给DUI客服,去后台查询根本原因 |
070317 | 资源校验失败 | 下载资源过程中资源被纂改 |
070319 | 当前产品中内核资源版本过低,请前往DUI控制台对应的产品中,选择最新的内核资源版本并重新发布产品 | 当前产品中内核资源版本过低,请前往DUI控制台对应的产品中,选择最新的内核资源版本并重新发布产品。 |
070320 | 存储空间不足 | 系统存储空间不足,请在错误的详细信息中查看需要的存储空间和现有的存储空间 |
070601 | 设备注册过程中无法连接到授权服务器 | 请检查网络是否畅通,或者productId与api key是否匹配 |
070602 | 设备注册过程无法颁发有效的profile文件 | 请检查产品ID或与客服联系 |
070603 | API Key无效 | 请到产品授权配置页面查看api key信息是否正确,请确认签名证书是否匹配,包名是否匹配 |
070604 | 无效的产品ID | 无效的产品ID,请确认是否未设置产品ID |
070606 | profile文件被禁用 | 请重新进行注册或者与客服联系 |
070607 | profile文件过期 | 请重新进行注册或者与客服联系 |
070609 | 设备注册无法保存有效的profile文件 | 检查文件系统是否异常或者重新进行设备注册 |
070612 | dns resolve failed: no answers(DNS失败) | 请检查网络是否畅通 |
070613 | dns resolve failed: exceed retry count(DNS失败) | 请检查网络是否畅通 |
070614 | dns resolve failed: network is unreachable(DNS失败) | 请检查网络是否畅通 |
070615 | dns resolve timeout(DNS超时) | 请检查网络是否畅通 |
070616 | connect ip failed: reasons for uncertainty(建立连接失败) | 请检查网络是否畅通 |
070617 | connect ip failed: network is unreachable(建立连接失败) | 请检查网络是否畅通 |
070618 | connect ip timeout(建立连接超时) | 请检查网络是否畅通 |
070619 | websocket handshake failed: reasons for uncertainty(websocket握手失败) | 请检查网络是否畅通 |
070620 | recv timeout(接收超时) | 请检查网络是否畅通 |
070621 | send timeout(发送超时) | 请检查网络是否畅通 |
070622 | orderly shutdown(发完数据正常关闭) | 请检查网络是否畅通 |
071301 | TTS合成超时 | 请检查网络是否正常 |
071302 | 对话超时 | 请检查网络是否正常 |
071303 | 对话连接断开 | 请检查网络是否正常 |
071304 | 识别结果为空 | 未检测到用户说法 |
071305 | 语义结果为空 | 用户的说法没有命中产品中的非闲聊技能 |
071306 | WebAPI错误 | 调用WebAPI时发生错误 |
071307 | NativeAPI错误 | 调用NativeAPI时发生错误 |
071308 | 进入闲聊技能 | 用户的首轮说法没有命中产品中的非闲聊技能 |
071309 | 异常重试达到最大次数 | 达到了产品错误处理的最大重试次数 |
071310 | 命中退出词 | 用户说了产品的退出词 |
071311 | NativeAPI未注册 | 请检测是否注册并实现NativeAPI |
071312 | 本地识别结果置信度低 | 网络离线时本地识别结果置信度较低 |
071313 | 自定义技能响应超时 | 联系技能开发者 |
071314 | 自定义技能内部错误 | 联系技能开发者 |
071315 | 自定义技能返回为空 | 联系技能开发者 |
071316 | 当前场景下不支持这么说 | 该技能关闭了智能调度 |
071317 | 进入兜底技能 | 用户说法进入了产品中的兜底技能 |
071318 | 进入知识型技能 | 用户说法进入了产品中的知识型技能,包括新闲聊、新百科 |
071319 | 未授权 | 请调用doAuth |
071320 | 在使用oauth授权方式的情况下,access token过期或者不合法 | 请使用oauth sdk刷新access token,然后用dds sdk的接口传入access token |
071321 | 自定义技能speaklist播报超时 | 请检查音频链接是否正常 |
071322 | 鉴权失败的情况下请求对话 | 请检查授权错误信息 |
071300 | 对话服务内部错误 | 联系DUI客服 |
072101 | ASREngine VAD超时 | 超过8s未检测到人声 |
072102 | ASREngine 识别为空 | 未检测到用户说法 |
072103 | ASREngine 识别服务超时 | 请检查网络是否正常 |
072104 | ASREngine 识别过程发生错误 | 联系DUI客服 |
072201 | 唤醒词个数超过限制 | 请清除之前的唤醒词后重试 |
六. 常见问题
6.1 SDK的软硬件配置要求
1)需要Android 4.0及其以上的系统;
2)/data分区剩余空间至少200MB。
6.2 授权失败
关于070603授权错误的问题,请做以下检查:
1)平台上生成的apikey和本地使用的apikey是否一致;
2)平台上release debug的sha256值是否和本地的对应;
3)gradle文件配置的signingConfigs,只针对generate生成的apk;
4)如果是点run运行的程序,debug的sha256要填的.android目录下的debug.keystore(最常见)。
6.3 客户端没收到Command/NativeAPI回调
常见原因如下,可以自上而下确认:
1)技能修改后,未发布;
2)技能发布后,产品没有选择该技能的最新版本;
3)产品未发布;
4)客户端配置的K_ALIAS_KEY和产品发布的分支不一致;
5)客户端没有注册对应的Command/NativeAPI;
6)客户端注册Command/NativeAPI的逻辑没走到;
7)客户端注册的Command/NativeAPI没填对,把?后面的参数也填进去了;
8)客户端注册Command/NativeAPI后,又重新初始化了DDS(release+init)。
6.4 智能家居refreshToken 断网2年后导致SDK授权失败且无法恢复的问题
1)通过订阅token_refresh.fail消息,如果token刷新失败,SDK会抛出这个消息,应用收到该消息后,重新走以下流程:requestAuthCode() -- setAuthCode()
2)setAuthCode授权成功后,将智能家居绑定流程再重新走一遍;确保DCA绑定成功。