国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android 基于百度語音的語音交互功能(推薦)

2019-12-12 04:40:14
字體:
來源:轉載
供稿:網友

項目里面用到了語音喚醒功能,前面一直在用訊飛的語音識別,本來打算也是直接用訊飛的語音喚醒,但是訊飛的語音喚醒要收費,試用版只有35天有效期。只好改用百度語音,百度語音所有功能免費,功能也比較簡單實用,包括語音識別,語音合成和語音喚醒,正好可以組成一套完整的語音交互功能。

效果圖:

首先是語音喚醒功能,說出關鍵詞即可叫語音識別,喚醒成功會有語音提示,這里采用了百度語音的合成功能。然后百度語音識別會根據wifi情況自動切換在線或者離線識別,但是離線識別只能識別已經導入的關鍵詞,而且離線第一次識別需要聯網,識別成功,同樣會有語音提示。效果圖gif沒有聲音,Toast顯示的時候就是語音提示的內容。

這里說一點,百度語音的demo里給的語音喚醒是在onResume()開始喚醒監聽,喚醒成功后在onPause()里就停止喚醒監聽。而我現在要在喚醒成功后彈出語音識別的UI界面,所以彈出UI的同時就會停止喚醒監聽。如果語音識別成功,UI界面消失,喚醒監聽會重新開始,此時說出喚醒詞即可重新喚醒。但是如果識別失敗,封裝好的UI界面會變成下圖情況,這時候就要手動點擊重試或者取消才可以,不符合全語音交互的理念。為了解決這個情況,要將停止喚醒監聽寫到onStop()里,這樣即使語音識別失敗,也可以重新喚醒。

具體的集成步驟官方文檔里都有,也可以參考下面的文章

//m.survivalescaperooms.com/article/97329.htm

注:我這里語音識別和語音合成都用到了,所以官網下的兩個sdk都要導入到工程里,這里還有個小問題,正常來說,Jar包導入到工程之后,還要將assert和jniLibs文件夾放到工程里,我這里只放了語音識別的assert文件夾,jniLibs文件夾我都沒放入工程里,這樣可以使用。如果我將語音識別和語音合成的assert和jniLibs都放到工程里,反而會報下面的錯誤,不知道為什么。

java.lang.UnsatisfiedLinkError: Native method not found: com.baidu.speech.easr.easrNativeJni.WakeUpFree:()I

MainActivity:

