科大讯飞离线命令词这个功能还是比较好用的 , 它可以配合着语音唤醒一起使用,这个时候就可以做出来你想要的效果 ,如智能音响什么的 ! 不多说, 直接上代码!
集成SDK可以参考官方文档来集成 , 我这边主要讲解一下如何实现和如何编写BNF文件!
经过我二次封装可以直接调用
代码如下:
public class IflyGrammar { private final static String mTag = "IflyGrammar"; private Context mContext; private HashMapmTszjNames; // 语音识别对象 private SpeechRecognizer mAsr; private Toast mToast; // 缓存 private SharedPreferences mSharedPreferences; private String mContent;// 语法、词典临时变量 // 本地语法文件 private String mLocalGrammar = null; // 本地词典 private String mLocalLexicon = null; // 本地语法构建路径 private String grmPath = Environment.getExternalStorageDirectory() .getAbsolutePath() + "/msc/test"; // 返回结果格式,支持:xml,json private String mResultType = "json"; private final String KEY_GRAMMAR_ABNF_ID = "grammar_abnf_id"; private final String GRAMMAR_TYPE_ABNF = "abnf"; private final String GRAMMAR_TYPE_BNF = "bnf"; private String mEngineType = SpeechConstant.TYPE_LOCAL; private int mRet; private VoiceWakeuper mIvw; //初始化监听器 private InitListener mInitListener = new InitListener() { @Override public void onInit(int code) { Log.d(mTag, "SpeechRecognizer init() code = " + code); if (code != ErrorCode.SUCCESS) { showTip("初始化失败,错误码:" + code); } } }; //识别监听器 private RecognizerListener mRecognizerListener = new RecognizerListener() { @Override public void onVolumeChanged(int volume, byte[] data) { // showTip("当前正在说话,音量大小:" + volume); Log.d(mTag, "返回音频数据:" + data.length); } @Override public void onResult(final RecognizerResult result, boolean isLast) { if (null != result && !TextUtils.isEmpty(result.getResultString())) { Log.d(mTag, "recognizer result:" + result.getResultString()); String text = ""; if (mResultType.equals("json")) { text = JsonParser.parseGrammarResult(result.getResultString(), mEngineType); GrammarRec grammarRec = JsonUtil.parseJStr2Object(GrammarRec.class, result.getResultString()); if (grammarRec == null) return; switch (grammarRec.getWs().get(0).getSlot()) { //这里面是识别后的回调在这这个里面做操作!,然后用EventBus传出去. case " " : String tt = JsonParser.parseGrammarResult(result.getResultString()); Log.e("走了",tt); if (tt.contains("XXXX")) { String s = "1"; EventBus.getDefault().post(new StartIDActivity(s)); } break; default: break; }
} else if (mResultType.equals("xml")) { text = XmlParser.parseNluResult(result.getResultString()); } // 显示 // ((EditText) findViewById(R.id.isr_text)).setText(text); } else { Log.d(mTag, "recognizer result : null"); } } @Override public void onEndOfSpeech() { // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入 showTip("结束说话"); Global.mIflyGrammer.stopRecognize(); EventBus.getDefault().post(new kaiqi()); Log.e("走了","4444444"); } @Override public void onBeginOfSpeech() { // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入 showTip("开始说话"); } @Override public void onError(SpeechError error) { showTip("onError Code:" + error.getErrorCode()); } @Override public void onEvent(int eventType, int arg1, int arg2, Bundle obj) { // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因 // 若使用本地能力,会话id为null // if (SpeechEvent.EVENT_SESSION_ID == eventType) { // String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID); // Log.d(TAG, "session id =" + sid); // } } }; //构建语法监听器 private GrammarListener mGrammarListener = new GrammarListener() { @Override public void onBuildFinish(String grammarId, SpeechError error) { if (error == null) { if (mEngineType.equals(SpeechConstant.TYPE_CLOUD)) { SharedPreferences.Editor editor = mSharedPreferences.edit(); if (!TextUtils.isEmpty(grammarId)) editor.putString(KEY_GRAMMAR_ABNF_ID, grammarId); editor.commit(); } showTip("语法构建成功:" + grammarId); } else { showTip("语法构建失败,错误码:" + error.getErrorCode()); } } }; //更新词典监听器 private LexiconListener mLexiconListener = new LexiconListener() { @Override public void onLexiconUpdated(String lexiconId, SpeechError error) { if (error == null) { showTip("词典更新成功"); } else { showTip("词典更新失败,错误码:" + error.getErrorCode()); } } }; public IflyGrammar(Context context) { mContext = context; mToast = Toast.makeText(context, "", Toast.LENGTH_SHORT); mAsr = SpeechRecognizer.createRecognizer(mContext, mInitListener); buildGrammar(); initTzsjNames(); updateLexicon(); } //设置参数 public boolean setParam() { boolean result = false; // 清空参数 mAsr.setParameter(SpeechConstant.PARAMS, null); // 设置识别引擎 mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType); // 设置本地识别资源 mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath()); // 设置语法构建路径 mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath); // 设置返回结果格式 mAsr.setParameter(SpeechConstant.RESULT_TYPE, mResultType); // 设置本地识别使用语法id mAsr.setParameter(SpeechConstant.LOCAL_GRAMMAR, "call"); // 设置识别的门限值 mAsr.setParameter(SpeechConstant.MIXED_THRESHOLD, "30"); // 使用8k音频的时候请解开注释 // mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000"); result = true; // 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限 // 注:AUDIO_FORMAT参数语记需要更新版本才能生效 mAsr.setParameter(SpeechConstant.AUDIO_FORMAT, "wav"); mAsr.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/asr.wav"); return result; } //获取识别资源路径 private String getResourcePath() { StringBuffer tempBuffer = new StringBuffer(); //识别通用资源 tempBuffer.append(ResourceUtil.generateResourcePath(mContext, ResourceUtil.RESOURCE_TYPE.assets, "asr/common.jet")); //识别8k资源-使用8k的时候请解开注释 // tempBuffer.append(";"); // tempBuffer.append(ResourceUtil.generateResourcePath(this, RESOURCE_TYPE.assets, "asr/common_8k.jet")); return tempBuffer.toString(); } private void showTip(final String str) { Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show(); } //构建语法 private void buildGrammar() { // 初始化语法、命令词 mLocalLexicon = "张海羊\n刘婧\n王锋\n"; mLocalGrammar = FucUtil.readFile(mContext, "call.bnf", "utf-8"); mContent = new String(mLocalGrammar); mAsr.setParameter(SpeechConstant.PARAMS, null); // 设置文本编码格式 mAsr.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8"); // 设置引擎类型 mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType); // 设置语法构建路径 mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath); //使用8k音频的时候请解开注释 // mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000"); // 设置资源路径 mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath()); mRet = mAsr.buildGrammar(GRAMMAR_TYPE_BNF, mContent, mGrammarListener); if (mRet != ErrorCode.SUCCESS) { showTip("语法构建失败,错误码:" + mRet); } } private void initTzsjNames() { mTszjNames = new HashMap<>(); Iterator iterator = Global.mPersons.entrySet().iterator(); mLocalLexicon = ""; while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); Person person = (Person) entry.getValue(); mTszjNames.put(person.mName, person.mID); mLocalLexicon += person.mName + "\n"; } } //本地-更新词典 private void updateLexicon() { mContent = new String(mLocalLexicon); mAsr.setParameter(SpeechConstant.PARAMS, null); // 设置引擎类型 mAsr.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL); // 设置资源路径 mAsr.setParameter(ResourceUtil.ASR_RES_PATH, getResourcePath()); //使用8k音频的时候请解开注释 // mAsr.setParameter(SpeechConstant.SAMPLE_RATE, "8000"); // 设置语法构建路径 mAsr.setParameter(ResourceUtil.GRM_BUILD_PATH, grmPath); // 设置语法名称 mAsr.setParameter(SpeechConstant.GRAMMAR_LIST, "call"); // 设置文本编码格式 mAsr.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8"); mRet = mAsr.updateLexicon("contact", mContent, mLexiconListener); if (mRet != ErrorCode.SUCCESS) { showTip("更新词典失败,错误码:" + mRet); } } //开始识别 public void startRecognize() { // 设置参数 if (!setParam()) { showTip("请先构建语法。"); return; } mRet = mAsr.startListening(mRecognizerListener); if (mRet != ErrorCode.SUCCESS) { showTip("识别失败,错误码: " + mRet); } } //停止识别 public void stopRecognize() { mAsr.stopListening(); showTip("停止识别"); } //取消识别 public void cancelRecognize() { mAsr.cancel(); showTip("取消识别"); } //反初始化 public void unInit() { if (null != mAsr) { // 退出时释放连接 mAsr.cancel(); mAsr.destroy(); } } }
以上就是命令词的代码可以直接复制使用 , 主要识别之后的操作我这边是用EvntBus传到相应的界面进行操作的!
然后现在教如何编写BNF文件:代码如下
#BNF+IAT 1.0 UTF-8; !grammar call; !slot以上就是命令词的代码实现 , 有什么不懂可以在底下评论,留言!;//这个是槽,你要加东西的话也是先创建槽然后在底下写上对应的 !slot ; !slot ; !slot ; !slot ; !slot ; !slot