import 'dart:async'; import 'package:flutter/services.dart'; import 'package:get/get.dart'; import '../../core/utils/logger.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import '../../modules/chat/models/message_model.dart'; import 'chat_history_service.dart'; import 'speech_impl/azure_asr_service.dart'; import 'speech_impl/azure_tts_service.dart'; import 'asr_service.dart'; import 'tts_service.dart'; /// 语音交互服务 /// /// 该服务提供了与Android端的VoiceInteractionService.kt通信的接口, /// 用于管理后台语音交互服务的生命周期和接收语音交互事件 class VoiceInteractionService extends GetxService { static VoiceInteractionService get to => Get.find(); // 方法通道和事件通道 static const MethodChannel _channel = MethodChannel('com.deep_voice.voice_interaction'); static const EventChannel _eventChannel = EventChannel('com.deep_voice.voice_interaction_events'); // 服务状态 final _isServiceRunning = false.obs; bool get isServiceRunning => _isServiceRunning.value; // 事件流控制器 StreamController? _eventStreamController; Stream? _eventStream; Stream? get eventStream => _eventStream; // 事件通道状态 bool _isEventChannelReady = false; Completer? _eventChannelReadyCompleter; StreamSubscription? _eventSubscription; // 配置信息 late String _azureSpeechKey; late String _azureSpeechRegion; late String _volcanoAiApiKey; // 初始化状态标志 static bool _isInitialized = false; /// 构造函数 VoiceInteractionService() { } /// 从环境变量加载配置 void _loadConfig() { _azureSpeechKey = dotenv.env['AZURE_SPEECH_KEY'] ?? ''; _azureSpeechRegion = dotenv.env['AZURE_SPEECH_REGION'] ?? ''; _volcanoAiApiKey = dotenv.env['VOLCANO_AI_API_KEY'] ?? ''; if (_azureSpeechKey.isEmpty || _azureSpeechRegion.isEmpty) { Logger.warning('未找到 Azure 语音服务配置。请在 .env 文件中设置 AZURE_SPEECH_KEY 和 AZURE_SPEECH_REGION'); } if (_volcanoAiApiKey.isEmpty) { Logger.warning('未找到火山 AI API 密钥。请在 .env 文件中设置 VOLCANO_AI_API_KEY'); } } /// 设置事件通道 void _setupEventChannel() { _eventChannelReadyCompleter = Completer(); _eventSubscription = _eventChannel .receiveBroadcastStream() .listen((event) { if (event is Map) { final String eventType = event['type'] as String? ?? ''; // 处理通道准备好的事件 if (eventType == 'channelReady') { _isEventChannelReady = true; if (!_eventChannelReadyCompleter!.isCompleted) { _eventChannelReadyCompleter!.complete(); } return; } _handleVoiceInteractionEvent(event); } }, onError: (error) { Logger.error('语音交互事件通道错误: $error'); }); } /// 创建事件流 void _createEventStream() { _eventStreamController = StreamController.broadcast(); _eventStream = _eventStreamController?.stream; } /// 等待事件通道准备好 Future _waitForEventChannel({Duration timeout = const Duration(seconds: 5)}) async { if (_isEventChannelReady) return true; try { await _eventChannelReadyCompleter!.future.timeout(timeout); return true; } on TimeoutException { Logger.error('等待语音交互事件通道准备好超时'); return false; } } /// 初始化服务 Future initialize() async { try { if (_isInitialized) { return this; } _isInitialized = true; _loadConfig(); _setupEventChannel(); _createEventStream(); // 检查服务是否正在运行 await _checkServiceStatus(); // 等待事件通道准备好 await _waitForEventChannel(); Logger.info('语音交互服务初始化完成'); return this; } catch (e) { Logger.error('语音交互服务初始化失败: $e'); return this; } } /// 检查服务状态 Future _checkServiceStatus() async { try { final bool isRunning = await _channel.invokeMethod('isVoiceInteractionServiceRunning') ?? false; _isServiceRunning.value = isRunning; Logger.info('语音交互服务状态: ${isRunning ? "运行中" : "未运行"}'); } catch (e) { Logger.error('检查语音交互服务状态失败: $e'); _isServiceRunning.value = false; } } /// 启动语音交互服务 Future startService() async { if (_isServiceRunning.value) { Logger.info('语音交互服务已经在运行'); return true; } try { final bool result = await _channel.invokeMethod('startVoiceInteractionService', { 'azure_speech_key': _azureSpeechKey, 'azure_speech_region': _azureSpeechRegion, 'volcano_ai_api_key': _volcanoAiApiKey, }) ?? false; if (result) { _isServiceRunning.value = true; Logger.info('语音交互服务启动成功'); } else { Logger.error('语音交互服务启动失败'); } return result; } catch (e) { Logger.error('启动语音交互服务失败: $e'); return false; } } /// 停止语音交互服务 Future stopService() async { if (!_isServiceRunning.value) { Logger.info('语音交互服务未运行'); return true; } try { final bool result = await _channel.invokeMethod('stopVoiceInteractionService') ?? false; if (result) { _isServiceRunning.value = false; Logger.info('语音交互服务停止成功'); } else { Logger.error('语音交互服务停止失败'); } return result; } catch (e) { Logger.error('停止语音交互服务失败: $e'); return false; } } /// 暂停语音交互(停止TTS和语音识别,但保持服务运行) Future pauseVoiceInteraction() async { if (!_isServiceRunning.value) { Logger.info('语音交互服务未运行,无法暂停'); return false; } try { final bool result = await _channel.invokeMethod('pauseVoiceInteraction') ?? false; if (result) { Logger.info('语音交互暂停成功'); } else { Logger.error('语音交互暂停失败'); } return result; } catch (e) { Logger.error('暂停语音交互失败: $e'); return false; } } /// 处理来自原生端的语音交互事件 void _handleVoiceInteractionEvent(dynamic event) { if (event is! Map || _eventStreamController == null) return; final Map eventMap = event; final String eventType = eventMap['type'] as String? ?? ''; final int timestamp = eventMap['timestamp'] as int? ?? 0; // 添加时间戳日志,帮助调试 Logger.info('收到原生端事件: $eventType, 时间戳: $timestamp, 当前时间: ${DateTime.now().millisecondsSinceEpoch}'); switch (eventType) { case 'chatHistory': final String agentId = eventMap['agentId'] as String? ?? ''; final String userMessage = eventMap['userMessage'] as String? ?? ''; final String assistantMessage = eventMap['assistantMessage'] as String? ?? ''; _eventStreamController?.add(ChatHistoryEvent( agentId: agentId, userMessage: userMessage, assistantMessage: assistantMessage, timestamp: timestamp, )); // 保存聊天记录 _saveChatHistory(agentId, userMessage, assistantMessage, timestamp); Logger.info('收到聊天历史事件: agentId=$agentId'); break; case 'recognitionStarted': _eventStreamController?.add(RecognitionStartedEvent( timestamp: timestamp, )); break; default: Logger.warning('收到未知类型的语音交互事件: $eventType'); break; } } @override void onClose() { // 清理资源 _eventSubscription?.cancel(); _eventStreamController?.close(); super.onClose(); } /// 保存聊天记录 void _saveChatHistory(String agentId, String userMessage, String assistantMessage, int timestamp) { try { // 获取ChatHistoryService实例 final chatHistoryService = Get.find(); // 创建用户消息和助手消息 final userMsg = Message( role: 'user', content: userMessage, timestamp: DateTime.fromMillisecondsSinceEpoch(timestamp), ); final assistantMsg = Message( role: 'assistant', content: assistantMessage, timestamp: DateTime.fromMillisecondsSinceEpoch(timestamp + 1), // 确保助手消息时间戳晚于用户消息 ); // 加载现有历史记录 final existingMessages = chatHistoryService.loadHistory(agentId); // 添加新消息 existingMessages.addAll([userMsg, assistantMsg]); // 保存更新后的历史记录 chatHistoryService.saveHistory(agentId, existingMessages); } catch (e) { Logger.error('保存聊天记录失败: $e'); } } } /// 语音交互事件基类 abstract class VoiceInteractionEvent { final int timestamp; VoiceInteractionEvent({required this.timestamp}); } /// 聊天历史事件 class ChatHistoryEvent extends VoiceInteractionEvent { final String agentId; final String userMessage; final String assistantMessage; ChatHistoryEvent({ required this.agentId, required this.userMessage, required this.assistantMessage, required int timestamp, }) : super(timestamp: timestamp); } /// 语音识别开始事件 class RecognitionStartedEvent extends VoiceInteractionEvent { RecognitionStartedEvent({ required int timestamp, }) : super(timestamp: timestamp); }