最近在百度人工智能开放平台看到,百度的离在线语音已经免费了,小激动一下(毕竟之前跟科大一样,都是离线收费),然后写了一个小工具APP基本功能如下:
1.拦截通知栏消息(NotificationListenerService
)
2.语音播放微信、QQ消息内容(可设置带着耳机的时候播放)
想法很简单,经常在跑步,中途不方便查看消息,这样的小工具就可以满足需求了,当然这篇文章主要是讲百度语音的快速集成,下面开始。
获取相关key
登录百度开发者管理平台,注册一个APP获取到三个东东:APPID、APPKEY、SECRETKEY
开始集成
百度官网给的相关文档:百度官方文档
虽然写的不是很清楚,但相信聪明的你还是能集成进去[/斜眼笑]
项目里面我封装成了一个相对简单的类,方便在其他应用里面调用,下面看下代码:
package com.tommy.modelweb;
import android.content.Context;
import android.media.AudioManager;
import android.os.Environment;
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 java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by Tommy on 2017/3/15.
*/
public class BaiDuSpeechDao implements SpeechSynthesizerListener {
private SpeechSynthesizer mSpeechSynthesizer;
public String mSampleDirPath;
private static final String SAMPLE_DIR_NAME = "baiduTTS";
private static final String SPEECH_FEMALE_MODEL_NAME = "bd_etts_common_speech_m15_mand_eng_high_am-mix_v3.0.0_20170505.dat";
private static final String SPEECH_MALE_MODEL_NAME = "bd_etts_common_speech_yyjw_mand_eng_high_am-mix_v3.0.0_20170512.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 APIKEY = AppConfig.APIKEY;
private static final String SECRETKEY = AppConfig.SECRETKEY;
private static final String APPID = AppConfig.APPID;
private AudioManager mAudioManager; //音乐媒体管理
public BaiDuSpeechDao(Context context){
initialEnv(context);
startTTS(context);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
private void initialEnv(Context context) {
if (mSampleDirPath == null) {
String sdcardPath = Environment.getExternalStorageDirectory().toString();
mSampleDirPath = sdcardPath + "/" + SAMPLE_DIR_NAME;
}
makeDir(mSampleDirPath);
copyFromAssetsToSdcard(context,false, SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);
copyFromAssetsToSdcard(context,false, SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_MALE_MODEL_NAME);
copyFromAssetsToSdcard(context,false, TEXT_MODEL_NAME, mSampleDirPath + "/" + TEXT_MODEL_NAME);
// copyFromAssetsToSdcard(context,false, LICENSE_FILE_NAME, mSampleDirPath + "/" + LICENSE_FILE_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(Context context, boolean isCover, String source, String dest) {
File file = new File(dest);
if (isCover || (!isCover && !file.exists())) {
InputStream is = null;
FileOutputStream fos = null;
try {
is = context.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();
}
}
}
}
// 初始化语音合成客户端并启动
private void startTTS(Context context) {
LogUtil.e("合成语音");
// 获取语音合成对象实例
mSpeechSynthesizer = SpeechSynthesizer.getInstance();
// 设置context
mSpeechSynthesizer.setContext(context);
// 设置语音合成状态监听器
// mSpeechSynthesizer.setSpeechSynthesizerListener(this);
// 设置在线语音合成授权,需要填入从百度语音官网申请的api_key和secret_key
mSpeechSynthesizer.setApiKey(APIKEY, SECRETKEY);
// 设置离线语音合成授权,需要填入从百度语音官网申请的app_id
mSpeechSynthesizer.setAppId(APPID);
// 设置语音合成文本模型文件
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/"+ TEXT_MODEL_NAME);
// 设置语音合成声音模型文件
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);
//设置发音的人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "4");
// 设置合成的音量,0-9 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "9");
// 设置合成的语速,0-9 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "3");
// 设置合成的语调,0-9 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");
// 设置语音合成声音授权文件
// mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_LICENCE_FILE, mSampleDirPath + "/" + LICENSE_FILE_NAME);
// 获取语音合成授权信息
AuthInfo authInfo = mSpeechSynthesizer.auth(TtsMode.MIX);
// 判断授权信息是否正确,如果正确则初始化语音合成器并开始语音合成,如果失败则做错误处理
if (authInfo.isSuccess()) {
LogUtil.e("授权成功");
mSpeechSynthesizer.initTts(TtsMode.MIX); //离在线合成
mSpeechSynthesizer.setStereoVolume(1.0f,1.0f);
// mSpeechSynthesizer.speak("百度语音合成示例程序正在运行");
} else {
// 授权失败
LogUtil.e("授权失败");
}
}
//设置音量
public void setVolume(float l,float r){
mSpeechSynthesizer.setStereoVolume(l,r);
}
public void onError(String arg0, SpeechError arg1) {
// 监听到出错,在此添加相关操作
LogUtil.e("合成失败");
}
public void onSpeechFinish(String arg0) {
// 监听到播放结束,在此添加相关操作
LogUtil.e("合成结束");
}
public void onSpeechProgressChanged(String arg0, int arg1) {
// 监听到播放进度有变化,在此添加相关操作
LogUtil.e("合成播放进度变化");
}
public void onSpeechStart(String arg0) {
// 监听到合成并播放开始,在此添加相关操作
LogUtil.e("合成并播放开始");
}
public void onSynthesizeDataArrived(String arg0, byte[] arg1, int arg2) {
// 监听到有合成数据到达,在此添加相关操作
LogUtil.e("合成到达");
}
public void onSynthesizeFinish(String arg0) {
// 监听到合成结束,在此添加相关操作
LogUtil.e("合成结束");
}
public void onSynthesizeStart(String arg0) {
// 监听到合成开始,在此添加相关操作
LogUtil.e("合成开始");
}
/**
* 说话
* @param str
*/
public void speak(String str){
if (mSpeechSynthesizer!=null){
//说好的时候把焦点获取过来,然后再播放,放完后再恢复其他声音
// if (mAudioManager!=null){
// mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
// }
// mSpeechSynthesizer.speak(str);
if (mAudioManager!=null){
//请求媒体焦点
int result = mAudioManager.requestAudioFocus(audioFocusChangeListener,9,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
//判断请求焦点是否成功
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED){
//请求成功,这里你就可以开始播放了 (比如这时候在拨打电话,那请求是不成功的)
mSpeechSynthesizer.speak(str);
releaseFocus();
}
}
}
}
//设置服务监听
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
//重新获取焦点
case AudioManager.AUDIOFOCUS_GAIN:
//判断是否需要重新播放音乐
LogUtil.e("重新获得焦点");
break;
//暂时失去焦点
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
//暂时失去焦点,暂停播放音乐(将needRestart设置为true)
LogUtil.e("暂时失去焦点");
break;
//失去焦点
case AudioManager.AUDIOFOCUS_LOSS:
//暂停播放音乐,不再继续播放
LogUtil.e("失去焦点");
mSpeechSynthesizer.stop();
break;
}
}
};
public void releaseFocus(){
//取消注册音频竞争
if (mAudioManager != null && audioFocusChangeListener != null) {
LogUtil.e("主动释放焦点");
mAudioManager.abandonAudioFocus(audioFocusChangeListener);
}
}
}
这个工具类贴进你项目中,然后在外面的调用是这样子滴:
//语音播报
private void speak(String text){
if (baiDuSpeechDao!=null){
baiDuSpeechDao.speak(text);
}else {
baiDuSpeechDao = new BaiDuSpeechDao(this);
baiDuSpeechDao.speak(text);
}
}
OK!就这么简单,完事。
快速集成步骤
1.导入各种离线包,你懂的,贴到你项目OK?
2.把 BaiDuSpeechDao.java 这个文件贴过去
3.权限
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"/>
<!-- 语音合成 -->
<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.调用一下,完事
//语音播报
private void speak(String text){
if (baiDuSpeechDao!=null){
baiDuSpeechDao.speak(text);
}else {
baiDuSpeechDao = new BaiDuSpeechDao(this);
baiDuSpeechDao.speak(text);
}
}
结束语
感谢你看到这里,到此百度语音就算集成完了。
对了,提醒下,demo里的 那些key 我写了//TODO: 请自行填补
完整Demo下载地址:下载地址