android 科大訊飛離線命令詞的使用
阿新 • • 發佈:2019-02-03
這篇部落格主要講解如何實現離線命令詞的功能
科大訊飛離線命令詞這個功能還是比較好用的 , 它可以配合著語音喚醒一起使用,這個時候就可以做出來你想要的效果 ,如智慧音響什麼的 ! 不多說, 直接上程式碼!
整合SDK可以參考官方文件來整合 , 我這邊主要講解一下如何實現和如何編寫BNF檔案!
經過我二次封裝可以直接呼叫
程式碼如下:
public class IflyGrammar { private final static String mTag = "IflyGrammar"; private Context mContext; privateHashMap<String, String> mTszjNames; // 語音識別物件 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 "<open>": 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 <contact>;//這個是槽,你要加東西的話也是先建立槽然後在底下寫上對應的 !slot <open>; !slot <location>; !slot <notes>; !slot <flish>; !slot <delete>; !slot <map>; !start <locationStart>; <locationStart>:[<open>]<notes>;//這裡是命令的拼接,中括號裡面的是指令 ,後面跟著的是口令! <contact>:張海洋|李四|王五; <open>:開啟|傳送;以上就是命令詞的程式碼實現 , 有什麼不懂可以在底下評論,留言!