DialogFlow Android SDK:实现监听等待TTS语音播放完成后恢复
解决DialogFlow监听与TTS播放冲突的问题
嘿,这个问题我之前做语音机器人时也碰到过!核心问题就是你现在的代码不管TTS有没有说完,直接就恢复监听了,导致机器人自己说话的时候监听已经在等输入,没几秒就超时失效。咱们可以通过监听TTS的播放完成事件,精准控制DialogFlow监听恢复的时机,让对话变得更自然流畅。
具体实现步骤
核心思路是用两个标志位跟踪状态,再配合TTS的播放完成监听器,确保只有机器人说完话后才恢复监听:
isTtsPlaying:标记当前TTS是否正在播放语音shouldResumeListening:标记当TTS结束后是否需要恢复DialogFlow的监听
1. 初始化TTS并设置播放完成监听
private TextToSpeech tts; private boolean isTtsPlaying = false; private boolean shouldResumeListening = false; // 在初始化方法(比如Activity的onCreate)里配置TTS tts = new TextToSpeech(this, status -> { if (status == TextToSpeech.SUCCESS) { // 设置TTS语言(根据你的需求调整) int langResult = tts.setLanguage(Locale.CHINESE); if (langResult == TextToSpeech.LANG_MISSING_DATA || langResult == TextToSpeech.LANG_NOT_SUPPORTED) { Log.e("TTS", "当前设备不支持该语言"); } else { // 设置播放完成监听(Android 21及以上版本可用) tts.setOnPlaybackCompletedListener(utteranceId -> { isTtsPlaying = false; // 如果TTS播放前已经标记需要恢复监听,现在执行 if (shouldResumeListening) { aiService.resume(); shouldResumeListening = false; } }); } } else { Log.e("TTS", "TTS初始化失败"); } });
2. 修改DialogFlow的回调方法,统一处理监听恢复
把原来直接调用aiService.resume()的地方,改成调用自定义方法,先判断TTS状态再决定是否恢复:
@Override public void onListeningCanceled() { resumeListeningAfterTts(); } @Override public void onListeningFinished() { resumeListeningAfterTts(); } @Override public void onError(AIError error) { resumeListeningAfterTts(); } // 自定义方法:根据TTS状态决定是否立即恢复监听 private void resumeListeningAfterTts() { if (isTtsPlaying) { // TTS还在说话,先标记需要在结束后恢复监听 shouldResumeListening = true; } else { // 没有播放,直接恢复监听 aiService.resume(); } }
3. 播放TTS响应时更新状态
当你拿到DialogFlow的文本响应,准备用TTS播放时,记得把isTtsPlaying设为true:
// 播放机器人的响应语音 public void playBotResponse(String responseText) { isTtsPlaying = true; shouldResumeListening = false; // 重置标记,避免旧状态干扰 // 设置utterance ID,方便监听识别(可选但推荐) HashMap<String, String> ttsParams = new HashMap<>(); ttsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "bot_response"); // 播放语音,QUEUE_FLUSH表示立即停止当前播放,开始新的响应 tts.speak(responseText, TextToSpeech.QUEUE_FLUSH, ttsParams, "bot_response"); }
逻辑说明
- 当TTS开始播放时,
isTtsPlaying变为true,此时如果DialogFlow的监听回调触发(比如onListeningFinished),会先把shouldResumeListening设为true,而不是直接恢复监听。 - 当TTS播放完成后,监听器会把
isTtsPlaying设为false,同时检查shouldResumeListening,如果为true就立即恢复DialogFlow的监听。 - 这样就保证了机器人说完话之后,才会再次开始监听用户的输入,完全符合自然对话的逻辑。
额外注意事项
- 记得在页面销毁时释放TTS资源,避免内存泄漏:
tts.shutdown(); - 如果你的App需要支持Android 21以下版本,可以用
OnUtteranceCompletedListener替代OnPlaybackCompletedListener,用法基本一致。 - 如果有多个TTS请求排队,可以根据需求调整
QUEUE_FLUSH或QUEUE_ADD,前者会覆盖当前播放,后者会追加到播放队列。
内容的提问来源于stack exchange,提问作者Ganesh K
相关产品推荐
相关产品推荐

