文字转语音中断

Text To Speech breaks

我正在使用这个代码说话

   Sample 1:

    speech.speak("Hello ABCD WELCOME ABCD", TextToSpeech.QUEUE_FLUSH,
                                        null);

如果代码按照示例 1 中所示的顺序排列,则此代码没有问题。如果我将其分成两个字符串,如示例 2 中所示,它会破坏说话,因为它只说 hell 或 hello 然后说欢迎abcd.

    Sample 2:

    speech.speak("Hello ABCD", TextToSpeech.QUEUE_FLUSH,
                                        null);
    speech.speak("Welcome ABCD", TextToSpeech.QUEUE_FLUSH,
                                        null);

我想要如果 speech.isSpeaking(),那么它应该等待完成 HELLO ABCD,完成后它应该说 WELCOME ABCD。

在 hashmap 或 arraylist 中使用字符串的替代方法。还有其他解决办法吗?

我以前没试过TextToSpeech,但是看到你做的代码是一个接一个运行,第二个speech.speak()值会超过运行第一个作为您设置的队列代码是 TextToSpeech.QUEUE_FLUSH。根据它的文档:

Queue mode where all entries in the playback queue (media to be played and text to be synthesized) are dropped and replaced by the new entry.

所以我觉得适合你用的是TextToSpeech.QUEUE_ADD:

Queue mode where the new entry is added at the end of the playback queue.

有几个选项。有些人有自己的注意事项。

首先,您可以使用 TextToSpeech.QUEUE_ADD 而不是 TextToSpeech.QUEUE_FLUSH

speech.speak("Hello ABCD", TextToSpeech.QUEUE_ADD, null);

speech.speak("Welcome ABCD", TextToSpeech.QUEUE_ADD, null);

这会将任何新文本添加到队列中,但会在开始说出任何新文本之前完全说出已经存在的内容。如果您不经常向队列中添加新文本,这很好。否则队列可能会变得太满,而 TTS 引擎的通话速度不够快,无法跟上。

你可以使用 speech.isSpeaking() 但如何巧妙地使用它呢?循环等待不是很好的编程:

speech.speak("Hello ABCD", TextToSpeech.QUEUE_FLUSH, null);

while (speech.isSpeaking()) {
    // Freezes the application. 
}

speech.speak("Welcome ABCD", TextToSpeech.QUEUE_FLUSH, null);

这在后台线程中还可以,但最好完全忘记这个想法。

也可以使用 UtteranceProgressListener 在 "utterance" 完成时得到通知——基本上是在 speak() 方法调用中给出的文本被说出时。这可能是一种聪明的方式,只有在之前的文本完全说完之后才开始说出新的文本。

监听器可以添加为匿名内部 class:

speech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
            // Speaking started. 

        }

        @Override
        public void onDone(String utteranceId) {
            // Speaking stopped.

        }

        @Override
        public void onError(String utteranceId) {
            // There was an error.
        }
    });

监听器不是很有用,除非在 speak() 方法调用中给出 utteranceId。否则您将无法确切知道说出了哪些文本以及接下来应该说出的内容。当然,您可以使用自己的一些成员变量来跟踪它,但是已经为您提供了一个内置机制:

speech.speak("Hello ABCD", TextToSpeech.QUEUE_ADD, "hello");

现在这个 speak() 操作被识别为 "hello"。只有在 "Hello ABCD" 被说出来后,我们才能用这个来说 "Welcome ABCD":

speech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
        @Override
        public void onStart(String utteranceId) {
            // Speaking started. 

        }

        @Override
        public void onDone(String utteranceId) {
            // Speaking stopped.

            if (utteranceId.equals("hello")) {
                speech.speak("Welcome ABCD", TextToSpeech.QUEUE_ADD, "welcome");        
            }

        }

        @Override
        public void onError(String utteranceId) {
            // There was an error.
        }
    });

听者当然应该在说任何话之前设置好。

这是基本思想,您是否应该使用 UtteranceProgressListener 取决于您正在开发的应用程序类型。如果有很多 "utterances" 需要发言和监控,它确实会变得有点复杂。如果您发现 TTS 队列填满的问题,您可以研究这种方法。

当然,如果您的文本位于 ArrayList 中,并且您使用文本的索引作为话语 ID,并在听众中选择要说出的下一个文本,那么这当然可以以更智能的方式进行基于索引。