1. 程式人生 > >Android整合訊飛語音、百度語音、阿里語音識別

Android整合訊飛語音、百度語音、阿里語音識別

一、引言

demo下載地址:https://fir.im/jy28
demo原始碼檢視:https://github.com/wapchief/android-CollectionDemo
效果圖:

選這幾個平臺的主要也是從多方面考慮。
大概從這幾個

  • 識別精準度
  • 免費限制
  • 穩定程度
  • 包體積
  • 拓展性

目前只有百度的語音服務支援長語音(60秒以上),和離線語音識別。
當然語音的庫(.so)檔案也是最大的。足足10多M。

二、申請應用

在整合之前,需要去相應的平臺去申請應用。
拿到key等金鑰。目前這幾個平臺都在測試免費層限制中。

百度是完全免費,訊飛有免費層日呼叫次數限制。

三、整合

首先去各大平臺下載對於的語音檔案庫
一般都包含.so和libs兩部分。這兩部分都需要加入到專案中。

不過這裡只需要注意一點是,每個平臺的文件不一樣,有些是使用libs整合第三方庫,有些是使用jnilibs載入。

如果都按照第三方文件來整合,必定會出錯。
這裡統一使用jniLibs來整合(只適用於AndroidStudio)。如果是eclipse,則需要使用libs整合

如果在整合中遇到了問題,可以參考我以前寫過的解決方案
Android關於libs,jniLibs庫的基本使用說明及衝突解決

1、(必須)將下載後的所有so庫檔案(以.so結尾的檔案)拷貝至專案下/app/src/main目錄,如果沒有則建立一個,裡面的名字是固定的,注意不能修改,必須按照這樣的架構目錄整合。

2、(必須)將jar檔案拷貝到libs目錄中

 

image.png

 

然後將jar新增到專案。
可以使用右鍵對應的jar包,add-libs手動新增

3、(必須)在AndroidManifest.xml新增許可權

以訊飛的許可權文件說明為例

<!--連線網路許可權,用於執行雲端語音能力 -->
<uses-permission android:name="android.permission.INTERNET"/>
<!--獲取手機錄音機使用許可權,聽寫、識別、語義理解需要用到此許可權 -->
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<!--讀取網路資訊狀態 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!--獲取當前wifi狀態 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!--允許程式改變網路連線狀態 -->
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<!--讀取手機資訊許可權 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<!--讀取聯絡人許可權,上傳聯絡人需要用到此許可權 -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<!--外儲存寫許可權,構建語法需要用到此許可權 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--外儲存讀許可權,構建語法需要用到此許可權 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!--配置許可權,用來記錄應用配置資訊 -->
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<!--手機定位資訊,用來為語義等功能提供定位,提供更精準的服務-->
<!--定位資訊是敏感資訊,可通過Setting.setLocationEnable(false)關閉定位請求 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!--如需使用人臉識別,還要新增:攝相頭許可權,拍照需要用到 -->
<uses-permission android:name="android.permission.CAMERA" />

如果SDK版本在6.0以上需要在專案中手動獲取錄音許可權


    /*動態許可權申請*/
    private void initPermission() {
        String permission[] = {Manifest.permission.RECORD_AUDIO,
                Manifest.permission.ACCESS_NETWORK_STATE,
                Manifest.permission.INTERNET,
                Manifest.permission.WRITE_EXTERNAL_STORAGE};
        ArrayList<String> applyList = new ArrayList<>();

        for (String per : permission) {
            if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(this, per)) {
                applyList.add(per);
            }
        }

        String tmpList[] = new String[applyList.size()];
        if (!applyList.isEmpty()) {
            ActivityCompat.requestPermissions(this, applyList.toArray(tmpList), 123);
        }
    }

四、初始化服務

各個平臺的初始化方法都不一樣。
但大多數都是在自己專案的Application中初始化。


        //初始化訊飛語音
        SpeechUtility.createUtility(mContext, SpeechConstant.APPID +"=59daecea," + SpeechConstant.FORCE_LOGIN +"=true");
        //訊飛除錯日誌開啟
        Setting.setShowLog(true);
        //初始化阿里語音
        NlsClient.openLog(true);
        NlsClient.configure(mContext);

