Android自带的语音播报不支持中文;
科大讯飞开始收费了;
百度离线语音合成也收费,但是! 在线语音合成不收费,需要在百度开放平台申请AppId;
文档:https://cloud.baidu.com/doc/SPEECH/index.html
SDK下载:https://ai.baidu.com/sdk#tts
百度在线语音合成:
没有找到百度在线语音合成的文档,自己参考百度语音SDK抽取了一下;
1、下载百度的SDK https://cloud.baidu.com/doc/SPEECH/s/Ck4nlz4cx , 把jar包之类的拷贝一下;
2、初始化,在线语音合成很简单(获取实例,给上下文、设置appid等、然后调用初始化就行了),百度建议放在子线程中:
protected SpeechSynthesizer mSpeechSynthesizer;
mSpeechSynthesizer = SpeechSynthesizer.getInstance();
mSpeechSynthesizer.setContext(context);
// 2. 设置listener
mSpeechSynthesizer.setSpeechSynthesizerListener(null);
// 3. 设置appId,appKey.secretKey
mSpeechSynthesizer.setAppId(AppConfig.BaiduTTSAppId);
mSpeechSynthesizer.setApiKey(AppConfig.BaiduTTSAppKey, AppConfig.BaiduTTSSecretKey);
// 5. 以下setParam 参数选填。不填写则默认值生效
// 设置在线发声音人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
// 设置合成的音量,0-15 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "15");
// 设置合成的语速,0-15 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5");
// 设置合成的语调,0-15 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);
// 该参数设置为TtsMode.MIX生效。即纯在线模式不生效。
// 6. 初始化
int result = mSpeechSynthesizer.initTts(TtsMode.ONLINE);
3、播放、暂停、恢复播放、停止播放:
mSpeechSynthesizer.speak(text); //开始播放
mSpeechSynthesizer.pause(); //暂停
mSpeechSynthesizer.resume(); //恢复
mSpeechSynthesizer.stop(); //停止
百度在线语音合成封装:
/**
* 百度语音合成 在线TTS
*
* 播放 :立即播报
* 排在正在播放的下一个
* 排在播放列表的最后
*
* 暂停 : 立即暂停
* 播报完成当前语音再暂停
*
* 停止 : 立即停止
* 播报完成当前语音再停止
*
* 恢复播放 : 若当前播报未完成,继续播报当前语音 否则播报队列中的;
*
* 可以获取当前播报状态
*
*/
public class TtsSyntherizer {
public TtsSyntherizer(Context context) {
this.context = context;
initTTs();
}
private Context context;
protected SpeechSynthesizer mSpeechSynthesizer;
private volatile boolean isInitTts = false;
/**
* 初始化语音播报
*/
protected void initTTs() {
new Thread(new Runnable() {
@Override
public void run() {
if (AppConfig.IS_DEV) LoggerProxy.printable(true); // 日志打印在logcat中
// 1. 获取实例
mSpeechSynthesizer = SpeechSynthesizer.getInstance();
mSpeechSynthesizer.setContext(context);
// 2. 设置listener
mSpeechSynthesizer.setSpeechSynthesizerListener(new MessageListener(){
@Override
public void onSpeechStart(String utteranceId) {
super.onSpeechStart(utteranceId);
L.cc("播放开始");
ttsState = TtsStateEnum.PLAY;
}
@Override
public void onSpeechFinish(String utteranceId) {
super.onSpeechFinish(utteranceId);
if (!ListUtils.isEmpty(ttsPlayDatas) && ttsState == TtsStateEnum.PLAY){
//如果当前播放列表中有数据,并且不是暂停状态或停止状态
ttsSpeak(ttsPlayDatas.get(0));
ttsPlayDatas.remove(0);
}
L.cc("播放结束");
ttsState = TtsStateEnum.LDLE;
}
});
// 3. 设置appId,appKey.secretKey
mSpeechSynthesizer.setAppId(AppConfig.BaiduTTSAppId);
mSpeechSynthesizer.setApiKey(AppConfig.BaiduTTSAppKey, AppConfig.BaiduTTSSecretKey);
// 5. 以下setParam 参数选填。不填写则默认值生效
// 设置在线发声音人: 0 普通女声(默认) 1 普通男声 2 特别男声 3 情感男声<度逍遥> 4 情感儿童声<度丫丫>
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
// 设置合成的音量,0-15 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_VOLUME, "15");
// 设置合成的语速,0-15 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEED, "5");
// 设置合成的语调,0-15 ,默认 5
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_PITCH, "5");
mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_DEFAULT);
// 该参数设置为TtsMode.MIX生效。即纯在线模式不生效。
// 6. 初始化
int result = mSpeechSynthesizer.initTts(TtsMode.ONLINE);
if (result == 0) {
isInitTts = true;
} else {
isInitTts = false;
}
}
}).start();
}
private TtsStateEnum ttsState = TtsStateEnum.LDLE; //默认是空闲状态
private List<String> ttsPlayDatas; //语音播报列表
/**
* 开始语音播报
* @param text 播报内容
* @param code 1 代表立即播报
* 2 排在正在播放的下一个
* 3 排在最后
* @param isClearQueue 是否播放完本条内容后清空队列停止播报
* @return
*/
public int ttsSpeak(String text , int code , boolean isClearQueue) {
if (mSpeechSynthesizer != null && isInitTts){
int result = 0;
if (ttsPlayDatas == null)ttsPlayDatas = new ArrayList<>();
switch (code){
case 1: //立即播报
if (ttsState != TtsStateEnum.LDLE)ttsStop(true);
ttsSpeak(text);
break;
case 2: //排在正在播放的下一个
if (ttsState != TtsStateEnum.LDLE) {
ttsPlayDatas.add(0, text);
}else {
ttsSpeak(text);
}
break;
case 3:
if (ttsState != TtsStateEnum.LDLE) {
ttsPlayDatas.add(text);
}else {
ttsSpeak(text);
}
break;
}
if (isClearQueue) ttsPlayDatas.clear();
return result;
}else {
return 1;
}
}
/**
* 默认开始播放
* @param text
* @return
*/
public int ttsSpeak(String text) {
if (AppConfig.IS_OFF_TTS_PLAY){
return 2; //已经关闭语音播报开关
}
if (mSpeechSynthesizer != null && isInitTts){
int result = mSpeechSynthesizer.speak(text);
return result;
}else {
return 1;
}
}
/**
* 暂停语音播报
* @parem afterCurrent 是否立即暂停
* @return 0 是成功
*/
public int ttsPause(boolean afterCurrent) {
if (mSpeechSynthesizer != null && isInitTts){
if (afterCurrent){ //立即暂停
int result = mSpeechSynthesizer.pause();
ttsState = TtsStateEnum.PAUSE;
return result;
}else { //播放完当前语音再暂停
ttsState = TtsStateEnum.PAUSE;
return 0;
}
}else {
return 1;
}
}
/**
* 恢复语音播报
* @return 0 是成功
*/
public int ttsResume() {
if (mSpeechSynthesizer != null && isInitTts){
if (ttsState == TtsStateEnum.PAUSE){ //如果是暂停状态,就恢复播放
int result = mSpeechSynthesizer.resume();
ttsState = TtsStateEnum.PLAY;
return result;
}else { //如果不是暂停状态
if (!ListUtils.isEmpty(ttsPlayDatas) && ttsState == TtsStateEnum.LDLE){
ttsSpeak(ttsPlayDatas.get(0));
}
return 0;
}
}else {
return -1;
}
}
/**
* 停止语音播报
* @parem afterCurrent 是否立即暂停
* @return 0是成功
*/
public int ttsStop(boolean afterCurrent) {
if (mSpeechSynthesizer != null && isInitTts){
if (ttsPlayDatas != null) ttsPlayDatas.clear();
if (afterCurrent){ //立即停止播报
int result = mSpeechSynthesizer.stop();
ttsState = TtsStateEnum.LDLE;
return result;
}else { //当前播报完成再停止
ttsState = TtsStateEnum.LDLE;
return 0;
}
}else {
return 1;
}
}
/**
* 获取TTS状态
* @return 0是成功
*/
public TtsStateEnum getTtsState() {
if (mSpeechSynthesizer != null && isInitTts){
return ttsState;
}else {
return TtsStateEnum.LDLE;
}
}
/**
* 释放TTS资源
*/
public void release() {
if (mSpeechSynthesizer != null){
mSpeechSynthesizer.stop();
mSpeechSynthesizer.release();
isInitTts = false;
ttsState = TtsStateEnum.LDLE;
ttsPlayDatas = null;
mSpeechSynthesizer = null;
}
}
}
public enum TtsStateEnum {
PLAY(0)
,PAUSE(1)
,LDLE(2);
private int state;
TtsStateEnum(int state){
this.state = state;
}
public int getState(){
return state;
}
}
代码其实很简单,自己又封装了一下队列播放消息;
最后,如果你打开了混淆,别忘记添加混淆配置:
# TTS
-keep class com.baidu.tts.**{*;}
-keep class com.baidu.speechsynthesizer.**{*;}