【Android語音合成TTS】百度語音接入方法,和使用技巧詳解
依託於百度開放雲,百度語音為合作伙伴提供了業界領先、永久免費的語音技術服務,目前已上線的服務包括語音識別、語義解析、語音合成,後續會繼續帶來開放資源、多輪對話等技術服務;通過SDK、REST API及離線開發包等多種服務方式,滿足不同開發者的開發需求。
目前百度語音提供免費的語音接入,語音合成質量尚可,但還沒開放離線TTS。
服務接入流程
整合開發
匯入百度語音的相關jar包和so檔案如圖:
提示:
將開發包中的 libs目錄整體拷貝到工程目錄,libs目錄包括了各平臺的 SO庫,開發者視應用需要可以進行刪減。galaxy_lite.jar是百度 Android公共基礎庫,如果專案中還集成了其它百度
[2013-10-22 11:02:57 - Dex Loader] Unableto execute dex: Multiple dex files defineLcom/baidu/android/common/logging/Configuration; [2013-10-22 11:02:57 -VoiceRecognitionDemo] Conversion to Dalvik format failed: Unable to executedex: Multiple dex files define Lcom/baidu/android/common/logging/Configuration;
請將此 Jar 包移除。如果 Eclipse ADT版本外掛低於 17,需要手工新增依賴庫,新增方法為:Project => Properties => Java Build Path => Libraries => AddJAR... 3
為了方便使用我這裡將百度語音合成引擎做了進一步的封裝,封裝成了SpeechUtil以方便呼叫:
package com.jph.tts; import android.content.Context; import android.media.AudioManager; import android.util.Log; import com.baidu.speechsynthesizer.SpeechSynthesizer; import com.baidu.speechsynthesizer.SpeechSynthesizerListener; import com.baidu.speechsynthesizer.publicutility.SpeechError; /** * 語音合成工具類 * * @author JPH * @date 2015-4-14 下午1:33:37 */ public class SpeechUtil implements SpeechSynthesizerListener { protected static final int UI_LOG_TO_VIEW = 0; private SpeechSynthesizer speechSynthesizer; private Context context; public SpeechUtil(Context activity) { this.context = activity; init(); } /** * 初始化合成相關元件 * * @author JPH * @date 2015-4-14 下午1:36:53 */ private void init() { speechSynthesizer = new SpeechSynthesizer(context, "holder", this); // 此處需要將setApiKey方法的兩個引數替換為你在百度開發者中心註冊應用所得到的apiKey和secretKey speechSynthesizer.setApiKey("your apiKey", "your secretKey"); speechSynthesizer.setAudioStreamType(AudioManager.STREAM_MUSIC); // activity.setVolumeControlStream(AudioManager.STREAM_MUSIC); setParams(); } /** * 開始文字合成並朗讀 * @author JPH * @date 2015-4-14 下午1:47:05 * @param content */ public void speak(final String content) { new Thread(new Runnable() { @Override public void run() { // setParams(); int ret = speechSynthesizer.speak(content.toString()); if (ret != 0) { Log.e("inf","開始合成器失敗:"+ret); } } }).start(); } /** * 取消本次合成並停止朗讀 * @author JPH * @date 2015-4-14 下午2:20:33 */ public void cancle() { speechSynthesizer.cancel(); } /** * 暫停文字朗讀,如果沒有呼叫speak(String)方法或者合成器初始化失敗,該方法將無任何效果 * @author JPH * @date 2015-4-14 下午2:21:07 */ public void pause() { speechSynthesizer.pause(); } /** * 繼續文字朗讀,如果沒有呼叫speak(String)方法或者合成器初始化失敗,該方法將無任何效果 * @author JPH * @date 2015-4-14 下午2:21:29 */ public void resume() { speechSynthesizer.resume(); } /** * 為語音合成器設定相關引數 * @author JPH * @date 2015-4-14 下午1:45:11 */ private void setParams() { speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");//發音人,目前支援女聲(0)和男聲(1) speechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "9");//音量,取值範圍[0, 9],數值越大,音量越大 speechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5");//朗讀語速,取值範圍[0, 9],數值越大,語速越快 speechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");//音調,取值範圍[0, 9],數值越大,音量越高 speechSynthesizer.setParam(SpeechSynthesizer.PARAM_AUDIO_ENCODE, SpeechSynthesizer.AUDIO_ENCODE_AMR);//音訊格式,支援bv/amr/opus/mp3,取值詳見隨後常量宣告 speechSynthesizer.setParam(SpeechSynthesizer.PARAM_AUDIO_RATE, SpeechSynthesizer.AUDIO_BITRATE_AMR_15K85);//音訊位元率,各音訊格式支援的位元率詳見隨後常量宣告 } @Override public void onStartWorking(SpeechSynthesizer synthesizer) { Log.i("msg", "開始工作,請等待資料..."); } @Override public void onSpeechStart(SpeechSynthesizer synthesizer) { Log.i("msg", "朗讀開始"); } @Override public void onSpeechResume(SpeechSynthesizer synthesizer) { Log.i("msg", "朗讀繼續"); } @Override public void onSpeechProgressChanged(SpeechSynthesizer synthesizer, int progress) { // TODO Auto-generated method stub } @Override public void onSpeechPause(SpeechSynthesizer synthesizer) { Log.i("msg", "朗讀已暫停"); } @Override public void onSpeechFinish(SpeechSynthesizer synthesizer) { Log.i("msg", "朗讀已停止"); } @Override public void onNewDataArrive(SpeechSynthesizer synthesizer, byte[] audioData, boolean isLastData) { Log.i("msg", "新的音訊資料:" + audioData.length + (isLastData ? "(end)" : "")); } @Override public void onError(SpeechSynthesizer synthesizer, SpeechError error) { Log.i("msg", "發生錯誤:" + error.errorDescription + "(" + error.errorCode + ")"); } @Override public void onCancel(SpeechSynthesizer synthesizer) { Log.i("msg", "已取消"); } @Override public void onBufferProgressChanged(SpeechSynthesizer synthesizer, int progress) { // TODO Auto-generated method stub } }
使用方法:
package com.jph.tts;
import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.baidu.tts.sample.R;
public class HomeActivity extends Activity implements OnClickListener {
protected static final int UI_LOG_TO_VIEW = 0;
private TextView logView;
private EditText inputTextView;
private Button startButton;
private SpeechUtil speechUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
logView = (TextView) findViewById(R.id.logView);
logView.setMovementMethod(new ScrollingMovementMethod());
inputTextView = (EditText) findViewById(R.id.inputTextView);
speechUtil = new SpeechUtil(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnStart:
speechUtil.speak(inputTextView.getText().toString());
break;
case R.id.btnPause:
speechUtil.pause();
break;
case R.id.btnResume:
speechUtil.resume();
break;
case R.id.btnStop:
speechUtil.cancle();
break;
default:
break;
}
}
}
因為百度TTS需要聯網解析所以要賦予應用相應的許可權:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
推薦閱讀: