最近有同事做项目遇到这样一个需求,就是通过原生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() {@Overridepublic 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)注意各种权限的申请
后续要做的工作就是实现中文的暂停播报。中文实现已经更新
补(2019.07.15):
该方法也可以通过安装中文引擎配合上面的接口实现,下载安装并配置中文引擎可参考Android原生TTS的基本使用以及配合中文语音包实现中文TTS,其他方式不变,即可实现中文TTS播报的暂停与恢复功能。
注:如果喜欢,可以扫码关注