在Android上使用Text-to-Speech时出现问题isSpeaking()

时间:2011-06-19 10:16:53

标签: android text-to-speech

我遇到了isSpeaking()方法的问题。将QUEUE_FLUSH传递给speak()方法时,isSpeaking()工作正常。但是,当我对多个话语进行排队时(通过传递QUEUE_ADD),isSpeaking()方法会在多个话语排队后立即开始返回false

然后我偶然发现了the source code of the TtsService class并看到了这段代码:

public boolean isSpeaking() {
  return (mSelf.mIsSpeaking && (mSpeechQueue.size() < 1));
}

有没有人有任何想法,为什么这种方法以这种方式实施?

2 个答案:

答案 0 :(得分:8)

我偶然发现了这个。

自从你提出这个问题已经过去了一年,没有答案可以解决......

所以我只能猜到编写这段代码的人意图表示

  

只有在说出最后话语时才会这样做。

这有意义吗?

唯一的问题是,无论是QUEUE_ADD还是QUEUE_FLUSH模式,经验观察都表明存在严重的时间竞争条件:

    如果在isSpeaking()中调用,
  1. onUtteranceCompleted()将始终返回 false
  2. isSpeaking()将始终返回 true ,如果在tts.speak()之后第一次 onUtteranceCompleted()之后立即调用。
  3. isSpeaking()将始终返回 false ,如果在tts.speak()之后立即调用,tts.speak()之间至少再有onUtteranceCompleted()个{{1}}在最后{{1}}之间分隔和它本身。
  4. 在某种程度上,它的行为完全与“预期”相反:

      

    仅在说出第一个话语”时(在 onUtteranceCompleted()之后)

    为什么它表现得像这样超出了我,但这至少是LogCat所展示的。

    另请注意official documentation的以下内容:

      

    请注意,一旦语音项目的音频数据被认为是完整的   已被发送到音频混音器,或写入文件。可能有   此点之间以及音频硬件完成时的有限延迟   回放。

    换句话说,这种方法完全没用。

答案 1 :(得分:4)

队列完成时有广播意图:ACTION_TTS_QUEUE_PROCESSING_COMPLETED。

这是一个注册BroadCastReceiver并使用它来确定isSpeaking状态的示例类。

从您活动的相关位置呼叫初始化和关闭,并使用此课程中提供的Speak和isSpeaking功能:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;

public class SpeechWrapper {

private static TextToSpeech mTts = null;        
private static boolean isSpeaking = false;
private static BroadcastReceiver receiver = new BroadcastReceiver(){
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED) && mTts != null)
        {
            isSpeaking = false;
        }
    }
};

private static void Speak(String sMessage, int intQueueType, int delay) {
    if (mTts == null || sMessage == null) return;
    sMessage = sMessage.trim();
    isSpeaking = true;
    if (delay > 0) {
        mTts.playSilence(delay, intQueueType, null);
        intQueueType = TextToSpeech.QUEUE_ADD;
    }
    mTts.speak(sMessage, intQueueType, null);
}

public static void Init(Context context) {
    mTts = new TextToSpeech(context, (OnInitListener) context);
    IntentFilter filter = new IntentFilter(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED);
    context.registerReceiver(receiver, filter);
}

public static void Shutdown() {
    if (mTts != null) {
        mTts.stop();
        mTts.shutdown();
    }
}

public static boolean isSpeaking() {
    return isSpeaking;
}

}