最近有同事做项目遇到这样一个需求,就是通过原生TTS播报文本希望能有暂停的功能,目前原生TTS接口TextToSpeech没有提供相应的接口,所以只能通过其他途径进行解决,目前初步的解决思路是:
- (1)通过TextToSpeech保存文本为本地wav文件
- (2)通过MediaPlayer播放本地的wav文件
- (3)通过MediaPlayer的接口实现播放的暂停,回复和重置等功能
思路很简单,网上也有相应的说法,但是没有落实的方案,今天特意测试了一下,先给出主要的代码逻辑,在总结一下主要的问提。
(1)通过TextToSpeech保存文本为本地wav文件
HashMap<String, String> myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, content);
mSpeech.synthesizeToFile(content, myHashRender, wavPath);
//或者
//mSpeech.synthesizeToFile(content, null, wavPath,TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID);
(2)通过MediaPlayer播放本地的wav文件
MediaPlayer本身也是一块较多较复杂的内容,我们这里只是最基本的用法:
player.setDataSource(wavPath);
player.prepare();
(3)通过MediaPlayer的接口实现播放的暂停,回复和重置等功能
//播放
player.start();
//暂停
player.pause();
//恢复
player.resume();
//重置
player.reset();
完整的逻辑代码如下:
package aoto.com.ttstest;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Environment;
import android.speech.tts.TextToSpeech;
import android.support.annotation.RequiresApi;
import android.util.Log;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
/**
* author:why
* created on: 2019/7/10 9:57
* description:
*/
public class TTSManager {
private static final String TAG = "TTSManagerWhy";
private static volatile TTSManager manager = null;
private static TextToSpeech mSpeech = null;
private Context mContext;
private String wavPath;
private MediaPlayer player;
private HashMap<String, String> myHashRender = new HashMap();
@RequiresApi(api = Build.VERSION_CODES.M)
private TTSManager(Context context) {
this.mContext = context;
wavPath = Environment.getExternalStorageDirectory() + "/temp.wav";
player = new MediaPlayer();
//6.0以上可以设置语速
// Log.e(TAG, "TTSManager: "+ player.getPlaybackParams().getSpeed());
// player.setPlaybackParams(player.getPlaybackParams().setSpeed(??));
initSpeech();
}
/**
* Init TTS and set params
*/
private void initSpeech() {
mSpeech = new TextToSpeech(mContext, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
mSpeech.setLanguage(Locale.ENGLISH);
}
});
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static TTSManager getInstance(Context context) {
if (manager == null) {
synchronized (TTSManager.class) {
if (manager == null) {
manager = new TTSManager(context);
}
}
}
return manager;
}
public void speak(String content) {
Log.e(TAG, "speak content: " + content);
myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, content);
int r = mSpeech.synthesizeToFile(content, myHashRender, wavPath);
if (r == TextToSpeech.SUCCESS) {
Log.e(TAG, "save success" + wavPath);
} else {
Log.e(TAG, "save fail");
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
player.reset();
player.setDataSource(wavPath);
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
player.start();
}
/**
* pause the TTS
*/
public void pause() {
if (player.isPlaying()) {
player.pause();
}
}
/**
* reset the TTS
*/
public void resume() {
player.start();
}
/**
* stop the TTS
*/
public void stop() {
player.stop();
player.release();
mSpeech.shutdown();
mSpeech.stop();
}
}
下面总结几个重要的点:
(1)这里面我的语言设置的是英语,因为原生的不支持中文,而且在设置TextToSpeech参数的时候,需要在初始化工作完成之后进行,否则容易出现设置无效的情况;关于如何实现中文的暂停播报,主要问题就是需要解决中文文本转为音频文件的工作
(2)这里的播放速度控制不能通过TextToSpeech来设置了,需要通过MediaPlayer来设置实现,有一点需要注意的是,这个功能只有在6.0以上的系统才有,可以通过如下方式设置:
player.setPlaybackParams(player.getPlaybackParams().setSpeed(??));
(3)在测试中发现,我们通过TextToSpeech保存wav文件时,log显示成功了之后我直接调用播放代码是播放不了的,需要休眠一段时间之后才行,这一点也需要注意一下,我这里休眠了500ms,估计这个和文本长度还有关系,具体可以多测试一下
(4)注意各种权限的申请
后续要做的工作就是实现中文的暂停播报。
注:如果喜欢,可以扫码关注