1. 程式人生 > >android 科大訊飛離線命令詞的使用

android 科大訊飛離線命令詞的使用

這篇部落格主要講解如何實現離線命令詞的功能

      科大訊飛離線命令詞這個功能還是比較好用的 , 它可以配合著語音喚醒一起使用,這個時候就可以做出來你想要的效果 ,如智慧音響什麼的 !  不多說, 直接上程式碼!

     整合SDK可以參考官方文件來整合 , 我這邊主要講解一下如何實現和如何編寫BNF檔案!

   經過我二次封裝可以直接呼叫

   程式碼如下:

public class IflyGrammar {
    private final static String mTag = "IflyGrammar";
    private Context mContext;
    private 
HashMap<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>:開啟|傳送;
以上就是命令詞的程式碼實現 , 有什麼不懂可以在底下評論,留言!