我正在开发一个我的文本视图包含String和两个按钮的应用程序。当我单击“语音”按钮时,文本将转换为语音。但是我想语音运行时突出显示单词。
这是我的文字到语音初始化:
textToSpeech = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
@Override
public void onInit(int status) {
if (status == TextToSpeech.SUCCESS) {
result = textToSpeech.setLanguage(Locale.ENGLISH);
textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
Log.d(utteranceId, "TTS start");}
@Override
public void onDone(String utteranceId) {
Log.d(utteranceId, "TTS done");}
@Override
public void onError(String utteranceId) {
});
} else {
Toast.makeText(getApplicationContext(), "Feature is not Available", Toast.LENGTH_SHORT).show();
}
}
});
和其他代码:
private void speak() {
if (result == TextToSpeech.LANG_MISSING_DATA || result == TextToSpeech.LANG_NOT_SUPPORTED) {
Toast.makeText(getApplicationContext(), "Feature is not Available", Toast.LENGTH_SHORT).show();
} else {
textToSpeech.setPitch(1f);
textToSpeech.setSpeechRate(0.8f);
HashMap<String, String> params = new HashMap<>();
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "utteranceId");
textToSpeech.speak(getString(R.string.storytxt), TextToSpeech.QUEUE_FLUSH, params);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (textToSpeech != null) {
textToSpeech.shutdown();
}
}
直到这里我都没问题。现在,我要突出显示文本。我不知道该怎么办。我到处搜寻都没有任何线索。
我将字符串存储在String.xml中。
理论上,实现此目的的最直观的方法是:
1)
将字符串分成pieces >>
[2)
检测何时/正在说每首]
3)
突出显示>相应地
但是,不幸的是,当使用实时生成语音输出的Android TextToSpeech类时,您能够精确检测(使用UtteranceProgressListener)的进度的最小语音单位是utterance(您决定发送给TTS的任何字符串)-不一定是word。
没有一种机制,您可以简单地发送多字串作为发声,然后以某种方式检测何时讲出每个字。
因此,为了(轻松地)连续突出显示每个单词,您必须:
[A)
”将每个单词作为单个发音单独发送到TTS(但这会导致发音不连贯,或者
[B)
而是逐句突出显示,将每个句子作为发声发送(最简单的方法,但不是您想要的行为)。
[如果您真的坚持要实现逐字突出显示效果,我能想到的唯一方法(使用Android TextToSpeech
)是使用句子大小的语音,而不是使用talk(),而是使用synthesizeToFile( )...然后使用某种媒体播放器或声音播放器播放语音...以某种方式根据第n个字相对于总音频文件长度的位置来估算高亮显示的时间。因此,例如,如果句子的长度为10个单词,而文件的完成率是30%,则您将突出显示第4个单词。这将是困难的,但在理论上是可能的。
[显然,已经存在可以执行此操作的应用和游戏...说唱歌手Parappa或卡拉ok应用之类的游戏,但我认为,他们的实现方式是通过预先录制带有特定标记的音频文件来触发亮点。
我不知道在哪里使用TTS的任何解决方案...特别是如果句子在运行前是未知的。
如果您决定采用这些更狭窄的方法之一,那么我建议相应地发布一个新问题。