前期准备
申请 key 和创建应用的步骤这里不再赘述,可以参考:在线合成Android-SDK介绍 官方文档
运行官方demo
1、下载 在线语音合成Android SDK
离线语音合成SDK只能免费使用 在线合成功能,纯离线和在线离线混合模式是需要收费的。所以我们直接使用 在线语音合成。
2、修改官方 demo 运行
打开 main/assets/auth.properties
填入自己 appId、appKey、secretKey、applicationId。
修改 app/build.gradle
中的 applicationId,改为自己的包名。
如果运行不了需要根据报错修改,可能需要修改:
1、local.properties
文件中
删掉 的 ndk.dir
修改 sdk.dir
2、修改 gradle-wrapper.properties
中 gradle 版本 和 整个项目的 build.gradle
的 gradle tools 版本,改成和自己项目相同的版本
整个项目的 build.gradle
的 repositories 改为和自己项目相同的仓库
运行程序,我们测试纯在线语音合成:
自己项目中集成
1、将官方 demo 中的 libs
文件夹下的 jar 包放入自己 libs
目录下
确保 build.gradle
中对这个 jar 包进行了引用
可以引入libs下所有的 jar
implementation fileTree(include: ['*.jar'], dir: 'libs')
或单独引入这个 jar
implementation files("libs/com.baidu.tts_2.6.2.2.20200629_44818d4.jar")
2、将 jinLibs
中自己用到的架构文件复制到自己相应的文件夹中
例如我的 build.gradle
文件中只指定了两个 abi,我就只需要复制两个文件夹即可:
3、AndroidManifest.xml 中增加权限
<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.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
4、按照官方 demo 中的 MySyntherizer 进行修改,改为符合自己业务需求的工具类
例如我的项目中有一个试听音效的功能,我就把 MySyntherizer 复制过来增加了一个播放状态speakStatus 字段,实现了 SpeechSynthesizerListener 的方法,在播放开始和结束时改变这个字段,以便在用户重复点击播放按钮的时候进行判断,如果在播放中则提示用户“播放中,请等待试听结束”。
同学们使用时需要将类中的 BD_APP_KEY 、BD_APP_SECRET_KEY 、BD_APP_ID 改为自己申请的值。
/**
* 该类是对SpeechSynthesizer的封装
* 百度语音在线合成 工具类
*/
public class MySyntherizer implements SpeechSynthesizerListener {
protected SpeechSynthesizer mSpeechSynthesizer;
protected Context context;
private static final String TAG = "MySyntherizer";
private static volatile MySyntherizer instance = null;
/**
* 当前播放状态 0 未播放 或播放已结束 1 播放中
*/
private int speakStatus = 0;
//修改为自己的 appId、appKey、secretKey
private static final String BD_APP_KEY = "nBrxIoewW0XFj2oqeqsiDdjpGTBubTMS";
private static final String BD_APP_SECRET_KEY = "aVW3OkCqRDjxFtIPPnawykiGIjVKo0ic";
private static final String BD_APP_ID = "9582183";
public static MySyntherizer getInstance() {
if (instance == null) {
synchronized (MySyntherizer.class) {
if (instance == null) {
instance = new MySyntherizer();
}
}
}
return instance;
}
/**
* 注意该方法需要在新线程中调用。且该线程不能结束。详细请参见NonBlockSyntherizer的实现
*
* @return 是否初始化成功
*/
public boolean init(Context context) {
this.context = context;
mSpeechSynthesizer = SpeechSynthesizer.getInstance();
mSpeechSynthesizer.setContext(context);
mSpeechSynthesizer.setSpeechSynthesizerListener(this);
mSpeechSynthesizer.setAppId(BD_APP_ID);
mSpeechSynthesizer.setApiKey(BD_APP_KEY, BD_APP_SECRET_KEY);
// 初始化tts 纯在线模式
int result = mSpeechSynthesizer.initTts(TtsMode.ONLINE);
if (result != 0) {
Log.d(TAG, "【error】initTts 初始化失败 + errorCode:" + result);
return false;
}
// 设置播放的音频流类型,具体参数和组合见AudioAttributes,https://source.android.google.cn/devices/audio/attributes
// mSpeechSynthesizer.setAudioAttributes(AudioAttributes.USAGE_MEDIA,AudioAttributes.CONTENT_TYPE_MUSIC);
return true;
}
/**
* 合成并播放
*
* @param text 小于1024 GBK字节,即512个汉字或者字母数字
* @return =0表示成功
*/
public void speak(String text) {
int result = mSpeechSynthesizer.speak(text);
if (result != 0) {
Log.i(TAG, "speak text:" + text + ";error,please look up error code =" + result + "in https://ai.baidu.com/ai-doc/SPEECH/qk844cpcs");
}
}
/**
* 合成并播放
*
* @param text 小于1024 GBK字节,即512个汉字或者字母数字
* @param utteranceId 用于listener的回调,默认"0"
* @return =0表示成功
*/
public void speak(String text, String utteranceId) {
int result = mSpeechSynthesizer.speak(text, utteranceId);
if (result != 0) {
Log.i(TAG, "speak text:" + text + ";error,please look up error code =" + result + "in https://ai.baidu.com/ai-doc/SPEECH/qk844cpcs");
}
}
/**
* 只合成不播放
* 音频流保存为文件的方法可以参见官方demo SaveFileActivity及FileSaveListener
*
* @param text 合成的文本
* @return =0表示成功
*/
public void synthesize(String text) {
int result = mSpeechSynthesizer.synthesize(text);
if (result != 0) {
Log.i(TAG, "speak text:" + text + ";error,please look up error code =" + result + "in https://ai.baidu.com/ai-doc/SPEECH/qk844cpcs");
}
}
public void synthesize(String text, String utteranceId) {
int result = mSpeechSynthesizer.synthesize(text, utteranceId);
if (result != 0) {
Log.i(TAG, "speak text:" + text + ";error,please look up error code =" + result + "in https://ai.baidu.com/ai-doc/SPEECH/qk844cpcs");
}
}
/**
* 批量播放
*/
public int batchSpeak(List<Pair<String, String>> texts) {
List<SpeechSynthesizeBag> bags = new ArrayList<SpeechSynthesizeBag>();
for (Pair<String, String> pair : texts) {
SpeechSynthesizeBag speechSynthesizeBag = new SpeechSynthesizeBag();
speechSynthesizeBag.setText(pair.first);
if (pair.second != null) {
speechSynthesizeBag.setUtteranceId(pair.second);
}
bags.add(speechSynthesizeBag);
}
return mSpeechSynthesizer.batchSpeak(bags);
}
public int speakStatus() {
return speakStatus;
}
public int pause() {
return mSpeechSynthesizer.pause();
}
public int resume() {
return mSpeechSynthesizer.resume();
}
public int stop() {
speakStatus = 0;
return mSpeechSynthesizer.stop();
}
/**
* 设置播放音量,默认已经是最大声音
* 0.0f为最小音量,1.0f为最大音量
*
* @param leftVolume [0-1] 默认1.0f
* @param rightVolume [0-1] 默认1.0f
*/
public void setStereoVolume(float leftVolume, float rightVolume) {
mSpeechSynthesizer.setStereoVolume(leftVolume, rightVolume);
}
public void release() {
mSpeechSynthesizer.stop();
mSpeechSynthesizer.release();
mSpeechSynthesizer = null;
}
//一些回调
@Override
public void onSynthesizeStart(String s) {
}
@Override
public void onSynthesizeDataArrived(String s, byte[] bytes, int i, int i1) {
}
@Override
public void onSynthesizeFinish(String s) {
}
@Override
public void onSpeechStart(String s) {
speakStatus = 1;
}
@Override
public void onSpeechProgressChanged(String s, int i) {
}
@Override
public void onSpeechFinish(String s) {
speakStatus = 0;
}
@Override
public void onError(String s, SpeechError speechError) {
}
}
5、初始化
在自己项目的 Application 中初始化
//百度语音
new Thread() {
@Override
public void run() {
MySyntherizer.getInstance().init(CommonApplication.this);
}
}.start();
6、使用
MySyntherizer.getInstance().speak("您有新订单,请及时处理");