package com.example.administrator.baiduvoicetest;import android.content.Intent;import android.os.Bundle;import android.os.Environment;import android.support.v7.app.AppCompatActivity;import android.text.TextUtils;import android.util.AndroidRuntimeException;import android.util.Log;import android.view.View;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import com.baidu.speech.EventListener;import com.baidu.speech.EventManager;import com.baidu.speech.EventManagerFactory;import com.baidu.tts.auth.AuthInfo;import com.baidu.tts.client.SpeechError;import com.baidu.tts.client.SpeechSynthesizer;import com.baidu.tts.client.SpeechSynthesizerListener;import com.baidu.tts.client.TtsMode;import org.json.JSONException;import org.json.JSONObject;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;public class MainActivity extends AppCompatActivity {private TextView txtResult;private EditText mInput;private EventManager mWpEventManager;private SpeechSynthesizer mSpeechSynthesizer;private String mSampleDirPath;private static final String SAMPLE_DIR_NAME = "baiduTTS";private static final String SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female.dat";private static final String SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male.dat";private static final String TEXT_MODEL_NAME = "bd_etts_text.dat";private static final String LICENSE_FILE_NAME = "temp_license";private static final String ENGLISH_SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female_en.dat";private static final String ENGLISH_SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male_en.dat";private static final String ENGLISH_TEXT_MODEL_NAME = "bd_etts_text_en.dat";private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);txtResult = (TextView) findViewById(R.id.txtResult);txtResult.setText("請說喚醒詞: 小度你好或者百度一下/n/n"+"離在線語法識別(首次使用需要聯網授權)/n"+"語音識別開始后你可以說(可以根據語法自行定義離線說法):/n" +" 1. 打電話給張三(離線)/n" +" 2. 打電話給李四(離線)/n" +" 3. 打開計算器(離線)/n" +" 4. 明天天氣怎么樣(需要聯網)/n" +" ..." +"/n");mInput= (EditText) findViewById(R.id.input);mInput.setVisibility(View.GONE);initialEnv();initialTts();}@Overrideprotected void onResume() {super.onResume();// 喚醒功能打開步驟// 1) 創建喚醒事件管理器mWpEventManager = EventManagerFactory.create(MainActivity.this, "wp");// 2) 注冊喚醒事件監聽器mWpEventManager.registerListener(new EventListener() {@Overridepublic void onEvent(String name, String params, byte[] data, int offset, int length) {Log.d(TAG, String.format("event: name=%s, params=%s", name, params));try {JSONObject json = new JSONObject(params);if ("wp.data".equals(name)) { // 每次喚醒成功, 將會回調name=wp.data的時間, 被激活的喚醒詞在params的word字段String word = json.getString("word");txtResult.append("喚醒成功, 喚醒詞: " + word + "/r/n");mInput.setText("喚醒成功,請說出指令");//mInput.setText("succeed");Toast.makeText(MainActivity.this,mInput.getText(),Toast.LENGTH_LONG).show();speak();//延時3秒,防止語音合成的內容又被語音識別try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}Intent intent = new Intent("com.baidu.action.RECOGNIZE_SPEECH");intent.putExtra("grammar", "asset:///baidu_speech_grammardemo.bsg"); // 設置離線的授權文件(離線模塊需要授權), 該語法可以用自定義語義工具生成, 鏈接http://yuyin.baidu.com/asr#m5//intent.putExtra("slot-data", your slots); // 設置grammar中需要覆蓋的詞條,如聯系人名startActivityForResult(intent, 1);} else if ("wp.exit".equals(name)) {txtResult.append("喚醒已經停止: " + params + "/r/n");}} catch (JSONException e) {throw new AndroidRuntimeException(e);}}});// 3) 通知喚醒管理器, 啟動喚醒功能HashMap params = new HashMap();params.put("kws-file", "assets:///WakeUpDemo.bin"); // 設置喚醒資源, 喚醒資源請到 http://yuyin.baidu.com/wake#m4 來評估和導出mWpEventManager.send("wp.start", new JSONObject(params).toString(), null, 0, 0);}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == RESULT_OK) {Bundle results = data.getExtras();ArrayList<String> results_recognition = results.getStringArrayList("results_recognition");//txtResult.append("識別結果(數組形式): " + results_recognition + "/n");//將數組形式的識別結果變為正常的String類型,例:[給張三打電話]變成給張三打電話String str=results_recognition+"";String res=str.substring(str.indexOf("[")+1,str.indexOf("]"));txtResult.append(res+"/n");mInput.setText("好的,馬上執行"+res);speak();Toast.makeText(MainActivity.this,mInput.getText(),Toast.LENGTH_LONG).show();}}private void initialTts() {this.mSpeechSynthesizer = SpeechSynthesizer.getInstance();this.mSpeechSynthesizer.setContext(this);this.mSpeechSynthesizer.setSpeechSynthesizerListener(new SpeechSynthesizerListener() {@Overridepublic void onSynthesizeStart(String s) {}@Overridepublic void onSynthesizeDataArrived(String s, byte[] bytes, int i) {}@Overridepublic void onSynthesizeFinish(String s) {}@Overridepublic void onSpeechStart(String s) {}@Overridepublic void onSpeechProgressChanged(String s, int i) {}@Overridepublic void onSpeechFinish(String s) {}@Overridepublic void onError(String s, SpeechError speechError) {}});// 文本模型文件路徑 (離線引擎使用)this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/"+ TEXT_MODEL_NAME);// 聲學模型文件路徑 (離線引擎使用)this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/"+ SPEECH_FEMALE_MODEL_NAME);// 本地授權文件路徑,如未設置將使用默認路徑.設置臨時授權文件路徑,LICENCE_FILE_NAME請替換成臨時授權文件的實際路徑,僅在使用臨時license文件時需要進行設置,如果在[應用管理]中開通了正式離線授權,不需要設置該參數,建議將該行代碼刪除(離線引擎)// 如果合成結果出現臨時授權文件將要到期的提示,說明使用了臨時授權文件,請刪除臨時授權即可。this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_LICENCE_FILE, mSampleDirPath + "/"+ LICENSE_FILE_NAME);// 請替換為語音開發者平臺上注冊應用得到的App ID (離線授權)this.mSpeechSynthesizer.setAppId("xxx"/*這里只是為了讓Demo運行使用的APPID,請替換成自己的id。*/);// 請替換為語音開發者平臺注冊應用得到的apikey和secretkey (在線授權)this.mSpeechSynthesizer.setApiKey("xxx","xxx"/*這里只是為了讓Demo正常運行使用APIKey,請替換成自己的APIKey*/);// 發音人(在線引擎),可用參數為0,1,2,3。。。(服務器端會動態增加,各值含義參考文檔,以文檔說明為準。0--普通女聲,1--普通男聲,2--特別男聲,3--情感男聲。。。)this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");// 設置Mix模式的合成策略this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);// 授權檢測接口(只是通過AuthInfo進行檢驗授權是否成功。)// AuthInfo接口用于測試開發者是否成功申請了在線或者離線授權,如果測試授權成功了,可以刪除AuthInfo部分的代碼(該接口首次驗證時比較耗時),不會影響正常使用(合成使用時SDK內部會自動驗證授權)AuthInfo authInfo = this.mSpeechSynthesizer.auth(TtsMode.MIX);if (authInfo.isSuccess()) {Toast.makeText(this,"auth success",Toast.LENGTH_LONG).show();} else {String errorMsg = authInfo.getTtsError().getDetailMessage();Toast.makeText(this,"auth failed errorMsg=" + errorMsg,Toast.LENGTH_LONG).show();}// 初始化ttsmSpeechSynthesizer.initTts(TtsMode.MIX);// 加載離線英文資源(提供離線英文合成功能)int result =mSpeechSynthesizer.loadEnglishModel(mSampleDirPath + "/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath+ "/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME);//Toast.makeText(this,"loadEnglishModel result=" + result,Toast.LENGTH_LONG).show();//打印引擎信息和model基本信息//printEngineInfo();}private void speak() {String text = this.mInput.getText().toString();//需要合成的文本text的長度不能超過1024個GBK字節。if (TextUtils.isEmpty(mInput.getText())) {text = "歡迎使用百度語音合成SDK,百度語音為你提供支持。";mInput.setText(text);}int result = this.mSpeechSynthesizer.speak(text);if (result < 0) {Toast.makeText(this,"error,please look up error code in doc or URL:http://yuyin.baidu.com/docs/tts/122 ",Toast.LENGTH_LONG).show();}}private void initialEnv() {if (mSampleDirPath == null) {String sdcardPath = Environment.getExternalStorageDirectory().toString();mSampleDirPath = sdcardPath + "/" + SAMPLE_DIR_NAME;}makeDir(mSampleDirPath);copyFromAssetsToSdcard(false, SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);copyFromAssetsToSdcard(false, SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_MALE_MODEL_NAME);copyFromAssetsToSdcard(false, TEXT_MODEL_NAME, mSampleDirPath + "/" + TEXT_MODEL_NAME);copyFromAssetsToSdcard(false, LICENSE_FILE_NAME, mSampleDirPath + "/" + LICENSE_FILE_NAME);copyFromAssetsToSdcard(false, "english/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/"+ ENGLISH_SPEECH_FEMALE_MODEL_NAME);copyFromAssetsToSdcard(false, "english/" + ENGLISH_SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/"+ ENGLISH_SPEECH_MALE_MODEL_NAME);copyFromAssetsToSdcard(false, "english/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + "/"+ ENGLISH_TEXT_MODEL_NAME);}private void makeDir(String dirPath) {File file = new File(dirPath);if (!file.exists()) {file.mkdirs();}}/*** 將sample工程需要的資源文件拷貝到SD卡中使用(授權文件為臨時授權文件,請注冊正式授權)** @param isCover 是否覆蓋已存在的目標文件* @param source* @param dest*/private void copyFromAssetsToSdcard(boolean isCover, String source, String dest) {File file = new File(dest);if (isCover || (!isCover && !file.exists())) {InputStream is = null;FileOutputStream fos = null;try {is = getResources().getAssets().open(source);String path = dest;fos = new FileOutputStream(path);byte[] buffer = new byte[1024];int size = 0;while ((size = is.read(buffer, 0, 1024)) >= 0) {fos.write(buffer, 0, size);}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}try {if (is != null) {is.close();}} catch (IOException e) {e.printStackTrace();}}}}@Overrideprotected void onStop() {super.onStop();// 停止喚醒監聽mWpEventManager.send("wp.stop", null, null, 0, 0);}}

注:源碼是將官網給的demo進行整合,并且刪除了一些用不到的方法,簡少了代碼量。

activity_main:只有一個TextView和一個EditView,很簡單。TextView用于顯示結果,EditView用于語音合成的文字信息

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.example.administrator.baiduvoicetest.MainActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="18dp"android:padding="8dp"android:id="@+id/txtResult" /><EditTextandroid:id="@+id/input"android:layout_width="fill_parent"android:layout_height="wrap_content"android:hint="input" /></LinearLayout>

AndroidManifest:添加權限和一個作為語音識別的UI的活動

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.administrator.baiduvoicetest"><uses-permission android:name="android.permission.RECORD_AUDIO" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.READ_PHONE_STATE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /><uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /><uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /><uses-permission android:name="android.permission.WRITE_SETTINGS" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><!-- begin: baidu speech sdk--><!--離線功能指南:1. 在百度語音開放平臺注冊應用,http://yuyin.baidu.com/app2. 為您的應用的“申請離線授權頁面”,填寫程序包名3. 在當前應用的AndroidManifest.xml中填寫相應的APP_ID(或在代碼中設置appid參數)4. 根據場景下載并集成相應的資源,見http://yuyin.baidu.com/docs/asr/131和http://yuyin.baidu.com/asr/download另外需要注意的是離線功能只是在線功能的“增強”,不能永久不聯網使用(特別是首次使用)。--><!-- 請填寫真實的APP_ID API_KEY SECRET_KEY --><meta-data android:name="com.baidu.speech.APP_ID" android:value="8888274"/><meta-data android:name="com.baidu.speech.API_KEY" android:value="FOFOGnjFERG3UTZC4FdDnXhM"/><meta-data android:name="com.baidu.speech.SECRET_KEY" android:value="63830985f5b05d2863f13ad07c7feaa3"/><service android:name="com.baidu.speech.VoiceRecognitionService" android:exported="false" /><activityandroid:name="com.baidu.voicerecognition.android.ui.BaiduASRDigitalDialog"android:configChanges="orientation|keyboardHidden|screenLayout"android:theme="@android:style/Theme.Dialog"android:exported="false"android:screenOrientation="portrait"><intent-filter><action android:name="com.baidu.action.RECOGNIZE_SPEECH" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></activity><!-- end : baidu speech sdk--><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity></application></manifest>

以上所述是小編給大家介紹的android 基于百度語音的語音交互功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 云霄县| 白朗县| 阜城县| 大埔区| 湾仔区| 济宁市| 通州区| 开原市| 漯河市| 仙居县| 浙江省| 东海县| 镇赉县| 长海县| 高唐县| 清河县| 台山市| 三江| 安徽省| 阿合奇县| 岳阳县| 东乡族自治县| 张掖市| 奉新县| 永平县| 山西省| 浦东新区| 怀安县| 洱源县| 宜都市| 保康县| 河津市| 新津县| 邳州市| 黑水县| 峨山| 崇明县| 抚顺县| 乳源| 洪雅县| 泌阳县|