有些是在AndroidManifest.xml中初始化

       <!--******************************百度語音**********************************-->
        <meta-data android:name="com.baidu.speech.APP_ID"
            android:value="8172882" />
        <meta-data
            android:name="com.baidu.speech.API_KEY"
            android:value="R3crsZhvpqQSrLGUvG7kuG0pCnpTbXvb" />
        <meta-data
            android:name="com.baidu.speech.SECRET_KEY"
            android:value="6MafqZkSLoNYUML1YduHPDYBg1kkPLHj" />

        <service android:name="com.baidu.speech.VoiceRecognitionService" android:exported="false"/>

五、開啟識別服務

以訊飛為例:
在開始識別前需要初始化識別物件,

 SpeechRecognizer  recognizer = SpeechRecognizer.createRecognizer(this, null);

然後配置聽寫引數

    /**
     * 引數設定
     */
    public void setParam() {
        //2.設定聽寫引數,詳見《科大訊飛MSC API手冊(Android)》SpeechConstant類
        recognizer.setParameter(SpeechConstant.DOMAIN, "iat");
        recognizer.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        recognizer.setParameter(SpeechConstant.ACCENT, "mandarin ");
        //設定音訊儲存路徑
        recognizer.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        recognizer.setParameter(SpeechConstant.ASR_AUDIO_PATH, Environment.getExternalStorageDirectory() + "/msc/iat.wav");

    }

開始識別的開始和終止,及識別過程的內容回撥

    //開啟
    private void startXF() {
        setParam();
        recognizer.startListening(recognizerListener);
    }

    //停止
    private void stopXF() {

        recognizer.stopListening();
    }


    /*監聽*/
    private RecognizerListener recognizerListener = new RecognizerListener() {
        @Override
        public void onVolumeChanged(int i, byte[] bytes) {
            //音量變化
        }

        @Override
        public void onBeginOfSpeech() {
            //開始說話
            Log.e(TAG, "XF開始說話");
        }

        @Override
        public void onEndOfSpeech() {
            //結束說話
            Log.e(TAG, "XF結束說話");

        }

        @Override
        public void onResult(RecognizerResult recognizerResult, boolean b) {
            //返回結果需要判斷null
            text = JsonParser.parseIatResult(recognizerResult.getResultString());
            Log.e(TAG, "XFResult:" + text + "\n" + recognizerResult.getResultString());
            mVoiceTv.setText(recognizerResult.getResultString());
            printResult(recognizerResult);
        }

        @Override
        public void onError(SpeechError speechError) {
            //錯誤回撥
            Log.e(TAG, "XFError:" + speechError.toString());

        }

        @Override
        public void onEvent(int i, int i1, int i2, Bundle bundle) {
            //事件拓展
        }
    };

解析語音識別的結果。

    //儲存聽寫結果
    private HashMap<String, String> mIatResults = new LinkedHashMap<String, String>();

 /*解析器*/
    private void printResult(RecognizerResult results) {
        String text = JsonParser.parseIatResult(results.getResultString());

        String sn = null;
        // 讀取json結果中的sn欄位
        try {
            JSONObject resultJson = new JSONObject(results.getResultString());
            sn = resultJson.optString("sn");
        } catch (JSONException e) {
            e.printStackTrace();
        }

        mIatResults.put(sn, text);

        StringBuffer resultBuffer = new StringBuffer();
        for (String key : mIatResults.keySet()) {
            resultBuffer.append(mIatResults.get(key));
        }

        mVoiceEt.setText("訊飛識別結果:" + resultBuffer.toString());
        mVoiceEt.setSelection(mVoiceEt.length());
//        mVoiceTv.setText(resultBuffer.toString());
    }

六、異常及其他

SecurityException異常:
如果是在6.0以上版本的sdk可能會出現該問題,主要是臨時許可權呼叫,比如呼叫系統的錄音檔案播放,或者呼叫系統的相簿。
可以參考呼叫相簿的解決方案,原理一樣
Android版本相機適配問題集合(不斷整理更新中)

demo下載地址:
https://fir.im/jy28
demo原始碼:
https://github.com/wapchief/android-CollectionDemo



作者:八怪不姓醜
連結:https://www.jianshu.com/p/950d73234991
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授