Android Studio應(yīng)用開發(fā)集成百度語音合成使用方法實例講解
首先,語音合成是指將文本信息轉(zhuǎn)換成聲音。意思就是將文本轉(zhuǎn)化為聲音,讓你的應(yīng)用開口說話。國內(nèi)在業(yè)內(nèi)比較有名的第三方語音合成平臺有百度語音和科大訊飛。
本文集成的是百度語音合成,其主要特點是:
完全永久免費
業(yè)界首創(chuàng)完全永久免費新形式,為開發(fā)者提供最流暢最自然的語音合成服務(wù)。完全免費,永久使用,徹底擺脫限制。
離線在線融合模式
SDK可以根據(jù)當(dāng)前網(wǎng)絡(luò)狀況,自動判斷使用本地引擎還是云端引擎進行語音合成,再也不用擔(dān)心流量消耗!
多語言多音色可選
中文普通話、中英文混讀、男聲、女聲任你選,更支持語速、音調(diào)、音量、音頻碼率設(shè)置,讓你的應(yīng)用擁有最甜美和最磁性的聲音!
流暢自然的合成效果
語音合成技術(shù)業(yè)界領(lǐng)先,合成效果接近真人發(fā)聲,流暢自然,且極具表現(xiàn)力,給你最舒適的聽覺體驗!
百度語音官方的Demo是在Eclipse環(huán)境下編寫的,而在Android Studio中則有點小區(qū)別,下面請看百度語音合成使用詳細步驟(一步一步操作不要跳躍心急吃不了熱豆腐):
1、注冊百度語音開發(fā)者平臺
注冊百度賬號,注冊開發(fā)者信息,創(chuàng)建應(yīng)用,可以得到 APP ID、 API Key、和 Secret Key,在開發(fā)過程中會使用這三個值進行授權(quán)(很關(guān)鍵),開通語音合成服務(wù),若需要使用離線合成功能還需要申請離線授權(quán)。詳細步驟請看百度語音接入流程 。
Key值查看(很關(guān)鍵)
2、下載資源
下載百度語音SDK,根據(jù)自己的需要下載,本樣例下載的是離在線融合語音合成SDK_Android版 , 地址: http://yuyin.baidu.com/tts/download
3、集成百度語音指南
3.1添加 jar 包和 so 庫到工程
將開發(fā)包中的 libs 目錄整體拷貝到工程目錄(Eclipse的用戶),libs 目錄包括了jar包和各平臺的 SO 庫,開發(fā)者視應(yīng)用需要可以進行刪減。galaxy_lite.jar 是百度 Android 公共基礎(chǔ)庫,如果項目中還集成了其它百度 SDK,
如 Push SDK,在打包過程中出現(xiàn)類似如下的錯誤信息:
[2013-10-22 11:02:57 - Dex Loader] Unable to execute dex: Multiple dex files define
Lcom/baidu/android/common/logging/Configuration;
[2013-10-22 11:02:57 - VoiceRecognitionDemo] Conversion to Dalvik format failed: Unable to
execute dex: Multiple dex files define Lcom/baidu/android/common/logging/Configuration;
請將此 Jar 包移除。對于使用Android Studio的用戶,應(yīng)將libs目錄中的jar包放在libs目錄下,然后添加庫依賴(千萬別忘記), 而 .SO 庫則應(yīng)該放在jniLibs目錄下, jniLibs目錄與Java、res在相同目錄下。若沒有相應(yīng)的目錄就自己創(chuàng)建。整個結(jié)構(gòu)如下圖:
3.2 添加語音合成資源文件
將開發(fā)包中的 data 目錄下的 dat 文件放到工程的assets目錄下,assets目錄與java、res在同一目錄下,以便設(shè)置資源文件參數(shù)時使用。
3.3 權(quán)限聲明
使用百度語音需要聲明以下權(quán)限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
4、語音合成功能代碼
4、1 Tts初始化
//獲取 tts 實例 speechSynthesizer = SpeechSynthesizer.getInstance(); //設(shè)置 app 上下文(必需參數(shù)) speechSynthesizer.setContext(Context); //設(shè)置 tts 監(jiān)聽器 speechSynthesizer.setSpeechSynthesizerListener(SpeechSynthesizerListener); //文本模型文件路徑,文件的絕對路徑 (離線引擎使用) speechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, TEXT_MODEL_FILE_FULL_PATH_NAME); //聲學(xué)模型文件路徑,文件的絕對路徑 (離線引擎使用) speechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, SPEECH_MODEL_FILE_FULL_PATH_NAME); // 本 地 授 權(quán) 文 件 路 徑 , 如 未 設(shè) 置 將 使 用 默 認 路 徑 . 設(shè) 置 臨 時 授 權(quán) 文 件 路 徑 , //LICENCE_FILE_NAME 請?zhí)鎿Q成臨時授權(quán)文件的實際路徑,僅在使用臨時 license 文件時需要進行設(shè)置, //如果在[應(yīng)用管理]中開通了離線授權(quán),不需要設(shè)置該參數(shù),建議將該行代碼刪除(離線引擎) speechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_LICENCE_FILE, LICENSE_FILE_FULL_PATH_NAME); //請?zhí)鎿Q為語音開發(fā)者平臺上注冊應(yīng)用得到的 App ID (離線授權(quán)) speechSynthesizer.setAppId("your_app_id"); //請?zhí)鎿Q為語音開發(fā)者平臺注冊應(yīng)用得到的 apikey 和 secretkey (在線授權(quán)) speechSynthesizer.setApiKey("your_api_key", "your_secret_key"); //授權(quán)檢測接口 AuthInfo authInfo = speechSynthesizer.auth(TtsMode); //引擎初始化接口 speechSynthesizer.initTts(TtsMode);
注意:在初始化設(shè)置之前先把assets文件夾中的資源文件拷貝到SD卡中,以便使用。另外,離線授權(quán)臨時文件有效期只有30天,若要長久使用語音離線合成應(yīng)在應(yīng)用管理中開通離線授權(quán)。
4、2合成并播放
mSpeechSynthesizer.speak(text);
該接口比較耗時,采用排隊策略,調(diào)用后將自動加入合成隊列,并按調(diào)用順序進行合成和播放。
好了,到此你的語音合成就可以使用了,若想要進行更多參數(shù)設(shè)置,請看百度語音合成官方開發(fā)文檔 和開發(fā)手冊。
5、源碼
最后貼上我的源碼。
Manifest文件: AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.junkchen.bdttsdemo"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <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>
Layout布局文件: activity_main.xml
<?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:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp" tools:context="com.junkchen.bdttsdemo.MainActivity"> <EditText android:id="@+id/edt_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="start" android:minLines="5" android:text="Hi 我是百度語音合成,請輸入要合成的語音內(nèi)容" /> <Button android:id="@+id/btn_speak" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="語音合成并播放" /> </LinearLayout>
Java: MainActivity.java
package com.junkchen.bdttsdemo; import android.os.Bundle; import android.os.Environment; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import com.baidu.tts.answer.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 java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; public class MainActivity extends AppCompatActivity implements SpeechSynthesizerListener { private static final String TAG = "MainActivity"; 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_2016-04-05"; 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 APP_ID = "7957876";//請更換為自己創(chuàng)建的應(yīng)用 private static final String API_KEY = "cVN31pILxBhRNdGdlNHyeuyq";//請更換為自己創(chuàng)建的應(yīng)用 private static final String SECRET_KEY = "84e6987b56f11e6ee97e02ef25a2b4f0";//請更換為自己創(chuàng)建的應(yīng)用 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initialEnv(); initialTts(); initView(); } @Override protected void onDestroy() { this.mSpeechSynthesizer.release();//釋放資源 super.onDestroy(); } private EditText edt_content; private Button btn_speak; private void initView() { edt_content = (EditText) findViewById(R.id.edt_content); btn_speak = (Button) findViewById(R.id.btn_speak); btn_speak.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String content = edt_content.getText().toString(); mSpeechSynthesizer.speak(content); Log.i(TAG, ">>>say: " + edt_content.getText().toString()); } }); } /** * 初始化語音合成客戶端并啟動 */ private void initialTts() { //獲取語音合成對象實例 this.mSpeechSynthesizer = SpeechSynthesizer.getInstance(); //設(shè)置Context this.mSpeechSynthesizer.setContext(this); //設(shè)置語音合成狀態(tài)監(jiān)聽 this.mSpeechSynthesizer.setSpeechSynthesizerListener(this); //文本模型文件路徑 (離線引擎使用) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/" + TEXT_MODEL_NAME); //聲學(xué)模型文件路徑 (離線引擎使用) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME); //本地授權(quán)文件路徑,如未設(shè)置將使用默認路徑.設(shè)置臨時授權(quán)文件路徑,LICENCE_FILE_NAME請?zhí)鎿Q成臨時授權(quán)文件的實際路徑, //僅在使用臨時license文件時需要進行設(shè)置,如果在[應(yīng)用管理]中開通了離線授權(quán), //不需要設(shè)置該參數(shù),建議將該行代碼刪除(離線引擎) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_LICENCE_FILE, mSampleDirPath + "/" + LICENSE_FILE_NAME); //請?zhí)鎿Q為語音開發(fā)者平臺上注冊應(yīng)用得到的App ID (離線授權(quán)) this.mSpeechSynthesizer.setAppId(APP_ID); // 請?zhí)鎿Q為語音開發(fā)者平臺注冊應(yīng)用得到的apikey和secretkey (在線授權(quán)) this.mSpeechSynthesizer.setApiKey(API_KEY, SECRET_KEY); //發(fā)音人(在線引擎),可用參數(shù)為0,1,2,3。。。 //(服務(wù)器端會動態(tài)增加,各值含義參考文檔,以文檔說明為準(zhǔn)。0--普通女聲,1--普通男聲,2--特別男聲,3--情感男聲。。。) this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0"); // 設(shè)置Mix模式的合成策略 this.mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT); // 授權(quán)檢測接口(可以不使用,只是驗證授權(quán)是否成功) AuthInfo authInfo = this.mSpeechSynthesizer.auth(TtsMode.MIX); if (authInfo.isSuccess()) { Log.i(TAG, ">>>auth success."); } else { String errorMsg = authInfo.getTtsError().getDetailMessage(); Log.i(TAG, ">>>auth failed errorMsg: " + errorMsg); } // 引擎初始化tts接口 mSpeechSynthesizer.initTts(TtsMode.MIX); // 加載離線英文資源(提供離線英文合成功能) int result = mSpeechSynthesizer.loadEnglishModel(mSampleDirPath + "/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + "/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME); Log.i(TAG, ">>>loadEnglishModel result: " + result); } @Override public void onSynthesizeStart(String s) { //監(jiān)聽到合成開始 Log.i(TAG, ">>>onSynthesizeStart()<<< s: " + s); } @Override public void onSynthesizeDataArrived(String s, byte[] bytes, int i) { //監(jiān)聽到有合成數(shù)據(jù)到達 Log.i(TAG, ">>>onSynthesizeDataArrived()<<< s: " + s); } @Override public void onSynthesizeFinish(String s) { //監(jiān)聽到合成結(jié)束 Log.i(TAG, ">>>onSynthesizeFinish()<<< s: " + s); } @Override public void onSpeechStart(String s) { //監(jiān)聽到合成并開始播放 Log.i(TAG, ">>>onSpeechStart()<<< s: " + s); } @Override public void onSpeechProgressChanged(String s, int i) { //監(jiān)聽到播放進度有變化 Log.i(TAG, ">>>onSpeechProgressChanged()<<< s: " + s); } @Override public void onSpeechFinish(String s) { //監(jiān)聽到播放結(jié)束 Log.i(TAG, ">>>onSpeechFinish()<<< s: " + s); } @Override public void onError(String s, SpeechError speechError) { //監(jiān)聽到出錯 Log.i(TAG, ">>>onError()<<< description: " + speechError.description + ", code: " + speechError.code); } private void initialEnv() { if (mSampleDirPath == null) { String sdcardPath = Environment.getExternalStorageDirectory().toString(); mSampleDirPath = sdcardPath + "/" + SAMPLE_DIR_NAME; } File file = new File(mSampleDirPath); if (!file.exists()) { file.mkdirs(); } 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); } /** * 將工程需要的資源文件拷貝到SD卡中使用(授權(quán)文件為臨時授權(quán)文件,請注冊正式授權(quán)) * * @param isCover 是否覆蓋已存在的目標(biāo)文件 * @param source * @param dest */ public 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(); } } } } }
以上所述是小編給大家介紹的Android Studio應(yīng)用開發(fā)集成百度語音合成使用方法實例講解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
android LinearLayout和RelativeLayout組合實現(xiàn)精確布局方法介紹
用android LinearLayout和RelativeLayout實現(xiàn)精確布局此方法適合很適合新人看2012-11-11Android Studio中一套代碼多渠道打包的實現(xiàn)方法
這篇文章主要介紹了Android Studio中一套代碼多渠道打包的實現(xiàn)方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2020-05-05android listview實現(xiàn)新聞列表展示效果
這篇文章主要為大家詳細介紹了android listview實現(xiàn)新聞列表展示效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03Android仿貼吧內(nèi)容下的簡單ListView嵌套GridView
這篇文章主要為大家詳細介紹了Android仿貼吧內(nèi)容下的簡單ListView嵌套GridView,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03Android常用控件ImageSwitcher使用方法詳解
這篇文章主要為大家詳細介紹了Android常用控件ImageSwitcher的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08Android下拉刷新PtrFrameLayout的使用實例代碼
本篇文章主要介紹了Android下拉刷新PtrFrameLayout的使用實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06