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
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授