Android SDK

一. 离线ASR概述

DUI Lite SDK离线识别可使在无网的情况下,提供将声音信息转化为文字信息的能力。

二. SDK使用说明

 

 2.1.  在 思必驰开放平台 注册账号成为开发者;

 2.2.   接入对应的单项技术

 2.3. 权限声明

如果资源放在sdcard中,需要申请读写权限

<!-- 文件读写需要用到此权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- 授权需要 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 保存文件需要用到此权限 -->

targetSdkVersion 版本高于30,需要增加权限

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
 
if (Build.VERSION.SDK_INT >= 30) {
    if (!Environment.isExternalStorageManager()) {
        Intent intent = new Intent("android.settings.MANAGE_ALL_FILES_ACCESS_PERMISSION");
        startActivity(intent);
    }
}

 2.4. 混淆

DuiLite SDK混淆文件

注意:

使用当前功能时,请先授权,否则禁止使用。请参考 授权说明

三. 集成DUI Lite SDK 包括 jar、JavaDoc 、so 动态库以及功能对应的资源。

DUI Lite SDK 支持 Android 4.0及以上系统,so 动态库目前支持 arm64-v8a, armeabi, armeabi-v7a, x86, x86_64,若需支持其它架构,请提工单申请。

3.1.引入对应的jar 包 , DUI-lite-SDK-for-Android-xxx.jar

3.2.引入对应的 libasr.so 库

四. 工作流程

五. 功能使用

AILocalASRConfig config = new AILocalASRConfig();
 
config.setAcousticResources(SampleConstants.EBNFR_RES);//设置声学资源
config.setNetbinResource(NET_BIN_PATH);//设置网络资源
config.setVadEnable(true);//设置是否启用vad,默认为true
config.setVadResource(SampleConstants.VAD_RES);//设置本地vad资源
 
mAsrEngine = AILocalASREngine.createInstance();
 
mAsrEngine.init(config, new AIASRListenerImpl());//初始化本地识别引擎

5.1初始化参数说明

详细参考AILocalASRConfig

参数名
取值
说明
是否必须
默认值
setAcousticResources(String acousticResources)

设置声学资源

1. 如在 sd 里设置为绝对路径 如/sdcard/speech/ebnfr.aicar.1.3.0.bin
2. 如在 assets 里设置为名称,如:ebnfr.aicar.1.3.0.bin

必须
setAggregateMateBinPath(String aggregateMateBinPath) 集内匹配资源路径

示例:res/itn/res_v1.1.4/command/cmd.bin

可选
setAggregateMateCommandBinPath(String aggregateMateCommandBinPath) 集内匹配资源路径

集内匹配资源路径,command.bin

可选
setEnableDoubleVad(boolean enableDoubleVad) 设置离线识别引擎是否使用双VAD

使用双VAD 需要 feed 2通道音频,而使用非双VAD 则 feed 1 通道的音频。

true 使用双VAD , false 非双VAD

可选 false

setItnLuaResFolderName(String itnLuaResFolderName) 设置itn功能的lua目录路径   可选
setItnUpperCase(boolean itnUpperCase) 设置是否开启英文首字母转换大写   可选 true
setLanguages(Languages languages) 语言   可选
setNetbinResource(String netbinResource) 设置网络资源

1. 如在 sd 里设置为绝对路径 如/sdcard/speech/***.bin
2. 如在 assets 里设置为名称

可选
setNgramSlotRes(String ngramSlotRes)

设置ngram编译资源

设置ngram编译需要的资源名,可设置 assets 下的相对路径 或 / 开头的绝对路径
须在init之前设置才生效

可选
setUseAggregateMate(boolean useAggregateMate) 是否启用集内匹配   可选 false
setVadEnable(boolean vadEnable) 设置是否启用vad true:使用Vad;false:禁止Vad 可选 true
setVadResource(String vadResource) 设置本地vad资源

1. 如在 sd 里设置为绝对路径 如/sdcard/speech/***.bin
2. 如在 assets 里设置为名称

可选

5.2开始

AILocalASRIntent aiLocalASRIntent = new AILocalASRIntent();
 
aiLocalASRIntent.setPauseTime(500);
aiLocalASRIntent.setUseConf(true);//识别结果返回阈值
aiLocalASRIntent.setUsePinyin(true);//识别结果返回拼音
aiLocalASRIntent.setUseXbnfRec(true);//识别结果返回语义信息
aiLocalASRIntent.setMode(ASRMode.MODE_ASR_X);
// 实时反馈会多几个中间结果,最终的识别结果和不开实时反馈是一样的
// 中间结果示例:{"grammar":{"rec":"打 开 WIFI","var":0}}:
// aiLocalASRIntent.setUseRealBack(true);//设置开启实时反馈
aiLocalASRIntent.setSaveAudioPath("/sdcard/speech");
aiLocalASRIntent.setNoSpeechTimeOut(0);
// aiLocalASRIntent.setMaxSpeechTimeS(0)
// aiLocalASRIntent.setThreshToUploadServer(1f); // 音频上传大数据的阈值,达不到阈值就可以上传。默认1,全部上传
// 更新热词,res资源(setResBin)必须需要使用 ebnfr.dymc.1.0.3.bin,否则会崩溃
/*ArrayList dynamicList = new ArrayList<String>();
dynamicList.add("北京市");
dynamicList.add("天安门博物馆");
aiLocalASRIntent.setDynamicList(dynamicList);
aiLocalASRIntent.setBlackWords(new String[]{"第十一个"});*/
 
