import 'dart:async'; import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'dart:developer' as developer; /// 火山语音识别服务 /// 负责与原生层的火山语音识别引擎交互 class VoiceRecognitionService extends GetxService { // 方法通道,用于调用原生方法 static const MethodChannel _methodChannel = MethodChannel('com.example.deep_voice/speech_recognition'); // 事件通道,用于接收原生层的事件 static const EventChannel _eventChannel = EventChannel('com.example.deep_voice/speech_recognition_events'); // 状态变量 final isInitialized = false.obs; final isListening = false.obs; final isConnecting = true.obs; // 识别结果 final recognizedText = ''.obs; // 回调函数 Function(String)? onRecognitionResult; Function(String)? onError; Function()? onRecognitionComplete; Function(String)? onConnectionStatusChanged; Function(String)? onSentenceComplete; // 事件流订阅 StreamSubscription? _eventSubscription; // 火山语音识别的 AppKey 和 AccessKey late final String _appKey; late final String _accessKey; late final String _cluster; @override void onInit() { developer.log('VoiceRecognitionService: 初始化服务', name: 'VoiceRecognition'); super.onInit(); _loadCredentials(); _setupEventListener(); } /// 加载火山语音识别的凭证 void _loadCredentials() { try { _appKey = dotenv.env['VOLC_SPEECH_APP_KEY'] ?? ''; _accessKey = dotenv.env['VOLC_SPEECH_ACCESS_KEY'] ?? ''; _cluster = dotenv.env['VOLC_SPEECH_CLUSTER'] ?? 'volcano_asr'; developer.log('VoiceRecognitionService: 加载凭证 - AppKey: ${_appKey.isNotEmpty ? '已设置' : '未设置'}, AccessKey: ${_accessKey.isNotEmpty ? '已设置' : '未设置'}, Cluster: $_cluster', name: 'VoiceRecognition'); if (_appKey.isEmpty || _accessKey.isEmpty) { developer.log('VoiceRecognitionService: 警告 - 火山语音识别凭证未设置,请在 .env 文件中设置 VOLC_SPEECH_APP_KEY 和 VOLC_SPEECH_ACCESS_KEY', name: 'VoiceRecognition'); } } catch (e, stack) { developer.log('VoiceRecognitionService: 加载火山语音识别凭证失败: $e', name: 'VoiceRecognition'); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); } } /// 设置事件监听器 void _setupEventListener() { try { developer.log('VoiceRecognitionService: 设置事件监听器', name: 'VoiceRecognition'); _eventSubscription = _eventChannel.receiveBroadcastStream().listen( (dynamic event) { _handleEvent(event.toString()); }, onError: (dynamic error) { developer.log('VoiceRecognitionService: 事件通道错误: $error', name: 'VoiceRecognition'); if (onError != null) { onError!('事件通道错误: $error'); } }, ); } catch (e, stack) { developer.log('VoiceRecognitionService: 设置事件监听器失败: $e', name: 'VoiceRecognition'); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); } } /// 处理来自原生层的事件 void _handleEvent(String eventJson) { try { developer.log('VoiceRecognitionService: 收到原始事件数据: $eventJson', name: 'VoiceRecognition'); final eventData = jsonDecode(eventJson); final eventName = eventData['event']; final data = eventData['data']; developer.log('VoiceRecognitionService: 收到事件: $eventName, 数据: $data', name: 'VoiceRecognition'); switch (eventName) { case 'status': _handleStatusEvent(data.toString()); break; case 'result': _handleResultEvent(data.toString()); break; case 'error': _handleErrorEvent(data.toString()); break; case 'vad': _handleVadEvent(data.toString()); break; default: developer.log('VoiceRecognitionService: 未知事件类型: $eventName', name: 'VoiceRecognition'); break; } } catch (e, stack) { developer.log('VoiceRecognitionService: 处理事件失败: $e', name: 'VoiceRecognition'); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); } } /// 处理状态事件 void _handleStatusEvent(String status) { developer.log('VoiceRecognitionService: 状态变更: $status', name: 'VoiceRecognition'); switch (status) { case 'initialized': isInitialized.value = true; isConnecting.value = false; developer.log('VoiceRecognitionService: 引擎初始化完成', name: 'VoiceRecognition'); break; case 'listening': isListening.value = true; developer.log('VoiceRecognitionService: 开始监听', name: 'VoiceRecognition'); break; case 'idle': isListening.value = false; developer.log('VoiceRecognitionService: 停止监听', name: 'VoiceRecognition'); break; } if (onConnectionStatusChanged != null) { onConnectionStatusChanged!(status); } } /// 处理识别结果事件 void _handleResultEvent(String resultJson) { try { final resultData = jsonDecode(resultJson); final text = resultData['text']; final isFinal = resultData['isFinal']; developer.log('VoiceRecognitionService: 识别结果: $text, 是否最终结果: $isFinal', name: 'VoiceRecognition'); // 更新识别文本 recognizedText.value = text; // 调用回调函数 if (onRecognitionResult != null) { onRecognitionResult!(text); } // 如果是最终结果,调用完成回调 if (isFinal && text.isNotEmpty) { developer.log('VoiceRecognitionService: 句子识别完成: $text', name: 'VoiceRecognition'); if (onSentenceComplete != null) { onSentenceComplete!(text); } if (onRecognitionComplete != null) { onRecognitionComplete!(); } } } catch (e, stack) { developer.log('VoiceRecognitionService: 处理识别结果失败: $e', name: 'VoiceRecognition'); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); } } /// 处理错误事件 void _handleErrorEvent(String errorJson) { try { final errorData = jsonDecode(errorJson); final errorMessage = errorData['message']; final errorCode = errorData['code'] ?? 'unknown'; developer.log('VoiceRecognitionService: 语音识别错误: 代码=$errorCode, 消息=$errorMessage', name: 'VoiceRecognition', error: errorMessage); if (onError != null) { onError!(errorMessage); } } catch (e, stack) { developer.log('VoiceRecognitionService: 处理错误事件失败: $e', name: 'VoiceRecognition'); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); } } /// 处理 VAD 事件 void _handleVadEvent(String vadState) { // 可以根据需要处理 VAD 状态变化 developer.log('VoiceRecognitionService: VAD 状态: $vadState', name: 'VoiceRecognition'); } /// 检查引擎能力和支持的指令 Future checkEngineCapabilities() async { try { developer.log('VoiceRecognitionService: 检查引擎能力', name: 'VoiceRecognition'); // 检查是否已初始化 if (!isInitialized.value) { developer.log('VoiceRecognitionService: 引擎未初始化,尝试初始化', name: 'VoiceRecognition'); await initialize(); } // 调用原生方法检查引擎能力 final result = await _methodChannel.invokeMethod('checkEngineCapabilities'); developer.log('VoiceRecognitionService: 引擎能力检查结果: $result', name: 'VoiceRecognition'); if (result != null) { try { final capabilities = jsonDecode(result); developer.log('VoiceRecognitionService: 引擎版本: ${capabilities['version']}', name: 'VoiceRecognition'); if (capabilities['supported_params'] != null) { developer.log('VoiceRecognitionService: 支持的参数: ${capabilities['supported_params']}', name: 'VoiceRecognition'); } if (capabilities['supported_directives'] != null) { developer.log('VoiceRecognitionService: 支持的指令: ${capabilities['supported_directives']}', name: 'VoiceRecognition'); } } catch (e) { developer.log('VoiceRecognitionService: 解析能力结果失败: $e', name: 'VoiceRecognition'); } } } catch (e, stack) { developer.log('VoiceRecognitionService: 检查引擎能力失败: $e', name: 'VoiceRecognition', error: e); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); } } /// 初始化语音识别引擎 Future initialize() async { try { developer.log('VoiceRecognitionService: 开始初始化语音引擎', name: 'VoiceRecognition'); isConnecting.value = true; // 检查凭证 if (_appKey.isEmpty || _accessKey.isEmpty) { developer.log('VoiceRecognitionService: 凭证未设置,无法初始化', name: 'VoiceRecognition', error: '火山语音识别凭证未设置'); throw '火山语音识别凭证未设置'; } // 添加详细日志 developer.log('VoiceRecognitionService: 使用凭证 AppKey: $_appKey, AccessKey: ${_accessKey.substring(0, 4)}***, Cluster: $_cluster', name: 'VoiceRecognition'); // 调用原生方法初始化引擎 try { final result = await _methodChannel.invokeMethod( 'initialize', { 'appKey': _appKey, 'accessKey': _accessKey, 'cluster': _cluster, }, ); developer.log('VoiceRecognitionService: 初始化结果: $result', name: 'VoiceRecognition'); // 初始化成功后,检查引擎能力 await checkEngineCapabilities(); } catch (e) { developer.log('VoiceRecognitionService: 初始化方法调用失败: $e', name: 'VoiceRecognition', error: e); // 尝试检查引擎是否已初始化 try { final isEngineInitialized = await _methodChannel.invokeMethod('isInitialized') ?? false; if (isEngineInitialized) { developer.log('VoiceRecognitionService: 引擎已经初始化,忽略错误', name: 'VoiceRecognition'); isInitialized.value = true; isConnecting.value = false; // 引擎已初始化,检查引擎能力 await checkEngineCapabilities(); return; } } catch (checkError) { developer.log('VoiceRecognitionService: 检查引擎初始化状态失败: $checkError', name: 'VoiceRecognition'); } // 如果检查失败或引擎未初始化,则重新抛出异常 rethrow; } // 初始化成功后,状态会通过事件通道更新 } catch (e, stack) { isConnecting.value = false; developer.log('VoiceRecognitionService: 初始化语音识别引擎失败: $e', name: 'VoiceRecognition', error: e); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); String errorMessage = '初始化失败: $e'; // 提供更具体的错误信息 if (e.toString().contains('error code: -7')) { errorMessage = '初始化失败: 无法创建日志目录,请检查应用权限'; developer.log('VoiceRecognitionService: 错误代码 -7: 无法创建日志目录', name: 'VoiceRecognition'); } else if (e.toString().contains('INIT_ERROR')) { errorMessage = '初始化失败: 引擎初始化错误,请检查网络连接和凭证'; developer.log('VoiceRecognitionService: INIT_ERROR: 引擎初始化错误', name: 'VoiceRecognition'); } if (onError != null) { onError!(errorMessage); } rethrow; } } /// 开始语音识别 Future startRecognition() async { try { developer.log('VoiceRecognitionService: 开始语音识别', name: 'VoiceRecognition'); // 检查是否已初始化 if (!isInitialized.value) { developer.log('VoiceRecognitionService: 引擎未初始化,尝试初始化', name: 'VoiceRecognition'); await initialize(); } developer.log('VoiceRecognitionService: 调用原生方法 startRecognition', name: 'VoiceRecognition'); // 调用原生方法开始识别 final result = await _methodChannel.invokeMethod('startRecognition'); developer.log('VoiceRecognitionService: 开始识别结果: $result', name: 'VoiceRecognition'); // 状态会通过事件通道更新 } catch (e, stack) { developer.log('VoiceRecognitionService: 开始语音识别失败: $e', name: 'VoiceRecognition', error: e); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); if (onError != null) { onError!('开始识别失败: $e'); } rethrow; } } /// 停止语音识别 Future stopRecognition() async { try { developer.log('VoiceRecognitionService: 停止语音识别', name: 'VoiceRecognition'); // 检查是否已初始化 if (!isInitialized.value) { developer.log('VoiceRecognitionService: 引擎未初始化,无法停止识别', name: 'VoiceRecognition'); return; } developer.log('VoiceRecognitionService: 调用原生方法 stopRecognition', name: 'VoiceRecognition'); // 调用原生方法停止识别 final result = await _methodChannel.invokeMethod('stopRecognition'); developer.log('VoiceRecognitionService: 停止识别结果: $result', name: 'VoiceRecognition'); // 状态会通过事件通道更新 } catch (e, stack) { developer.log('VoiceRecognitionService: 停止语音识别失败: $e', name: 'VoiceRecognition', error: e); developer.log('VoiceRecognitionService: 错误堆栈: $stack', name: 'VoiceRecognition'); if (onError != null) { onError!('停止识别失败: $e'); } } } @override void onClose() { developer.log('VoiceRecognitionService: 关闭服务', name: 'VoiceRecognition'); // 取消事件订阅 _eventSubscription?.cancel(); // 停止识别 stopRecognition(); super.onClose(); } }