import 'dart:async'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import '../../../data/services/asr_service.dart'; import '../../../data/services/tts_service.dart'; import '../../../data/services/speech_factory.dart'; import '../../../core/utils/logger.dart'; /// 语音测试控制器 class SpeechTestController extends GetxController { // 语音服务工厂 final SpeechFactory _speechFactory = Get.find(); // 当前使用的TTS服务 late TtsService _ttsService; // 当前使用的ASR服务 late AsrService _asrService; // 状态变量 final RxBool isInitialized = false.obs; final RxBool isProcessing = false.obs; final RxBool isListening = false.obs; final RxBool isSpeaking = false.obs; // 识别结果 final RxString intermediateResult = ''.obs; // 中间结果 final RxString finalResult = ''.obs; // 最终结果 final RxString recognitionStatus = '准备就绪'.obs; final RxString detectedLanguage = ''.obs; // 检测到的语言 // TTS事件 final RxString ttsStatus = '准备就绪'.obs; // 当前选择的语音服务类型 final Rx selectedServiceType = SpeechServiceType.azure.obs; // 音频输入源 bool _audioSourceType = false; // 连续识别结果流 StreamSubscription? _recognitionSubscription; // TTS事件流 StreamSubscription? _ttsEventSubscription; // 文本控制器 final TextEditingController textController = TextEditingController(); // 连续播放的测试句子 final List testSentences = [ '这是第一句测试语音。', '这是第二句测试语音,语音合成支持连续播放。', '这是第三句测试语音,将在连续模式下播放完毕。' ]; @override void onInit() { super.onInit(); // 设置默认待播放文本 textController.text = '欢迎使用语音测试,这是一段默认的测试文本。您可以修改此文本,然后点击播放按钮测试语音合成效果。'; _initServices(); } /// 初始化服务 Future _initServices() async { try { isProcessing.value = true; // 获取服务实例 _ttsService = _speechFactory.getTtsService(); _asrService = _speechFactory.getAsrService(); // 初始化服务 await _ttsService.initialize(); await _asrService.initialize(); // 监听TTS事件 _setupTtsEventListener(); // 获取识别事件流 - 这启动了异步识别过程 final stream = await _asrService.recognizeCallback(); // 设置事件监听 - 异步处理识别结果 _setupAsrEventListener(stream); isInitialized.value = true; ttsStatus.value = '准备就绪'; recognitionStatus.value = '准备就绪'; } catch (e) { ttsStatus.value = '初始化失败'; recognitionStatus.value = '初始化失败'; Logger.error('语音测试初始化失败: ${e.toString()}'); } finally { isProcessing.value = false; } } /// 设置TTS事件监听 void _setupTtsEventListener() { // 取消旧的订阅 _ttsEventSubscription?.cancel(); // 设置新的订阅 _ttsEventSubscription = _ttsService.onEvent.listen((event) { switch (event.type) { case TtsEventType.started: isSpeaking.value = true; ttsStatus.value = '正在播放...'; break; case TtsEventType.completed: isSpeaking.value = false; ttsStatus.value = '播放完成'; break; case TtsEventType.canceled: isSpeaking.value = false; ttsStatus.value = '播放已取消'; break; case TtsEventType.error: isSpeaking.value = false; ttsStatus.value = '播放错误: ${event.error}'; break; } }); } /// 设置ASR事件监听 void _setupAsrEventListener(Stream stream) { // 取消旧的订阅 _recognitionSubscription?.cancel(); // 重置识别结果 intermediateResult.value = ''; finalResult.value = ''; detectedLanguage.value = ''; recognitionStatus.value = '正在等待语音输入...'; // 设置新的订阅 _recognitionSubscription = stream.listen((event) { switch (event.type) { case RecognitionEventType.sessionStarted: isListening.value = true; recognitionStatus.value = '开始聆听...'; break; case RecognitionEventType.sessionStopped: isListening.value = false; recognitionStatus.value = '聆听已结束'; // 清空中间结果,保留最终结果 intermediateResult.value = ''; break; case RecognitionEventType.intermediateResult: // 更新中间结果,显示为斜体或不同颜色 intermediateResult.value = event.text; if (event.detectedLanguage.isNotEmpty) { detectedLanguage.value = event.detectedLanguage; } recognitionStatus.value = '正在识别...'; break; case RecognitionEventType.finalResult: // 更新最终结果,显示为正常文本 finalResult.value = event.text; intermediateResult.value = ''; // 清空中间结果 if (event.detectedLanguage.isNotEmpty) { detectedLanguage.value = event.detectedLanguage; } recognitionStatus.value = '识别完成'; break; case RecognitionEventType.error: isListening.value = false; recognitionStatus.value = '识别错误: ${event.error}'; break; case RecognitionEventType.canceled: isListening.value = false; recognitionStatus.value = '识别已取消'; // 清空中间结果 intermediateResult.value = ''; break; case RecognitionEventType.onAudio: // TODO: Handle this case. break; } }, onError: (error) { isListening.value = false; recognitionStatus.value = '识别错误: $error'; intermediateResult.value = ''; }); } /// 切换语音服务类型 void switchServiceType(SpeechServiceType type) async { if (selectedServiceType.value == type) return; try { isProcessing.value = true; // 停止当前的所有服务状态 await stopAll(); // 切换服务类型 _speechFactory.setServiceType(type); selectedServiceType.value = type; // 重新初始化服务 await _initServices(); } catch (e) { Logger.error('切换语音服务类型失败: ${e.toString()}'); } finally { isProcessing.value = false; } } /// 停止所有活动 Future stopAll() async { // 停止ASR if (isListening.value) { await stopContinuousRecognition(); } // 停止TTS if (isSpeaking.value) { await stopSpeaking(); } // 取消所有订阅 await _recognitionSubscription?.cancel(); _recognitionSubscription = null; } /// 单次播放文本 Future speakOnce() async { if (!isInitialized.value || isProcessing.value) return; final text = textController.text.trim(); if (text.isEmpty) { ttsStatus.value = '请输入要播放的文本'; return; } try { isProcessing.value = true; ttsStatus.value = '准备播放...'; final result = await _ttsService.speakOnce(text); if (!result) { ttsStatus.value = '播放失败'; } } catch (e) { ttsStatus.value = '播放异常: $e'; Logger.error('单次播放异常: ${e.toString()}'); } finally { isProcessing.value = false; } } /// 连续播放测试 Future speakContinuously() async { if (!isInitialized.value || isProcessing.value) return; try { isProcessing.value = true; ttsStatus.value = '准备连续播放...'; // 为避免阻塞,使用一个句子接一个句子的方式添加到队列 for (final sentence in testSentences) { if (!await _ttsService.speakStream(sentence)) { ttsStatus.value = '添加句子到队列失败'; break; } // 给前一个句子一点处理时间 await Future.delayed(const Duration(milliseconds: 50)); } // 刷新队列,确保播放完成 await _ttsService.flushStream(); } catch (e) { ttsStatus.value = '连续播放异常: $e'; Logger.error('连续播放异常: ${e.toString()}'); } finally { isProcessing.value = false; } } /// 停止播放 Future stopSpeaking() async { if (!isInitialized.value) return; try { await _ttsService.stop(); } catch (e) { ttsStatus.value = '停止播放异常: $e'; Logger.error('停止播放异常: ${e.toString()}'); } } /// 一次性识别 Future recognizeOnce() async { if (!isInitialized.value || isProcessing.value || isListening.value) return; try { isProcessing.value = true; recognitionStatus.value = '开始识别...'; // 清空之前的结果 intermediateResult.value = ''; finalResult.value = ''; detectedLanguage.value = ''; // 显示正在进行的状态 recognitionStatus.value = '正在聆听...'; // 执行一次性识别 - 这是同步等待结果的操作 final result = await _asrService.recognizeOnce(); if (result.isError) { recognitionStatus.value = '识别错误: ${result.error}'; Logger.error('一次性识别错误: ${result.error}'); } else { // 更新最终结果 finalResult.value = result.text; // 更新语言信息 if (result.detectedLanguage.isNotEmpty) { detectedLanguage.value = result.detectedLanguage; Logger.debug('检测到语言: ${result.detectedLanguage}'); } recognitionStatus.value = '识别完成'; } } catch (e) { recognitionStatus.value = '识别异常: $e'; Logger.error('一次性识别异常: ${e.toString()}'); } finally { isProcessing.value = false; } } /// 开始连续识别 Future startContinuousRecognition() async { if (!isInitialized.value || isProcessing.value || isListening.value) return; try { isProcessing.value = true; // 清空之前的结果 intermediateResult.value = ''; finalResult.value = ''; detectedLanguage.value = ''; recognitionStatus.value = '准备连续识别...'; // 获取识别事件流 - 这启动了异步识别过程 final stream = await _asrService.startContinuousRecognition(_audioSourceType); } catch (e) { recognitionStatus.value = '启动连续识别异常: $e'; Logger.error('启动连续识别异常: ${e.toString()}'); isListening.value = false; intermediateResult.value = ''; finalResult.value = ''; } finally { isProcessing.value = false; } } /// 停止连续识别 Future stopContinuousRecognition() async { if (!isInitialized.value || !isListening.value) return; try { // 首先更新状态,防止重复调用 isListening.value = false; recognitionStatus.value = '正在停止识别...'; // 停止识别过程 await _asrService.stopContinuousRecognition(); // 更新UI状态 recognitionStatus.value = '连续识别已停止'; intermediateResult.value = ''; } catch (e) { recognitionStatus.value = '停止连续识别异常: $e'; Logger.error('停止连续识别异常: ${e.toString()}'); } } // 获取识别结果(用于UI显示) String getDisplayResult() { // 如果有最终结果,优先显示 String displayText = ''; if (finalResult.value.isNotEmpty) { displayText = finalResult.value; } // 如果有中间结果,添加到最终结果后(可在UI中使用不同样式显示) if (intermediateResult.value.isNotEmpty) { if (displayText.isNotEmpty) { displayText = '$displayText\n\n正在识别: ${intermediateResult.value}'; } else { displayText = '正在识别: ${intermediateResult.value}'; } } return displayText; } @override void onClose() { // 取消所有订阅 _recognitionSubscription?.cancel(); _ttsEventSubscription?.cancel(); // 释放控制器 textController.dispose(); super.onClose(); } }