gpt4 book ai didi

java - 在语音进行时突出显示文本

转载 作者:行者123 更新时间:2023-12-02 01:32:37 25 4
gpt4 key购买 nike

我正在开发一个应用程序,其中 TextView 由字符串和两个按钮组成。当我单击“讲话”按钮时,文本将转换为语音。但我想在语音运行时突出显示该单词

请检查以下链接中的“我的应用程序”屏幕截图。 enter image description here

这是我的文字转语音初始化:

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 中。

最佳答案

对于 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");

}

}

//--------------------------------------------------------- ----------------------

Android API 25 及以下版本:

理论上,实现此目的最直观的方法是:

1) 将字符串分成 fragment

2) 检测每个 fragment 何时被说出/正在被说出

3) 相应地突出显示该 fragment

但是,不幸的是,当使用实时生成语音输出的 Android TextToSpeech 类时,您能够精确检测进度(使用 UtteranceProgressListener)的最小语音单位是话语(无论您决定发送到 TTS 的任何字符串)——不一定是单词。

没有任何机制可以让您简单地将多单词字符串作为话语发送,然后以某种方式准确检测每个单词的说出时间。

因此,为了(轻松)按顺序突出显示每个单词,您必须:

A) 将每个单词作为单个话语单独发送到 TTS(但这会导致发音脱节),或者

B) 逐句突出显示,将每个句子作为一个话语发送(最简单的方法,但不是您想要的行为)。

如果你真的坚持要实现逐字突出显示的效果,我能想到的唯一方法(使用Android TextToSpeech)就是使用句子大小的话语,而不是使用speak (),使用 SynthesizeToFile()...然后使用某种媒体播放器或声音播放器来播放语音...以某种方式根据第 n 个单词相对于总音频的位置来近似突出显示的时间文件长度。例如,如果句子有 10 个单词长,并且文件已完成 30%,那么您将突出显示第 4 个单词。这会很困难且不精确,但理论上是可能的。

显然已经有一些应用程序和游戏可以做到这一点......像Parappa the Rapper这样的游戏,或卡拉OK应用程序,但我认为他们这样做的方式是预先录制/静态音频文件,其标记编码为触发亮点的确切时间。如果您的文本内容始终相同,并且仅使用一种语言,那么您也可以这样做。

但是,如果语音文本是用户输入的或在运行时之前未知,需要 TTS,那么我不知道有任何直接的解决方案。

如果您决定选择其中一种更缩小范围的方法,那么我建议您相应地发布一个新问题。

关于java - 在语音进行时突出显示文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59488998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com