mAsrEngine.start(aiLocalASRIntent);

详细参数说明AILocalASRIntent

参数名
取值
说明
是否必须
默认值
enableInterimResult(boolean enable) true 启用,默认为false 设置是否开启识别中间结果  
setActiveDecoders(List<String> activeDecoderList) 解码网络名称列表

激活解码网络
注意:如果unregister后,必须更新此列表,否则 start会失败

 
setBlackWords(String blackWords) 热词黑名单 热词黑名单  
setBlackWords(String[] blackWords) 黑名单词表 设置热词黑名单  
setCustomThreshold(Map<String, Double> customThreshold) 自定义词和阈值

自定义词和阈值

 
setCustomThreshold(String[] words, Double[] threshold)

words 词表
threshold 阈值

自定义单词置信度阈值    
setDynamicList(List<String> dynamicList) 热词列表字符串 设置识别热词列表字符串,比如:"北京市,YOU ARE RIGHT,BLUCE,tfboys,天安门博物馆"    
setDynamicList(String dynamicList)   识别热词列表字符串,比如:"北京市,YOU ARE RIGHT,BLUCE,tfboys,天安门博物馆"    
setEnglishThreshold(double englishThreshold)   存在英文情况下设置英文置信度(中英文下识别率低,需另外设置置信度)    
setEnv(String env) env json串 env    
setExpandFnPath(String expandFnPath) 文件的绝对路径

ExpandFn 文件路径,用于动态拆分net.bin文件
start 之前传入有效

   
setFespxEngine(IFespxEngine fespxEngine)

fespxEngine 引擎实例
RuntimeException 内部录音机且多麦模式下没设置

设置关联的信号处理引擎AILocalSignalAndWakeupEngine实例,只在使用内部录音机且多麦模式下才需要设置    
setFillerPenaltyScore(float fillerPenaltyScore)        
setIntervalTimeThresh(int intervalTimeThresh)  

设置oneshot功能的唤醒词和命令词之间的时间间隔阈值,单位:毫秒,default is {@value}ms
如果小于该阈值,就认为不是oneshot,如果大于该阈值,就认为是oneshot

   
setIsIgnoreThreshold(boolean isIgnoreThreshold)   设置是否忽略阈值,不管kernel返回的结果是大于还是小于阈值,都将结果返回给上层    
setMaxSpeechTimeS(int maxSpeechTimeS)  

设置音频最大录音时长,达到该值将取消语音引擎并抛出异常
允许的最大录音时长 单位秒,取值范围 1-60秒,默认60秒

   
setMode(ASRMode mode)

/**
* 识别模式,抛出 1|2 路结果(视具体初始化配置的识别资源)
*/
MODE_ASR(1),
/**
* 热词模式,热词 1 路结果
*/
MODE_HOTWORD(2),
/**
* 增强模式,识别+热词 3 路结果(资源必须为 ngram+grammar 的资源,并开启 use_dymc = 1 )
*/
MODE_ASR_X(3);

设置引擎模式   ASRMode#MODE_ASR
setNgramConf(double ngramConf)   设置置信度    
setNoSpeechTimeOut(int noSpeechTimeOut) 超时时长,单位毫秒 设置无语音超时时长,单位毫秒,默认值为5000ms ;如果达到该设置值时,自动停止录音并放弃请求识别内核    
setPauseTime(int pauseTime) 单位:ms,默认300 设置VAD右边界    
setSaveAudioPath(String saveAudioPath) 路径 设置保存的音频路径,最终的音频路径为path + local_asr_+ recordId + ".pcm"    
setThreshold(double threshold)   设置置信度阈值    
setUseConf(boolean useConf) true 启用,默认为true 设置是否开启置信度    
setUseDelimiter(String useDelimiter) 分割符

