Aja*_*jja 4 java android highlight text-to-speech
我正在开发一个应用程序,其中我的 textview 由字符串和两个按钮组成。当我单击说话按钮时,文本会转换为语音。但是我想在语音运行时突出显示这个词。
这是我的文本到语音初始化:
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();
}
}
});
Run Code Online (Sandbox Code Playgroud)
和其他代码:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
到这里我没有遇到任何问题。现在我想突出显示文本。我不知道该怎么做。我到处搜索仍然没有这方面的线索。
我将字符串存储在 String.xml 中。
对于 Android API 26 及更高版本以及支持 onRangeStart 的 TTS 引擎(在本例中为 Google TTS):
public class MainActivity extends AppCompatActivity implements TextToSpeech.OnInitListener {
TextToSpeech tts;
String sentence = "The Quick Brown Fox Jumps Over The Lazy Dog.";
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
textView.setText(sentence);
tts = new TextToSpeech(this, this);
}
// TextToSpeech.OnInitListener (for our purposes, the "main method" of this activity)
public void onInit(int status) {
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String utteranceId) {
Log.i("XXX", "utterance started");
}
@Override
public void onDone(String utteranceId) {
Log.i("XXX", "utterance done");
}
@Override
public void onError(String utteranceId) {
Log.i("XXX", "utterance error");
}
@Override
public void onRangeStart(String utteranceId,
final int start,
final int end,
int frame) {
Log.i("XXX", "onRangeStart() ... utteranceId: " + utteranceId + ", start: " + start
+ ", end: " + end + ", frame: " + frame);
// onRangeStart (and all UtteranceProgressListener callbacks) do not run on main thread
// ... so we explicitly manipulate views on the main thread:
runOnUiThread(new Runnable() {
@Override
public void run() {
Spannable textWithHighlights = new SpannableString(sentence);
textWithHighlights.setSpan(new ForegroundColorSpan(Color.YELLOW), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
textView.setText(textWithHighlights);
}
});
}
});
}
public void startClicked(View ignored) {
tts.speak(sentence, TextToSpeech.QUEUE_FLUSH, null, "doesn't matter yet");
}
}
Run Code Online (Sandbox Code Playgroud)
// ------------------------------------------------ -------------------
Android API 25 及以下:
理论上,最直观的方法是:
1)把绳子掰成几段
2) 检测每件作品何时被/正在被说出来
3) 相应地突出显示该部分
然而,不幸的是,当使用实时生成语音输出的 Android TextToSpeech 类时,您能够精确检测(使用 UtteranceProgressListener)进度的最小语音单位是一个话语(您决定发送的任何字符串)到 TTS)——不一定是一个词。
没有任何机制可以让您简单地将多字串作为话语发送,然后以某种方式准确检测每个单词何时被说出。
因此,为了(轻松)按顺序突出显示每个单词,您必须:
A) 将每个单词作为单个话语单独发送到 TTS(但这会导致发音不连贯),或
B) 而是逐句突出显示,将每个句子作为一个话语发送(最简单的方法,但不是您想要的行为)。
如果你真的坚持要实现逐字高亮效果,我能想到的唯一方法(使用 Android TextToSpeech)是使用句子大小的话语,但不是使用 speak(),而是使用 synthesizeToFile()...和然后使用某种媒体播放器或声音播放器播放语音……以某种方式根据第 n 个单词相对于总音频文件长度的位置来近似高光的时间。因此,例如,如果句子长度为 10 个单词,并且文件已完成 30%,那么您将突出显示第 4 个单词。这将是困难和不准确的,但在理论上是可能的。
显然已经有一些应用程序和游戏可以做到这一点……像说唱歌手帕拉帕这样的游戏,或者卡拉 OK 应用程序,但我认为他们这样做的方式是预先录制/静态音频文件,并在准确的时间编码标记触发亮点。如果您的文本内容总是相同的,并且只有一种语言,那么您也可以这样做。
但是,如果语音文本是用户输入的或在运行时之前未知,需要 TTS,那么我不知道任何直接的解决方案。
如果您决定采用这些更狭窄的方法之一,那么我建议相应地发布一个新问题。
| 归档时间: |
|
| 查看次数: |
1808 次 |
| 最近记录: |