|
|
|
@ -43,96 +43,67 @@ class BackgroundAgentService extends GetxService { |
|
|
|
// 最后一次识别到语音的时间 |
|
|
|
DateTime? _lastSpeechTime; |
|
|
|
|
|
|
|
// 添加一个标志,表示系统是否正在播放 TTS |
|
|
|
bool _isSpeaking = false; |
|
|
|
|
|
|
|
// 添加一个变量来跟踪当前的AI响应流订阅 |
|
|
|
StreamSubscription? _aiResponseSubscription; |
|
|
|
|
|
|
|
// 添加一个标志,表示是否应该取消当前的AI响应 |
|
|
|
bool _shouldCancelAiResponse = false; |
|
|
|
|
|
|
|
// 添加一个变量来跟踪最后一次 TTS 状态变化的时间 |
|
|
|
DateTime? _lastTtsStateChangeTime; |
|
|
|
// 添加计数器,用于跟踪连续无输入的次数 |
|
|
|
int _noSpeechCount = 0; |
|
|
|
|
|
|
|
BackgroundAgentService() |
|
|
|
: _aiService = VolcanoAIService(), |
|
|
|
_ttsService = Get.find<VolcanoTtsService>(), |
|
|
|
_voiceRecognitionService = Get.find<VoiceRecognitionService>() { |
|
|
|
// 不再监听 TTS 播放状态,而是使用定期检查 |
|
|
|
// 初始化 TTS 状态 |
|
|
|
_isSpeaking = _ttsService.isActuallyPlaying(); |
|
|
|
_lastTtsStateChangeTime = DateTime.now(); |
|
|
|
|
|
|
|
// 添加定期检查实际播放状态的计时器 |
|
|
|
Timer.periodic(const Duration(seconds: 1), (timer) { |
|
|
|
// 检查实际播放状态 |
|
|
|
final actuallyPlaying = _ttsService.isActuallyPlaying(); |
|
|
|
|
|
|
|
// 如果状态发生变化,更新状态并记录时间 |
|
|
|
if (_isSpeaking != actuallyPlaying) { |
|
|
|
print('TTS 播放状态变化: $_isSpeaking -> $actuallyPlaying'); |
|
|
|
_isSpeaking = actuallyPlaying; |
|
|
|
_lastTtsStateChangeTime = DateTime.now(); |
|
|
|
|
|
|
|
// 如果 TTS 服务的 isPlaying 与实际状态不一致,尝试修正 |
|
|
|
if (actuallyPlaying != _ttsService.isPlaying.value) { |
|
|
|
// 简化构造函数,不需要定期检查TTS状态 |
|
|
|
} |
|
|
|
|
|
|
|
// 启动无语音超时计时器 |
|
|
|
void _startNoSpeechTimer() { |
|
|
|
// 取消之前的计时器 |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
|
|
|
|
// 设置15秒的超时计时器 |
|
|
|
_noSpeechTimer = Timer(const Duration(seconds: 15), () { |
|
|
|
// 检查TTS是否正在播放 |
|
|
|
bool isTtsPlaying = false; |
|
|
|
try { |
|
|
|
_ttsService.isPlaying.value = actuallyPlaying; |
|
|
|
print('已修正 TTS 服务的播放状态'); |
|
|
|
isTtsPlaying = _ttsService.isActuallyPlaying(); |
|
|
|
} catch (e) { |
|
|
|
print('修正 TTS 播放状态失败: $e'); |
|
|
|
} |
|
|
|
print('检查TTS播放状态失败: $e'); |
|
|
|
isTtsPlaying = false; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果 TTS 停止播放,且正在进行语音识别,重新启动无语音超时计时器 |
|
|
|
if (!actuallyPlaying && _isListening && _hasRecognizedSpeech && _noSpeechTimer == null) { |
|
|
|
if (isTtsPlaying) { |
|
|
|
// 如果TTS正在播放,重置定时器 |
|
|
|
print('TTS正在播放,重置15秒超时计时器'); |
|
|
|
_startNoSpeechTimer(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 如果正在处理交互,进行更全面的检查 |
|
|
|
if (_isProcessing) { |
|
|
|
_checkAndUpdateTtsState(); |
|
|
|
} else { |
|
|
|
// 如果TTS不在播放,且15秒内没有检测到用户输入,退出交互 |
|
|
|
print('15秒内没有检测到用户输入,退出交互'); |
|
|
|
_exitInteraction(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加一个方法来检查和更新 TTS 状态 |
|
|
|
void _checkAndUpdateTtsState() { |
|
|
|
try { |
|
|
|
// 获取实际播放状态 |
|
|
|
final actuallyPlaying = _ttsService.isActuallyPlaying(); |
|
|
|
|
|
|
|
// 如果状态显示正在播放,但已经很长时间没有状态变化,强制重置 |
|
|
|
if (actuallyPlaying && _lastTtsStateChangeTime != null) { |
|
|
|
final now = DateTime.now(); |
|
|
|
final difference = now.difference(_lastTtsStateChangeTime!); |
|
|
|
|
|
|
|
// 如果超过15秒没有状态变化,强制重置 |
|
|
|
if (difference.inSeconds > 15) { |
|
|
|
print('强制重置 TTS 状态:已经 ${difference.inSeconds} 秒没有状态变化'); |
|
|
|
|
|
|
|
try { |
|
|
|
// 停止 TTS 播放 |
|
|
|
_ttsService.stop(); |
|
|
|
|
|
|
|
// 强制更新状态 |
|
|
|
_isSpeaking = false; |
|
|
|
_ttsService.isPlaying.value = false; |
|
|
|
|
|
|
|
// 更新最后状态变化时间 |
|
|
|
_lastTtsStateChangeTime = DateTime.now(); |
|
|
|
|
|
|
|
print('TTS 状态已强制重置'); |
|
|
|
} catch (e) { |
|
|
|
print('强制重置 TTS 状态失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
// 退出交互 |
|
|
|
Future<void> _exitInteraction() async { |
|
|
|
// 完成当前的recognitionCompleter(如果有) |
|
|
|
if (_recognitionCompleter != null && !_recognitionCompleter!.isCompleted) { |
|
|
|
_recognitionCompleter!.complete(''); |
|
|
|
} |
|
|
|
// 设置标志,停止循环交互 |
|
|
|
_shouldContinueInteraction = false; |
|
|
|
_isProcessing = false; |
|
|
|
// 播放退出提示 |
|
|
|
try { |
|
|
|
await _ttsService.speak("没有听到您说话,已退出语音交互"); |
|
|
|
} catch (e) { |
|
|
|
print('检查 TTS 播放状态失败: $e'); |
|
|
|
print('播放退出提示失败: $e'); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 处理蓝牙耳机按钮触发的交互 |
|
|
|
@ -148,11 +119,10 @@ class BackgroundAgentService extends GetxService { |
|
|
|
try { |
|
|
|
// 确保之前的语音识别已经停止 |
|
|
|
if (_isListening) { |
|
|
|
print('交互开始前确保语音识别已停止'); |
|
|
|
await stopVoiceRecognition(); |
|
|
|
} |
|
|
|
|
|
|
|
// 循环进行交互,直到用户 10 秒没有说话或手动停止 |
|
|
|
// 循环进行交互,直到用户 30 秒没有说话或手动停止 |
|
|
|
while (_shouldContinueInteraction) { |
|
|
|
await _processSingleInteraction(systemPrompt); |
|
|
|
} |
|
|
|
@ -164,7 +134,6 @@ class BackgroundAgentService extends GetxService { |
|
|
|
|
|
|
|
// 重置语音识别服务 |
|
|
|
try { |
|
|
|
print('交互结束,重置语音识别服务'); |
|
|
|
await _voiceRecognitionService.initialize(); |
|
|
|
} catch (e) { |
|
|
|
print('重置语音识别服务失败: $e'); |
|
|
|
@ -172,53 +141,6 @@ class BackgroundAgentService extends GetxService { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 启动无语音超时计时器 |
|
|
|
void _startNoSpeechTimer() { |
|
|
|
// 检查 TTS 播放状态,使用 isActuallyPlaying 获取实际状态 |
|
|
|
_isSpeaking = _ttsService.isActuallyPlaying(); |
|
|
|
|
|
|
|
// 如果系统正在播放 TTS,不启动计时器 |
|
|
|
if (_isSpeaking) { |
|
|
|
print('系统正在播放 TTS,不启动无语音超时计时器 (isPlaying.value: ${_ttsService.isPlaying.value}, 实际播放状态: $_isSpeaking)'); |
|
|
|
|
|
|
|
// 即使TTS正在播放,也设置一个更长的安全超时,防止系统永远卡在循环中 |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
_noSpeechTimer = Timer(const Duration(seconds: 30), () { |
|
|
|
// 再次检查 TTS 状态,使用 isActuallyPlaying |
|
|
|
_isSpeaking = _ttsService.isActuallyPlaying(); |
|
|
|
|
|
|
|
print('安全超时触发:即使TTS正在播放,30秒内没有新的语音输入,强制退出循环交互 (实际播放状态: $_isSpeaking)'); |
|
|
|
if (_recognitionCompleter != null && !_recognitionCompleter!.isCompleted) { |
|
|
|
_recognitionCompleter!.complete(''); |
|
|
|
} |
|
|
|
_shouldContinueInteraction = false; |
|
|
|
}); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 取消之前的计时器 |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
|
|
|
|
// 设置新的计时器,如果 10 秒内没有新的识别结果,且系统没有在播放 TTS,则认为用户已经停止交互 |
|
|
|
_noSpeechTimer = Timer(const Duration(seconds: 10), () { |
|
|
|
// 再次检查是否正在播放 TTS,使用 isActuallyPlaying |
|
|
|
_isSpeaking = _ttsService.isActuallyPlaying(); |
|
|
|
|
|
|
|
print('无语音超时计时器触发,当前 TTS 播放状态: $_isSpeaking (isPlaying.value: ${_ttsService.isPlaying.value}, 实际播放状态: $_isSpeaking)'); |
|
|
|
|
|
|
|
if (!_isSpeaking && _isListening && _recognitionCompleter != null && !_recognitionCompleter!.isCompleted) { |
|
|
|
print('10秒内没有新的语音输入,且系统没有在播放 TTS,退出循环交互'); |
|
|
|
_recognitionCompleter!.complete(''); |
|
|
|
|
|
|
|
// 直接设置标志,停止循环交互 |
|
|
|
_shouldContinueInteraction = false; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
print('启动无语音超时计时器,10秒后检查'); |
|
|
|
} |
|
|
|
|
|
|
|
// 处理单次交互 |
|
|
|
Future<void> _processSingleInteraction(String systemPrompt) async { |
|
|
|
_isProcessing = true; |
|
|
|
@ -226,9 +148,6 @@ class BackgroundAgentService extends GetxService { |
|
|
|
_hasFinalResult = false; |
|
|
|
|
|
|
|
try { |
|
|
|
// 强制重置 TTS 状态,确保不会因为错误的状态导致系统卡住 |
|
|
|
_resetTtsStateIfNeeded(); |
|
|
|
|
|
|
|
// 先播放一个简短的提示音或提示语,表示开始监听 |
|
|
|
try { |
|
|
|
await _ttsService.speak("我在听"); |
|
|
|
@ -238,19 +157,16 @@ class BackgroundAgentService extends GetxService { |
|
|
|
} |
|
|
|
|
|
|
|
// 开始语音识别 |
|
|
|
bool recognitionStarted = false; |
|
|
|
String userInput = ''; |
|
|
|
|
|
|
|
try { |
|
|
|
// 确保之前的语音识别已经停止 |
|
|
|
if (_isListening) { |
|
|
|
print('检测到上一次语音识别未正确停止,先停止它'); |
|
|
|
await stopVoiceRecognition(); |
|
|
|
} |
|
|
|
|
|
|
|
// 尝试启动语音识别 |
|
|
|
await startVoiceRecognition(); |
|
|
|
recognitionStarted = true; |
|
|
|
|
|
|
|
// 创建一个 Completer 来处理语音识别完成 |
|
|
|
_recognitionCompleter = Completer<String>(); |
|
|
|
@ -265,55 +181,20 @@ class BackgroundAgentService extends GetxService { |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
_noSpeechTimer = null; |
|
|
|
|
|
|
|
// 如果没有识别到语音,则停止循环交互 |
|
|
|
if (!_hasRecognizedSpeech || userInput.trim().isEmpty) { |
|
|
|
print('没有识别到用户语音或识别结果为空,退出循环交互'); |
|
|
|
|
|
|
|
// 停止语音识别 |
|
|
|
if (_isListening) { |
|
|
|
await stopVoiceRecognition(); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
await _ttsService.speak("没有听到您说话,已退出语音交互"); |
|
|
|
} catch (e) { |
|
|
|
print('播放退出提示失败: $e'); |
|
|
|
} |
|
|
|
|
|
|
|
// 设置标志,停止循环交互 |
|
|
|
_shouldContinueInteraction = false; |
|
|
|
_isProcessing = false; |
|
|
|
// 如果用户输入为空,重新启动超时计时器并返回 |
|
|
|
if (userInput.trim().isEmpty) { |
|
|
|
_startNoSpeechTimer(); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 注意:不再停止语音识别,保持语音识别状态 |
|
|
|
// 只有在退出交互时才停止语音识别 |
|
|
|
} catch (e) { |
|
|
|
print('语音识别过程出错: $e'); |
|
|
|
|
|
|
|
_startNoSpeechTimer(); // 出错时也启动超时计时器 |
|
|
|
return; |
|
|
|
} finally { |
|
|
|
// 清理资源,但保持语音识别状态 |
|
|
|
_recognitionCompleter = null; |
|
|
|
_silenceTimer?.cancel(); |
|
|
|
_silenceTimer = null; |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
_noSpeechTimer = null; |
|
|
|
} |
|
|
|
|
|
|
|
if (userInput.isEmpty) { |
|
|
|
try { |
|
|
|
await _ttsService.speak("没有听到您说话"); |
|
|
|
} catch (_) {} |
|
|
|
|
|
|
|
// 如果没有识别到语音,停止循环交互 |
|
|
|
_shouldContinueInteraction = false; |
|
|
|
_isProcessing = false; |
|
|
|
|
|
|
|
// 停止语音识别 |
|
|
|
if (_isListening) { |
|
|
|
await stopVoiceRecognition(); |
|
|
|
} |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 保存用户消息到历史记录 |
|
|
|
@ -329,7 +210,6 @@ class BackgroundAgentService extends GetxService { |
|
|
|
{'role': 'user', 'content': userInput}, |
|
|
|
]; |
|
|
|
|
|
|
|
|
|
|
|
String fullResponse = ''; |
|
|
|
try { |
|
|
|
// 重置取消标志 |
|
|
|
@ -391,6 +271,9 @@ class BackgroundAgentService extends GetxService { |
|
|
|
} |
|
|
|
_pendingTtsText = ''; |
|
|
|
_aiResponseSubscription = null; |
|
|
|
|
|
|
|
// AI响应完成后,重新启动超时计时器 |
|
|
|
_startNoSpeechTimer(); |
|
|
|
} |
|
|
|
); |
|
|
|
|
|
|
|
@ -401,6 +284,14 @@ class BackgroundAgentService extends GetxService { |
|
|
|
print('AI响应生成失败: $e'); |
|
|
|
// 如果AI响应失败,使用默认回复 |
|
|
|
fullResponse = '抱歉,我现在无法回答您的问题。请稍后再试。'; |
|
|
|
|
|
|
|
// 播放错误提示 |
|
|
|
try { |
|
|
|
await _ttsService.speak(fullResponse); |
|
|
|
} catch (_) {} |
|
|
|
|
|
|
|
// 启动超时计时器 |
|
|
|
_startNoSpeechTimer(); |
|
|
|
} finally { |
|
|
|
// 清理资源 |
|
|
|
_aiResponseSubscription?.cancel(); |
|
|
|
@ -423,11 +314,8 @@ class BackgroundAgentService extends GetxService { |
|
|
|
_messageHistory.removeRange(0, _messageHistory.length - 20); |
|
|
|
} |
|
|
|
|
|
|
|
// 短暂暂停,然后开始下一轮交互 |
|
|
|
await Future.delayed(const Duration(milliseconds: 500)); |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
print('Background agent interaction failed: $e'); |
|
|
|
print('交互过程出错: $e'); |
|
|
|
try { |
|
|
|
await _ttsService.speak("抱歉,出现了一些问题"); |
|
|
|
} catch (_) {} |
|
|
|
@ -448,14 +336,12 @@ class BackgroundAgentService extends GetxService { |
|
|
|
// 开始语音识别 |
|
|
|
Future<void> startVoiceRecognition() async { |
|
|
|
if (_isListening) { |
|
|
|
print('已经在监听中,先停止当前监听'); |
|
|
|
await stopVoiceRecognition(); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
// 确保语音识别服务已初始化 |
|
|
|
if (!await _voiceRecognitionService.initialize()) { |
|
|
|
print('语音识别服务初始化失败,尝试重新初始化'); |
|
|
|
// 尝试重新初始化 |
|
|
|
await Future.delayed(const Duration(milliseconds: 500)); |
|
|
|
if (!await _voiceRecognitionService.initialize()) { |
|
|
|
@ -483,32 +369,38 @@ class BackgroundAgentService extends GetxService { |
|
|
|
|
|
|
|
// 收到最终结果,立即完成识别过程 |
|
|
|
if (_recognitionCompleter != null && !_recognitionCompleter!.isCompleted) { |
|
|
|
print('收到最终识别结果,立即处理: ${event.text}'); |
|
|
|
_recognitionCompleter!.complete(event.text); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 如果最终结果为空,但之前有中间结果,仍然标记为有语音 |
|
|
|
if (_hasRecognizedSpeech) { |
|
|
|
print('最终识别结果为空,但之前有中间结果,使用最后的中间结果'); |
|
|
|
// 如果最终结果为空,但有中间结果,使用最后的中间结果 |
|
|
|
if (_hasRecognizedSpeech && recognizedText.value.isNotEmpty) { |
|
|
|
if (_recognitionCompleter != null && !_recognitionCompleter!.isCompleted) { |
|
|
|
_recognitionCompleter!.complete(recognizedText.value); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// 如果最终结果为空,且没有中间结果,重新启动无语音超时计时器 |
|
|
|
print('最终识别结果为空,且没有中间结果,重新启动无语音超时计时器'); |
|
|
|
// 如果最终结果为空,且没有中间结果,重新启动超时计时器 |
|
|
|
_startNoSpeechTimer(); |
|
|
|
} |
|
|
|
} |
|
|
|
print('最终识别结果: ${event.text}'); |
|
|
|
} else if (event.type == RecognitionEventType.intermediateResult) { |
|
|
|
recognizedText.value = event.text; |
|
|
|
if (event.text.isNotEmpty) { |
|
|
|
_hasRecognizedSpeech = true; |
|
|
|
_lastSpeechTime = DateTime.now(); |
|
|
|
|
|
|
|
// 检测到用户说话,重置无语音计时器 |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
_startNoSpeechTimer(); |
|
|
|
|
|
|
|
// 如果系统正在播放TTS或接收AI响应,检测到用户开始说话时立即中断 |
|
|
|
if (_isSpeaking && event.text.trim().isNotEmpty) { |
|
|
|
print('检测到用户开始说话,中断TTS播放和AI响应'); |
|
|
|
bool isTtsPlaying = false; |
|
|
|
try { |
|
|
|
isTtsPlaying = _ttsService.isActuallyPlaying(); |
|
|
|
} catch (e) { |
|
|
|
isTtsPlaying = false; |
|
|
|
} |
|
|
|
|
|
|
|
if (isTtsPlaying && event.text.trim().isNotEmpty) { |
|
|
|
_ttsService.stop(); // 停止当前TTS播放 |
|
|
|
|
|
|
|
// 设置标志,表示应该取消当前的AI响应 |
|
|
|
@ -525,7 +417,7 @@ class BackgroundAgentService extends GetxService { |
|
|
|
// 取消之前的静默计时器 |
|
|
|
_silenceTimer?.cancel(); |
|
|
|
|
|
|
|
// 取消之前的无语音超时计时器 |
|
|
|
// 取消之前的无语音超时计时器,用户正在说话 |
|
|
|
_noSpeechTimer?.cancel(); |
|
|
|
_noSpeechTimer = null; |
|
|
|
|
|
|
|
@ -533,12 +425,10 @@ class BackgroundAgentService extends GetxService { |
|
|
|
_silenceTimer = Timer(const Duration(seconds: 2), () { |
|
|
|
if (_hasRecognizedSpeech && !_hasFinalResult && |
|
|
|
_recognitionCompleter != null && !_recognitionCompleter!.isCompleted) { |
|
|
|
print('用户停止说话 2 秒,使用当前识别结果: ${recognizedText.value}'); |
|
|
|
_recognitionCompleter!.complete(recognizedText.value); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
print('中间识别结果: ${event.text}'); |
|
|
|
} else if (event.type == RecognitionEventType.error) { |
|
|
|
print('识别错误: ${event.error}'); |
|
|
|
} |
|
|
|
@ -563,11 +453,11 @@ class BackgroundAgentService extends GetxService { |
|
|
|
|
|
|
|
// 停止语音识别并返回识别的文本 |
|
|
|
Future<String> stopVoiceRecognition() async { |
|
|
|
if (!_isListening) return ''; |
|
|
|
if (!_isListening) { |
|
|
|
return ''; |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
print('停止语音识别...'); |
|
|
|
|
|
|
|
// 取消静默计时器 |
|
|
|
_silenceTimer?.cancel(); |
|
|
|
_silenceTimer = null; |
|
|
|
@ -590,7 +480,6 @@ class BackgroundAgentService extends GetxService { |
|
|
|
_isListening = false; |
|
|
|
isListening.value = false; |
|
|
|
|
|
|
|
print('语音识别已停止'); |
|
|
|
return result; |
|
|
|
} catch (e) { |
|
|
|
print('停止语音识别失败: $e'); |
|
|
|
@ -600,7 +489,9 @@ class BackgroundAgentService extends GetxService { |
|
|
|
// 尝试强制重置语音识别服务 |
|
|
|
try { |
|
|
|
await _voiceRecognitionService.initialize(); |
|
|
|
} catch (_) {} |
|
|
|
} catch (e) { |
|
|
|
print('强制重置语音识别服务失败: $e'); |
|
|
|
} |
|
|
|
|
|
|
|
return recognizedText.value; // 返回当前已识别的文本 |
|
|
|
} |
|
|
|
@ -634,38 +525,4 @@ class BackgroundAgentService extends GetxService { |
|
|
|
_shouldContinueInteraction = false; |
|
|
|
super.onClose(); |
|
|
|
} |
|
|
|
|
|
|
|
// 添加一个方法来强制重置 TTS 状态 |
|
|
|
void _resetTtsStateIfNeeded() { |
|
|
|
// 检查 TTS 状态,使用 isActuallyPlaying 获取实际状态 |
|
|
|
bool isCurrentlyPlaying = false; |
|
|
|
try { |
|
|
|
isCurrentlyPlaying = _ttsService.isActuallyPlaying(); |
|
|
|
} catch (e) { |
|
|
|
print('获取实际播放状态失败: $e'); |
|
|
|
isCurrentlyPlaying = _ttsService.isPlaying.value; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果实际状态与当前状态不一致,更新它 |
|
|
|
if (_isSpeaking != isCurrentlyPlaying) { |
|
|
|
print('重置前检测到 TTS 播放状态不一致,修正: _isSpeaking=$_isSpeaking, 实际=${isCurrentlyPlaying}'); |
|
|
|
_isSpeaking = isCurrentlyPlaying; |
|
|
|
|
|
|
|
// 如果实际状态与 TTS 服务的 isPlaying 不一致,尝试修正 TTS 服务的状态 |
|
|
|
if (isCurrentlyPlaying != _ttsService.isPlaying.value) { |
|
|
|
try { |
|
|
|
_ttsService.isPlaying.value = isCurrentlyPlaying; |
|
|
|
print('已修正 TTS 服务的播放状态'); |
|
|
|
} catch (e) { |
|
|
|
print('修正 TTS 播放状态失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 更新最后一次状态变化的时间 |
|
|
|
_lastTtsStateChangeTime = DateTime.now(); |
|
|
|
} |
|
|
|
|
|
|
|
// 检查是否需要强制重置 |
|
|
|
_checkAndUpdateTtsState(); |
|
|
|
} |
|
|
|
} |