添加识别结果分割符,如设置 "," 识别结果显示 : "打,开,天,窗"
start 之前设置生效

   
setUseE2EFusion(boolean useE2EFusion) 是否开启融合默认是关闭

开启融合,
并且active_decoder_list需要激活e2e和ngram

   
setUseFiller(boolean useFiller) true 使用Filler,false 不使用(default)

<p>设置是否开启 Filler,用于减少误识别。</p>
例如:asr.xbnf 里有词 “周杰伦的歌”,用户只说了 “周杰伦”。
<ul>
<li>当不使用 Filler 时,会回调 “周杰伦的歌”</li>
<li>当使用 Filler 时,会回调 ""</li>
</ul>
<p>
当使用<b>热词</b>时,Filler 功能一定会打开,开关设置无效
</p>

   
setUseFiller(boolean useFiller, float fillerPenaltyScore)

useFiller true 使用Filler,false 不使用(default)
fillerPenaltyScore 惩罚分数,default is 2.0。使用Filler时这个参数才有效

<p>设置是否开启 Filler,用于减少误识别。</p>
例如:asr.xbnf 里有词 “周杰伦的歌”,用户只说了 “周杰伦”。
<ul>
<li>当不使用 Filler 时,会回调 “周杰伦的歌”</li>
<li>当使用 Filler 时,会回调 ""</li>
</ul>
<p>
当使用<b>热词</b>时,Filler 功能一定会打开,开关设置无效,惩罚分数设置仍然有效
</p>

   
setUseHoldConf(boolean useHoldConf)   设置是否开启ngram置信度   true
setUseOneShot(boolean useOneShot)  

是否使用oneshot功能,default is false <br>
true 使用one shot功能,唤醒后立马起识别 <br>
false 不使用oneshot,合成后启动识别,或只是启动识别

   
setUseOneShot(boolean useOneShot, int intervalTimeThresh)

useOneShot true 使用 oneshot功能,false 不使用
intervalTimeThresh useOneShot 为 true 时才有效,单位:毫秒,默认为600ms。

设置是否使用oneshot功能,以及oneshot功能的唤醒词和命令词之间的时间间隔阈值,
如果小于该阈值,就认为不是oneshot,如果大于该阈值,就认为是oneshot

   
setUseOneshotJson(boolean useOneshotJson)   使用one_shot_json配置    
setUsePinyin(boolean usePinyin)   设置是否开启拼音输出   false
setUseRawRec(boolean useRawRec)        
setUseRealBack(boolean useRealBack)   设置是否开启实时反馈   false
setUseXbnfRec(boolean useXbnfRec)   设置是否启用基于语法的语义识别   false
setVadEnable(Boolean vadEnable)  

