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'; /// 火山语音识别服务 /// 负责与原生层的火山语音识别引擎交互 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; @override void onInit() { super.onInit(); _loadCredentials(); _setupEventListener(); } /// 加载火山语音识别的凭证 void _loadCredentials() { try { _appKey = dotenv.env['VOLC_SPEECH_APP_KEY'] ?? ''; _accessKey = dotenv.env['VOLC_SPEECH_ACCESS_KEY'] ?? ''; if (_appKey.isEmpty || _accessKey.isEmpty) { debugPrint('警告: 火山语音识别凭证未设置,请在 .env 文件中设置 VOLC_SPEECH_APP_KEY 和 VOLC_SPEECH_ACCESS_KEY'); } } catch (e) { debugPrint('加载火山语音识别凭证失败: $e'); } } /// 设置事件监听器 void _setupEventListener() { try { _eventSubscription = _eventChannel.receiveBroadcastStream().listen( (dynamic event) { _handleEvent(event.toString()); }, onError: (dynamic error) { debugPrint('事件通道错误: $error'); if (onError != null) { onError!('事件通道错误: $error'); } }, ); } catch (e) { debugPrint('设置事件监听器失败: $e'); } } /// 处理来自原生层的事件 void _handleEvent(String eventJson) { try { final eventData = jsonDecode(eventJson); final eventName = eventData['event']; final data = eventData['data']; 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; } } catch (e) { debugPrint('处理事件失败: $e'); } } /// 处理状态事件 void _handleStatusEvent(String status) { switch (status) { case 'initialized': isInitialized.value = true; isConnecting.value = false; break; case 'listening': isListening.value = true; break; case 'idle': isListening.value = false; break; } if (onConnectionStatusChanged != null) { onConnectionStatusChanged!(status); } } /// 处理识别结果事件 void _handleResultEvent(String resultJson) { try { final resultData = jsonDecode(resultJson); final text = resultData['text']; final isFinal = resultData['isFinal']; // 更新识别文本 recognizedText.value = text; // 调用回调函数 if (onRecognitionResult != null) { onRecognitionResult!(text); } // 如果是最终结果,调用完成回调 if (isFinal && text.isNotEmpty) { if (onSentenceComplete != null) { onSentenceComplete!(text); } if (onRecognitionComplete != null) { onRecognitionComplete!(); } } } catch (e) { debugPrint('处理识别结果失败: $e'); } } /// 处理错误事件 void _handleErrorEvent(String errorJson) { try { final errorData = jsonDecode(errorJson); final errorMessage = errorData['message']; debugPrint('语音识别错误: $errorMessage'); if (onError != null) { onError!(errorMessage); } } catch (e) { debugPrint('处理错误事件失败: $e'); } } /// 处理 VAD 事件 void _handleVadEvent(String vadState) { // 可以根据需要处理 VAD 状态变化 debugPrint('VAD 状态: $vadState'); } /// 初始化语音识别引擎 Future initialize() async { try { isConnecting.value = true; // 检查凭证 if (_appKey.isEmpty || _accessKey.isEmpty) { throw '火山语音识别凭证未设置'; } // 调用原生方法初始化引擎 final result = await _methodChannel.invokeMethod( 'initialize', { 'appKey': _appKey, 'accessKey': _accessKey, }, ); debugPrint('初始化结果: $result'); // 初始化成功后,状态会通过事件通道更新 } catch (e) { isConnecting.value = false; debugPrint('初始化语音识别引擎失败: $e'); if (onError != null) { onError!('初始化失败: $e'); } rethrow; } } /// 开始语音识别 Future startRecognition() async { try { // 检查是否已初始化 if (!isInitialized.value) { await initialize(); } // 调用原生方法开始识别 final result = await _methodChannel.invokeMethod('startRecognition'); debugPrint('开始识别结果: $result'); // 状态会通过事件通道更新 } catch (e) { debugPrint('开始语音识别失败: $e'); if (onError != null) { onError!('开始识别失败: $e'); } rethrow; } } /// 停止语音识别 Future stopRecognition() async { try { // 检查是否已初始化 if (!isInitialized.value) { return; } // 调用原生方法停止识别 final result = await _methodChannel.invokeMethod('stopRecognition'); debugPrint('停止识别结果: $result'); // 状态会通过事件通道更新 } catch (e) { debugPrint('停止语音识别失败: $e'); if (onError != null) { onError!('停止识别失败: $e'); } } } @override void onClose() { // 取消事件订阅 _eventSubscription?.cancel(); // 停止识别 stopRecognition(); super.onClose(); } }