设置是否启用本地vad。启用前提是 {@link AILocalASRConfig#isVadEnable()} 为true,否则该参数无效。
此参数可设置本轮start的引擎是否使用vad功能

   
setWakeupWords(String[] wakeupWords) 唤醒词列表 设置唤醒词列表,用于oneshot过滤唤醒词    
setWords(String words) 内核词表 直接按照内核既定格式设置词表如: \"打开副屏,打开今日头条\"    
setWords(String[] words) 词表 设置词表    

 

5.3动态设置参数

详细参数说明AILocalASREngine

参数名
取值
说明
是否必须
默认值
setWakeupWords(String[] wakeupWords) bool

设置唤醒词列表,用于oneshot过滤唤醒词

   
updateDecoder(AIUpdateListener updateListener, Decoder... decoders)

 

     
updateNetBinPath(String netBinPath, AIUpdateListener listener)

listener 更新接口回调 {@link AIUpdateListener}
netBinPath net.bin 资源自定义路径

更新编译 xbnf 后的 netBin    
updateVocab(Vocab vocab, AIUpdateListener updateListener)  

 

   
updateVocabs(AIUpdateListener updateListener, Vocab... vocabs)

updateListener 更新结果回调
vocabs 词库内容

更新单个或者多个词库    

 

六. 示例代码

详细代码参考sample

AILocalASRConfig config = new AILocalASRConfig();
 
config.setAcousticResources(SampleConstants.EBNFR_RES);//设置声学资源
config.setNetbinResource(NET_BIN_PATH);//设置网络资源
config.setVadEnable(true);//设置是否启用vad,默认为true
config.setVadResource(SampleConstants.VAD_RES);//设置本地vad资源
 
mAsrEngine = AILocalASREngine.createInstance();
 
mAsrEngine.init(config, new AIASRListenerImpl());//初始化本地识别引擎
 
 
 
 
AILocalASRIntent aiLocalASRIntent = new AILocalASRIntent();
 
aiLocalASRIntent.setPauseTime(500);
aiLocalASRIntent.setUseConf(true);//识别结果返回阈值
aiLocalASRIntent.setUsePinyin(true);//识别结果返回拼音
aiLocalASRIntent.setUseXbnfRec(true);//识别结果返回语义信息
aiLocalASRIntent.setMode(ASRMode.MODE_ASR_X);
// 实时反馈会多几个中间结果,最终的识别结果和不开实时反馈是一样的
// 中间结果示例:{"grammar":{"rec":"打 开 WIFI","var":0}}:
// aiLocalASRIntent.setUseRealBack(true);//设置开启实时反馈
aiLocalASRIntent.setSaveAudioPath("/sdcard/speech");
aiLocalASRIntent.setNoSpeechTimeOut(0);
// aiLocalASRIntent.setMaxSpeechTimeS(0)
// aiLocalASRIntent.setThreshToUploadServer(1f); // 音频上传大数据的阈值,达不到阈值就可以上传。默认1,全部上传
// 更新热词,res资源(setResBin)必须需要使用 ebnfr.dymc.1.0.3.bin,否则会崩溃
/*ArrayList dynamicList = new ArrayList<String>();
dynamicList.add("北京市");
dynamicList.add("天安门博物馆");
aiLocalASRIntent.setDynamicList(dynamicList);
aiLocalASRIntent.setBlackWords(new String[]{"第十一个"});*/
 
mAsrEngine.start(aiLocalASRIntent);
 
 
/**
 * 识别引擎回调接口,用以接收相关事件
 */
public class AIASRListenerImpl implements AIASRListener {
 
        @Override
        public void onBeginningOfSpeech() {
            showInfo("检测到说话");
 
        }
 
        @Override
        public void onEndOfSpeech() {
            showInfo("检测到语音停止,开始识别...");
        }
 
        @Override
        public void onReadyForSpeech() {
            showInfo("请说话...");
        }
 
        @Override
        public void onResultDataReceived(byte[] buffer, int size, int wakeupType) {
 
        }
 
        @Override
        public void onRmsChanged(float rmsdB) {
            showTip("RmsDB = " + rmsdB);
        }
 
        @Override
        public void onError(AIError error) {
            Log.d(tag, error.toString());
            showTip(error.toString());
            setAsrBtnState(false"识别");
        }
 
        /**
         * <p>
         * AIResult.getResultObject().toString() 是返回的识别结果
         * </p>
         * 中间结果(如果设置开启实时反馈)
         * <pre>
         *  {
         *      "grammar": {
         *          "rec": "打 开 WIFI",
         *          "var": 0
         *       }
         *  }
         * </pre>
         * <p>
         * 最终识别结果
         * <pre>
         *  {
         *      "version": "1.0.12.2020.6.11.11:11:30",
         *      "res": "aicar.1.3.0",
         *      "eof": 1,
         *      "rec": "打 开 WIFI",
         *      "conf": 0.6936,
         *      "pinyin": "da kai WIFI",
         *      "wavetime": 1880,
         *      "prutime": 0,
         *      "systime": 1977,
         *      "rectime": 0,
         *      "sestime": 1977,
         *      "delaytime": 5,
         *      "delayframe": 0,
         *      "net_type": 0,
         *      "post": {
         *          "sem": {}
         *       }
         *  }
         * </pre>
         *
         * @param results 识别结果
         */
        @Override
        public void onResults(AIResult results) {
 
            Log.i(tag, results.getResultObject().toString());
            try {
                showInfo(new JSONObject(results.getResultObject().toString()).toString(4));
            catch (JSONException e) {
                e.printStackTrace();
            }
            setAsrBtnState(true"识别");
        }
 
        @Override
        public void onInit(int status) {
            if (status == 0) {
                Log.i(tag, "end of init asr engine");
                showInfo("识别引擎加载成功");
                setResBtnEnable(true);
                setAsrBtnState(true"识别");
            else {
                showInfo("识别引擎加载失败");
            }
        }
 
        @Override
        public void onNotOneShot() {
            //do nothing
        }
 
        @Override
        public void onResultDataReceived(byte[] buffer, int size) {
            //do nothing
        }
 
        @Override
        public void onRawDataReceived(byte[] buffer, int size) {
            //do nothing
        }
 
    }

更多的接口内容与描述请参阅 javadoc