diff --git a/lib/core/services/floating_window_manager.dart b/lib/core/services/floating_window_manager.dart index 056425701..b374d496b 100644 --- a/lib/core/services/floating_window_manager.dart +++ b/lib/core/services/floating_window_manager.dart @@ -165,9 +165,8 @@ class FloatingWindowManager extends GetxController { try { await _api.updateContent(data.toMap()); - Logger.info('悬浮窗内容已更新'); } catch (e) { - Logger.error('更新悬浮窗内容失败: $e'); + Logger.e('FloatingWindow', '更新悬浮窗内容失败: $e'); } } diff --git a/lib/core/utils/app_lifecycle_manager.dart b/lib/core/utils/app_lifecycle_manager.dart index 3f0f744b8..8685e0ffd 100644 --- a/lib/core/utils/app_lifecycle_manager.dart +++ b/lib/core/utils/app_lifecycle_manager.dart @@ -79,7 +79,7 @@ class AppLifecycleManager extends GetxService with WidgetsBindingObserver { _lastCanWakeUp = canWakeUp; try { - Logger.info('lxm---设置是否可以ble唤醒agent: $canWakeUp'); + Logger.i('AppLifecycle', '设置是否可以ble唤醒agent: $canWakeUp'); await AgentService.setCanWakeUp(canWakeUp); } catch (e) { Logger.warning('setCanWakeUp失败: $e'); diff --git a/lib/core/utils/logger.dart b/lib/core/utils/logger.dart index 239bdd0dc..05d276c72 100644 --- a/lib/core/utils/logger.dart +++ b/lib/core/utils/logger.dart @@ -1,6 +1,7 @@ import 'dart:developer' as developer; import 'dart:io'; import 'dart:async'; +import 'package:flutter/foundation.dart'; import 'package:path_provider/path_provider.dart'; import 'package:intl/intl.dart'; @@ -14,10 +15,19 @@ enum LogLevel { /// 日志工具类 /// -/// 提供统一的日志记录接口,支持控制台输出和文件存储 +/// 特性: +/// - 写日志只入内存队列,由后台 Timer 定时批量刷盘,避免主 Isolate 同步 I/O。 +/// - Release 包默认 [LogLevel.warning],Debug 包默认 [LogLevel.debug]。 +/// - `error` 级别写入后强制立即 flush,崩溃前关键错误不丢。 +/// - 支持 `dLazy/iLazy/wLazy` 闭包式 API,级别被过滤时完全不执行字符串插值。 +/// - 时间戳格式化按秒缓存,避免每条日志重复 `DateFormat`。 class Logger { - /// 当前日志级别,低于此级别的日志不会被输出 - static LogLevel _currentLevel = LogLevel.debug; + /// 当前日志级别 + static LogLevel _currentLevel = + kReleaseMode ? LogLevel.warning : LogLevel.debug; + + /// 控制台输出开关(Release 默认关闭以减少 developer.log 开销) + static bool _consoleEnabled = !kReleaseMode; /// 默认标签 static const String _defaultTag = 'App'; @@ -27,30 +37,44 @@ class Logger { static File? _currentLogFile; static bool _fileLogEnabled = false; static String? _logDirPath; - static final DateFormat _dateFormat = DateFormat('yyyy-MM-dd HH:mm:ss.SSS'); static final DateFormat _fileDateFormat = DateFormat('yyyy-MM-dd'); + /// 单行最大字符数,超过则截断(避免日志被过长字符串拖慢) + static const int _maxLineLength = 4000; + /// 最大单个日志文件大小 (2MB) static const int _maxFileSize = 2 * 1024 * 1024; /// 最多保留日志文件数量 static const int _maxLogFiles = 7; - /// 写入计数器,用于节流轮转检查和刷盘 - static int _writeCount = 0; + /// 内存队列:写日志只入队,由定时器批量落盘 + static final List _queue = []; + + /// 队列上限。超过后丢弃最旧条目(保留最新),防止内存无限增长。 + static const int _maxQueueSize = 5000; - /// 轮转检查间隔(每 100 次写入检查一次) - static const int _rotationCheckInterval = 100; + /// 定时刷盘间隔 + static const Duration _flushInterval = Duration(milliseconds: 500); + static Timer? _flushTimer; - /// 刷盘间隔(每 50 次写入刷一次) - static const int _flushInterval = 50; + /// 轮转检查间隔 + static const Duration _rotationInterval = Duration(seconds: 30); + static Timer? _rotationTimer; /// 轮转锁,防止并发轮转 static bool _isRotating = false; - /// 当前日志文件的日期标识,用于快速判断是否需要换天 + /// 正在刷盘标记,防止定时器重入 + static bool _isFlushing = false; + + /// 当前日志文件的日期标识 static String _currentFileDate = ''; + /// 时间戳缓存:同一秒内复用 + static int _cachedTsEpochSecond = 0; + static String _cachedTsString = ''; + /// 初始化文件日志 static Future initFileLog() async { try { @@ -62,7 +86,13 @@ class Logger { } await _openLogFile(); _fileLogEnabled = true; - Logger.i('Logger', '文件日志初始化成功: $_logDirPath'); + + // 启动后台刷盘与轮转定时器 + _flushTimer ??= Timer.periodic(_flushInterval, (_) => _drainQueue()); + _rotationTimer ??= + Timer.periodic(_rotationInterval, (_) => _checkRotation()); + + Logger.i('Logger', '文件日志初始化成功: $_logDirPath level=$_currentLevel'); } catch (e) { developer.log('[Logger] 文件日志初始化失败: $e'); } @@ -73,24 +103,47 @@ class Logger { final today = _fileDateFormat.format(DateTime.now()); final filePath = '$_logDirPath/app_$today.log'; _currentLogFile = File(filePath); - // 先关闭旧 sink,必须 await 确保关闭完成 await _logSink?.flush(); await _logSink?.close(); _logSink = _currentLogFile!.openWrite(mode: FileMode.append); _currentFileDate = today; } - /// 检查日志文件是否需要轮转(受节流和锁保护) + /// 把队列里的所有条目一次性写到 sink + static Future _drainQueue() async { + if (_isFlushing) return; + if (!_fileLogEnabled || _logSink == null) return; + if (_queue.isEmpty) return; + _isFlushing = true; + try { + // O(1) 取出全部 + final batch = List.unmodifiable(_queue); + _queue.clear(); + // 单次 write 减少 syscall 次数 + _logSink!.write(batch.join('\n')); + _logSink!.write('\n'); + await _logSink!.flush(); + } catch (e) { + developer.log('[Logger] drain 失败: $e'); + } finally { + _isFlushing = false; + } + } + + /// 检查日志文件是否需要轮转(后台定时调度,不在写路径执行) static Future _checkRotation() async { if (_isRotating || _currentLogFile == null) return; _isRotating = true; try { - // 检查日期是否变更 + // 先把队列里的内容落盘,以免轮转后丢 + await _drainQueue(); + + // 日期变更 → 换新文件 final today = _fileDateFormat.format(DateTime.now()); if (_currentFileDate != today) { await _openLogFile(); } - // 检查文件大小 + // 文件过大 → 切分 if (await _currentLogFile!.exists()) { final size = await _currentLogFile!.length(); if (size > _maxFileSize) { @@ -104,9 +157,9 @@ class Logger { _logSink = _currentLogFile!.openWrite(mode: FileMode.append); } } - // 清理旧日志文件 await _cleanOldLogs(); - } catch (_) {} finally { + } catch (_) { + } finally { _isRotating = false; } } @@ -131,40 +184,38 @@ class Logger { } catch (_) {} } - /// 单行最大字符数,超过则分批写入 - static const int _maxLineLength = 4000; - - /// 写入日志到文件 - static void _writeToFile(String level, String tag, String message) { - if (!_fileLogEnabled || _logSink == null) return; - try { - final timestamp = _dateFormat.format(DateTime.now()); - if (message.length <= _maxLineLength) { - _logSink!.writeln('$timestamp [$level][$tag] $message'); - } else { - final totalParts = (message.length + _maxLineLength - 1) ~/ _maxLineLength; - for (var i = 0; i < totalParts; i++) { - final start = i * _maxLineLength; - final end = start + _maxLineLength > message.length ? message.length : start + _maxLineLength; - final chunk = message.substring(start, end); - _logSink!.writeln('$timestamp [$level][$tag] [${i + 1}/$totalParts] $chunk'); - } - } - _writeCount++; - - // 定期刷盘,确保数据写入磁盘 - if (_writeCount % _flushInterval == 0) { - _logSink!.flush(); - } + /// 快速时间戳(到秒级缓存 + 毫秒拼接) + static String _formatTimestamp(DateTime now) { + final epochSec = now.millisecondsSinceEpoch ~/ 1000; + if (epochSec != _cachedTsEpochSecond) { + _cachedTsEpochSecond = epochSec; + // yyyy-MM-dd HH:mm:ss + final y = now.year.toString().padLeft(4, '0'); + final mo = now.month.toString().padLeft(2, '0'); + final d = now.day.toString().padLeft(2, '0'); + final h = now.hour.toString().padLeft(2, '0'); + final mi = now.minute.toString().padLeft(2, '0'); + final s = now.second.toString().padLeft(2, '0'); + _cachedTsString = '$y-$mo-$d $h:$mi:$s'; + } + final ms = now.millisecond.toString().padLeft(3, '0'); + return '$_cachedTsString.$ms'; + } - // 定期检查轮转(节流,不是每次写入都检查) - if (_writeCount % _rotationCheckInterval == 0) { - _checkRotation(); - } - } catch (e) { - // 文件写入失败不应影响业务逻辑(尤其是 Dio 拦截器链) - developer.log('[Logger] 文件写入失败: $e'); + /// 入队(不触发 I/O) + static void _enqueue(String level, String tag, String message) { + if (!_fileLogEnabled) return; + final ts = _formatTimestamp(DateTime.now()); + String msg = message; + if (msg.length > _maxLineLength) { + msg = + '${msg.substring(0, _maxLineLength)}… (truncated ${message.length - _maxLineLength}字符)'; + } + // 溢出保护:保留最新 + if (_queue.length >= _maxQueueSize) { + _queue.removeRange(0, _queue.length - _maxQueueSize + 1); } + _queue.add('$ts [$level][$tag] $msg'); } /// 获取日志目录路径 @@ -180,12 +231,13 @@ class Logger { .where((e) => e is File && e.path.endsWith('.log')) .cast() .toList(); - files.sort((a, b) => b.path.compareTo(a.path)); // 最新在前 + files.sort((a, b) => b.path.compareTo(a.path)); return files; } - /// 刷新缓冲区(导出前调用) + /// 强制把队列刷到磁盘(导出前调用) static Future flush() async { + await _drainQueue(); await _logSink?.flush(); } @@ -194,86 +246,114 @@ class Logger { _currentLevel = level; } - /// 输出调试日志 (不带标签版本) + /// 开关控制台输出(默认 Release 关闭) + static void setConsoleEnabled(bool enabled) { + _consoleEnabled = enabled; + } + + /// 当前级别是否允许某级别输出 + static bool isLoggable(LogLevel level) => + level.index >= _currentLevel.index; + + // ========== 普通 API ========== + static void debug(String message) { - if (_currentLevel.index <= LogLevel.debug.index) { - _log('DEBUG', _defaultTag, message); + if (LogLevel.debug.index >= _currentLevel.index) { + _log('DEBUG', _defaultTag, message, false); } } - /// 输出调试日志 static void d(String tag, String message) { - if (_currentLevel.index <= LogLevel.debug.index) { - _log('DEBUG', tag, message); + if (LogLevel.debug.index >= _currentLevel.index) { + _log('DEBUG', tag, message, false); } } - /// 输出信息日志 (不带标签版本) static void info(String message) { - if (_currentLevel.index <= LogLevel.info.index) { - _log('INFO', _defaultTag, message); + if (LogLevel.info.index >= _currentLevel.index) { + _log('INFO', _defaultTag, message, false); } } - /// 输出信息日志 static void i(String tag, String message) { - if (_currentLevel.index <= LogLevel.info.index) { - _log('INFO', tag, message); + if (LogLevel.info.index >= _currentLevel.index) { + _log('INFO', tag, message, false); } } - /// 输出警告日志 (不带标签版本) static void warning(String message) { - if (_currentLevel.index <= LogLevel.warning.index) { - _log('WARNING', _defaultTag, message); + if (LogLevel.warning.index >= _currentLevel.index) { + _log('WARN', _defaultTag, message, false); } } - /// 输出警告日志 static void w(String tag, String message) { - if (_currentLevel.index <= LogLevel.warning.index) { - _log('WARNING', tag, message); + if (LogLevel.warning.index >= _currentLevel.index) { + _log('WARN', tag, message, false); } } - /// 输出错误日志 (不带标签版本) static void error(String message, [dynamic error, StackTrace? stackTrace]) { - if (_currentLevel.index <= LogLevel.error.index) { - _log('ERROR', _defaultTag, message); - if (error != null) { - _log('ERROR', _defaultTag, 'Original error: $error'); - } + if (LogLevel.error.index >= _currentLevel.index) { + _log('ERROR', _defaultTag, message, true); + if (error != null) _log('ERROR', _defaultTag, 'Original error: $error', true); if (stackTrace != null) { - _log('ERROR', _defaultTag, 'Stack trace: $stackTrace'); + _log('ERROR', _defaultTag, 'Stack trace: $stackTrace', true); } } } - /// 输出错误日志 - static void e(String tag, String message, [dynamic error, StackTrace? stackTrace]) { - if (_currentLevel.index <= LogLevel.error.index) { - _log('ERROR', tag, message); - if (error != null) { - _log('ERROR', tag, 'Original error: $error'); - } + static void e(String tag, String message, + [dynamic error, StackTrace? stackTrace]) { + if (LogLevel.error.index >= _currentLevel.index) { + _log('ERROR', tag, message, true); + if (error != null) _log('ERROR', tag, 'Original error: $error', true); if (stackTrace != null) { - _log('ERROR', tag, 'Stack trace: $stackTrace'); + _log('ERROR', tag, 'Stack trace: $stackTrace', true); } } } + // ========== 闭包式 API(高频热点推荐) ========== + + /// Debug 级别懒求值:级别未放行时连字符串都不会构造。 + static void dLazy(String tag, String Function() messageBuilder) { + if (LogLevel.debug.index >= _currentLevel.index) { + _log('DEBUG', tag, messageBuilder(), false); + } + } + + static void iLazy(String tag, String Function() messageBuilder) { + if (LogLevel.info.index >= _currentLevel.index) { + _log('INFO', tag, messageBuilder(), false); + } + } + + static void wLazy(String tag, String Function() messageBuilder) { + if (LogLevel.warning.index >= _currentLevel.index) { + _log('WARN', tag, messageBuilder(), false); + } + } + /// 内部日志输出方法 - static void _log(String level, String tag, String message) { - if (message.length <= _maxLineLength) { - developer.log('[$tag]: $message'); - } else { - final totalParts = (message.length + _maxLineLength - 1) ~/ _maxLineLength; - for (var i = 0; i < totalParts; i++) { - final start = i * _maxLineLength; - final end = start + _maxLineLength > message.length ? message.length : start + _maxLineLength; - developer.log('[$tag]: [${i + 1}/$totalParts] ${message.substring(start, end)}'); + /// + /// [forceFlush] = true 时(error 级别)立即触发一次 drain, + /// 保证崩溃前关键错误一定落盘。 + static void _log(String level, String tag, String message, bool forceFlush) { + if (_consoleEnabled) { + if (message.length <= _maxLineLength) { + developer.log('[$tag]: $message'); + } else { + developer.log( + '[$tag]: ${message.substring(0, _maxLineLength)}… (+${message.length - _maxLineLength}字符)'); } } - _writeToFile(level, tag, message); + _enqueue(level, tag, message); + if (forceFlush) { + // fire-and-forget;_drainQueue 自带并发保护 + // 不 await 以免阻塞调用方 + // ignore: discarded_futures + _drainQueue(); + } } } diff --git a/lib/data/services/ble_manager.dart b/lib/data/services/ble_manager.dart index a71d35e4d..f73e0cb2e 100644 --- a/lib/data/services/ble_manager.dart +++ b/lib/data/services/ble_manager.dart @@ -259,180 +259,119 @@ class BleManager extends GetxService { /// 设置BLE事件监听 void _setupBleListener() { - //Logger.info('lxm--_setupBleListener被调用,开始设置BLE事件监听'); _statusSubscription?.cancel(); _dataSubscription?.cancel(); try { - Logger.info('lxm--开始监听BLE状态更新流'); - // 监听BLE状态更新 _statusSubscription = _bleService.onStatusUpdated.listen( (event) { - Logger.info('lxm--收到BLE状态更新事件: $event'); - if (event is Map) { - Logger.info('lxm--事件是Map类型,开始处理'); - // 处理连接状态更新 - if (event['type'] == 'connectionStateChanged') { - Logger.info('lxm--处理连接状态变化事件'); - final state = event['state'] as int; - final oldState = _connectionState.value; - _connectionState.value = state; - - Logger.d('BleManager', '🔄 BLE状态更新: $oldState → $state'); - Logger.d('BleManager', '📡 通知监听器状态变化: ${_connectionState.value}'); - - // 连接状态转换 - if (state == BleConnectionState.connected) { - Logger.info('lxm--BLE设备已连接'); - _isConnected.value = true; - - // 设备信息(含唤醒状态)由 HomeController.fetchDeviceInfo() 统一查询 - } else if (state == BleConnectionState.disconnected || - state == BleConnectionState.error) { - Logger.info('lxm--BLE设备已断开或发生错误'); - _isConnected.value = false; - _awaitingCodecOpen = false; - _awaitingCodecClose = false; - _isCodecActive.value = false; - _voiceWakeupSupported.value = false; - _voiceWakeupEnabled.value = true; - Logger.info('[VoiceWakeup] 断开连接,重置 supported=false, enabled=true'); - Logger.info('lxm--断开连接时重置设备信息为0'); - _updateDeviceInfoIfNeeded( - batteryLevel: 0, - leftEarBattery: 0, - rightEarBattery: 0, - caseBattery: 0, - leftEarCharging: false, - rightEarCharging: false, - caseCharging: false, - firmwareVersion: '', - firmwareProductId: '', - firmwareProductColor: '', - wakeupLeftVersion: '', - wakeupRightVersion: '', - ); - // 断开连接时不清除设备信息,保留最后的电量信息 - // 只有在需要完全清除设备时才重置信息 - } - } - - if (event['type'] == 'wakeupVoiceUpgradeProgress') { - // 唤醒语音升级进度 - Logger.info('lxm--处理唤醒语音升级进度事件: $event'); - _wakeupVoiceUpgradeProgress.value = - event['progress'] as int? ?? 0; - _wakeupVoiceUpgradeStatus.value = 1; // 升级中 - Logger.info( - 'lxm--唤醒语音升级进度: ${_wakeupVoiceUpgradeProgress.value}%'); - } - if (event['type'] == 'wakeupVoiceUpgradeSuccess') { - // 唤醒语音升级状态 - Logger.info('lxm--处理唤醒语音升级状态事件: $event'); - _wakeupVoiceUpgradeStatus.value = 2; // 升级成功 - Logger.info('lxm--唤醒语音升级状态: ${_wakeupVoiceUpgradeStatus.value}'); + if (event is! Map) return; + + if (event['type'] == 'connectionStateChanged') { + final state = event['state'] as int; + final oldState = _connectionState.value; + _connectionState.value = state; + Logger.i('BleManager', 'BLE状态更新: $oldState → $state'); + + if (state == BleConnectionState.connected) { + _isConnected.value = true; + } else if (state == BleConnectionState.disconnected || + state == BleConnectionState.error) { + _isConnected.value = false; + _awaitingCodecOpen = false; + _awaitingCodecClose = false; + _isCodecActive.value = false; + _voiceWakeupSupported.value = false; + _voiceWakeupEnabled.value = true; + Logger.i('BleManager', + '[VoiceWakeup] 断开连接,重置 supported=false, enabled=true'); + _updateDeviceInfoIfNeeded( + batteryLevel: 0, + leftEarBattery: 0, + rightEarBattery: 0, + caseBattery: 0, + leftEarCharging: false, + rightEarCharging: false, + caseCharging: false, + firmwareVersion: '', + firmwareProductId: '', + firmwareProductColor: '', + wakeupLeftVersion: '', + wakeupRightVersion: '', + ); } + } - if (event['type'] == 'wakeupVoiceUpgradeFailure') { - // 唤醒语音升级状态 - Logger.info('lxm--处理唤醒语音升级状态事件: $event'); - _wakeupVoiceUpgradeStatus.value = 3; // 升级失败 - Logger.info('lxm--唤醒语音升级状态: ${_wakeupVoiceUpgradeStatus.value}'); - } + if (event['type'] == 'wakeupVoiceUpgradeProgress') { + _wakeupVoiceUpgradeProgress.value = event['progress'] as int? ?? 0; + _wakeupVoiceUpgradeStatus.value = 1; + } + if (event['type'] == 'wakeupVoiceUpgradeSuccess') { + _wakeupVoiceUpgradeStatus.value = 2; + Logger.i('BleManager', '唤醒语音升级成功'); + } - Logger.info('lxm--准备调用_processDeviceInfo处理设备信息'); - // 处理设备信息 - _processDeviceInfo(event); - } else { - Logger.info('lxm--事件不是Map类型: ${event.runtimeType}'); + if (event['type'] == 'wakeupVoiceUpgradeFailure') { + _wakeupVoiceUpgradeStatus.value = 3; + Logger.w('BleManager', '唤醒语音升级失败'); } + + _processDeviceInfo(event); }, onError: (error) { - Logger.error('lxm--BLE状态事件流错误: $error'); + Logger.e('BleManager', 'BLE状态事件流错误: $error'); }, ); - - Logger.info('lxm--BLE状态监听器设置完成'); - // 监听BLE数据流 } catch (e) { - Logger.error('lxm--设置BLE事件监听器失败: ${e.toString()}'); + Logger.e('BleManager', '设置BLE事件监听器失败: ${e.toString()}'); } } /// 处理来自原生层的设备信息 void _processDeviceInfo(Map event) { try { - Logger.info('lxm--_processDeviceInfo被调用'); - Logger.info('lxm--接收到的事件数据: $event'); - - // 检查是否是设备信息响应 - if (event.containsKey('command') && event.containsKey('success')) { - Logger.info('lxm--事件包含command和success字段'); - final bool success = event['success'] as bool; - Logger.info('lxm--命令执行成功状态: $success'); - - if (!success) { - Logger.warning('lxm--设备命令执行失败: ${event['command']}'); - return; - } + if (!event.containsKey('command') || !event.containsKey('success')) { + return; + } - // 根据命令类型处理不同信息 - final command = event['command']; - Logger.info('lxm--命令类型: $command (${command.runtimeType})'); - - if (command is int) { - Logger.info('lxm--基于命令ID处理: $command'); - // 基于命令ID处理 - _processDeviceInfoByCommandId(command, event); - } else if (command is String) { - Logger.info('lxm--基于命令名称处理: $command'); - // 基于命令名称处理 - _processDeviceInfoByCommandName(command, event); - } else { - Logger.warning('lxm--未知的命令类型: ${command.runtimeType}'); - } + final bool success = event['success'] as bool; + if (!success) { + Logger.w('BleManager', '设备命令执行失败: ${event['command']}'); + return; + } + + final command = event['command']; + if (command is int) { + _processDeviceInfoByCommandId(command, event); + } else if (command is String) { + _processDeviceInfoByCommandName(command, event); } else { - Logger.info('lxm--事件不包含command或success字段,跳过处理'); - Logger.info('lxm--事件包含的键: ${event.keys.toList()}'); + Logger.w('BleManager', '未知的命令类型: ${command.runtimeType}'); } - } catch (e) { - Logger.error('lxm--处理设备信息异常: ${e.toString()}'); - Logger.error('lxm--异常堆栈: ${StackTrace.current}'); + } catch (e, s) { + Logger.e('BleManager', '处理设备信息异常: $e', e, s); } } /// 根据命令ID处理设备信息 void _processDeviceInfoByCommandId( int commandId, Map data) { - Logger.info('lxm--_processDeviceInfoByCommandId被调用,命令ID: $commandId'); - Logger.info('lxm--命令数据: $data'); - switch (commandId) { case BleCommands.GET_VERSION: - Logger.info('lxm--处理版本信息命令'); _updateVersionInfoFromData(data); break; case BleCommands.GET_PRODUCT_ID: - Logger.info('lxm--处理产品ID命令'); _updateProductIdFromData(data); break; case BleCommands.GET_PRODUCT_COLOR: - Logger.info('lxm--处理产品颜色命令(暂未实现)'); break; case BleCommands.GET_BATTERY_INFO: - Logger.info('lxm--处理电池信息命令,准备调用_updateBatteryInfoFromData'); _updateBatteryInfoFromData(data); - Logger.info('lxm--电池信息处理完成'); break; case BleCommands.CONTROL_CODEC: - Logger.info('lxm--处理编解码控制命令'); - // 处理通话状态 - print(" CONTROL_CODEC: $commandId,$data"); - final bool codecSuccess = _isCodecControlSuccess(data); if (_awaitingCodecOpen) { - //如果正在等待打开编解码器 - _isCodecActive.value = codecSuccess; // 只在等待打开时更新状态 + _isCodecActive.value = codecSuccess; _awaitingCodecOpen = false; } else if (_awaitingCodecClose) { if (codecSuccess) { @@ -440,31 +379,21 @@ class BleManager extends GetxService { } _awaitingCodecClose = false; } - - if (codecSuccess) { - print("lxm--编解码控制成功 (rawData 第二字节非 0)"); - Logger.info('lxm--编解码控制成功 (rawData 第二字节非 0)'); - } else { - print("lxm--编解码控制失败 (rawData 为 [162, 0] 或无法解析)"); - Logger.warning('lxm--编解码控制失败 (rawData 为 [162, 0] 或无法解析)'); + if (!codecSuccess) { + Logger.w('BleManager', '编解码控制失败'); } - break; case BleCommands.GET_WAKEUP_VERSION: - Logger.info('lxm--处理唤醒语音版本命令'); _updateWakeupVersionFromData(data); break; case BleCommands.GET_VOICE_WAKEUP_STATUS: - Logger.info('[VoiceWakeup] 收到查询响应(0x14), data: $data'); _updateVoiceWakeupStatusFromData(data); break; case BleCommands.SET_VOICE_WAKEUP_STATUS: - Logger.info('[VoiceWakeup] 收到设置响应(0x15), data: $data'); _updateVoiceWakeupSetResultFromData(data); break; default: - Logger.warning('lxm--未处理的命令ID: $commandId,数据: $data'); - print(" 未处理的命令ID: $commandId,$data"); + Logger.w('BleManager', '未处理的命令ID: $commandId'); } } @@ -484,82 +413,46 @@ class BleManager extends GetxService { case 'productColor': break; case 'Error': - print(" Error: $commandName,$data"); + Logger.w('BleManager', '收到 Error 命令'); break; default: - print(" 未处理的命令名称: $commandName,$data"); - Logger.info('未处理的命令名称: $commandName'); + Logger.w('BleManager', '未处理的命令名称: $commandName'); } } /// 更新电池信息 void _updateBatteryInfoFromData(Map data) { try { - Logger.info('lxm--_updateBatteryInfoFromData被调用'); - Logger.info('lxm--接收到的原始数据: $data'); - - // 确保数据中包含电池信息 if (!data.containsKey('leftEarBattery') || !data.containsKey('rightEarBattery') || !data.containsKey('caseBattery')) { - Logger.warning('lxm--电池信息数据不完整,缺少必要字段'); - Logger.warning('lxm--数据包含的键: ${data.keys.toList()}'); + Logger.w('BleManager', '电池信息数据不完整'); return; } - Logger.info('lxm--原始电池数据解析:'); - Logger.info( - 'lxm-- leftEarBattery原始值: ${data['leftEarBattery']} (类型: ${data['leftEarBattery'].runtimeType})'); - Logger.info( - 'lxm-- rightEarBattery原始值: ${data['rightEarBattery']} (类型: ${data['rightEarBattery'].runtimeType})'); - Logger.info( - 'lxm-- caseBattery原始值: ${data['caseBattery']} (类型: ${data['caseBattery'].runtimeType})'); - Logger.info( - 'lxm-- leftEarCharging原始值: ${data['leftEarCharging']} (类型: ${data['leftEarCharging'].runtimeType})'); - Logger.info( - 'lxm-- rightEarCharging原始值: ${data['rightEarCharging']} (类型: ${data['rightEarCharging'].runtimeType})'); - Logger.info( - 'lxm-- caseCharging原始值: ${data['caseCharging']} (类型: ${data['caseCharging'].runtimeType})'); - Logger.info( - 'lxm-- batteryLevel原始值: ${data['batteryLevel']} (类型: ${data['batteryLevel']?.runtimeType})'); - - // 提取电池信息 final int leftBattery = (data['leftEarBattery'] as int? ?? 0) == 127 - ? -1 // 特殊值127转换为-1 + ? -1 : (data['leftEarBattery'] as int? ?? 0) > 100 - ? 0 // 大于100的值重置为0 - : (data['leftEarBattery'] as int? ?? 0); // 正常值 + ? 0 + : (data['leftEarBattery'] as int? ?? 0); final int rightBattery = (data['rightEarBattery'] as int? ?? 0) == 127 - ? -1 // 特殊值127转换为-1 + ? -1 : (data['rightEarBattery'] as int? ?? 0) > 100 - ? 0 // 大于100的值重置为0 - : (data['rightEarBattery'] as int? ?? 0); // 正常值 + ? 0 + : (data['rightEarBattery'] as int? ?? 0); final int caseBattery = (data['caseBattery'] as int? ?? 0) == 127 - ? -1 // 特殊值127转换为-1 + ? -1 : (data['caseBattery'] as int? ?? 0) > 100 - ? 0 // 大于100的值重置为0 - : (data['caseBattery'] as int? ?? 0); // 正常值 + ? 0 + : (data['caseBattery'] as int? ?? 0); final bool leftCharging = data['leftEarCharging'] as bool? ?? false; final bool rightCharging = data['rightEarCharging'] as bool? ?? false; final bool caseCharging = data['caseCharging'] as bool? ?? false; - // 获取整体电量(原生层使用左耳电量作为主要指示) final int overallBattery = data['batteryLevel'] as int? ?? leftBattery; - Logger.info('lxm--处理后的电池数据:'); - Logger.info('lxm-- leftBattery: $leftBattery'); - Logger.info('lxm-- rightBattery: $rightBattery'); - Logger.info('lxm-- caseBattery: $caseBattery'); - Logger.info('lxm-- leftCharging: $leftCharging'); - Logger.info('lxm-- rightCharging: $rightCharging'); - Logger.info('lxm-- caseCharging: $caseCharging'); - Logger.info('lxm-- overallBattery: $overallBattery'); - - Logger.info('lxm--准备调用_updateDeviceInfoIfNeeded'); - - // 更新设备信息 _updateDeviceInfoIfNeeded( batteryLevel: overallBattery, leftEarBattery: leftBattery, @@ -569,12 +462,8 @@ class BleManager extends GetxService { rightEarCharging: rightCharging, caseCharging: caseCharging, ); - - Logger.info( - 'lxm--设备电池信息已更新: 电量=$overallBattery%, 左耳=$leftBattery%, 右耳=$rightBattery%, 充电仓=$caseBattery%'); - } catch (e) { - Logger.error('lxm--更新电池信息失败: ${e.toString()}'); - Logger.error('lxm--错误堆栈: ${StackTrace.current}'); + } catch (e, s) { + Logger.e('BleManager', '更新电池信息失败: $e', e, s); } } @@ -718,18 +607,8 @@ class BleManager extends GetxService { String? wakeupLeftVersion, String? wakeupRightVersion, }) { - Logger.info('lxm--_updateDeviceInfoIfNeeded被调用'); - Logger.info( - 'lxm--传入参数: batteryLevel=$batteryLevel, leftEarBattery=$leftEarBattery, rightEarBattery=$rightEarBattery, caseBattery=$caseBattery'); - Logger.info( - 'lxm--充电状态: leftEarCharging=$leftEarCharging, rightEarCharging=$rightEarCharging, caseCharging=$caseCharging'); - Logger.info('lxm--当前deviceInfo.value是否为null: ${deviceInfo.value == null}'); - // 如果设备信息已存在,则更新 if (deviceInfo.value != null) { - Logger.info('lxm--设备信息已存在,进行更新操作'); - Logger.info('lxm--更新前的设备信息: ${deviceInfo.value}'); - deviceInfo.value = deviceInfo.value!.copyWith( batteryLevel: batteryLevel ?? deviceInfo.value?.batteryLevel, leftEarBattery: _getValidBatteryValue( @@ -751,20 +630,17 @@ class BleManager extends GetxService { wakeupRightVersion: wakeupRightVersion ?? deviceInfo.value!.wakeupRightVersion, ); - - Logger.info('lxm--更新后的设备信息: ${deviceInfo.value}'); } // 创建设备信息 // 如果设备信息不存在,但有地址和名称,则创建新的设备信息 else if (deviceInfo.value == null && _isConnected.value && (firmwareVersion != null || batteryLevel != null)) { - Logger.info('lxm--设备信息不存在,创建新的设备信息对象'); - // 使用保存的设备信息创建新的DeviceInfo对象 String deviceAddress = currentDeviceAddress ?? ""; String deviceName = _currentDeviceName ?? ""; - Logger.info('lxm--创建新的设备信息对象: address=$deviceAddress, name=$deviceName'); + Logger.i('BleManager', + '创建新的设备信息对象: address=$deviceAddress, name=$deviceName'); deviceInfo.value = DeviceInfo( address: deviceAddress, name: deviceName, @@ -781,11 +657,6 @@ class BleManager extends GetxService { wakeupLeftVersion: wakeupLeftVersion ?? '', wakeupRightVersion: wakeupRightVersion ?? '', ); - - Logger.info('lxm--新创建的设备信息: ${deviceInfo.value}'); - } else { - Logger.info( - 'lxm--不满足更新条件: deviceInfo.value == null: ${deviceInfo.value == null}, _isConnected.value: ${_isConnected.value}, firmwareVersion: $firmwareVersion, batteryLevel: $batteryLevel'); } } @@ -1053,7 +924,7 @@ class BleManager extends GetxService { ); stsCmei = matchedDevice.cmei; } catch (_) {} - Logger.info('lxm--当前设备 CMEI: $stsCmei (MAC=$mac)'); + Logger.i('BleManager', '当前设备 CMEI: $stsCmei (MAC=$mac)'); final config = { // STS 模式路由 @@ -1139,35 +1010,17 @@ class BleManager extends GetxService { }); } - Logger.info('lxm--准备调用AgentService.startAgentService启动BLE服务'); final result = await AgentService.startAgentService(config); - Logger.info('lxm--AgentService.startAgentService调用结果: $result'); + Logger.i('BleManager', 'AgentService.startAgentService 结果: $result'); if (result) { - Logger.info('lxm--BLE服务启动成功'); - - // 添加延迟以等待设备连接 - Logger.info('lxm--等待2秒让设备连接'); - //await Future.delayed(const Duration(seconds: 2)); - - // 检查连接状态 - Logger.info('lxm--检查设备连接状态'); final isConnected = await _bleService.isConnected(); - Logger.info('lxm--设备连接状态检查结果: $isConnected'); if (isConnected) { - Logger.info('lxm--设备已连接,更新连接状态'); _isConnected.value = true; _connectionState.value = BleConnectionState.connected; - - // 如果设备信息存在,则获取详细信息 - Logger.info('lxm--准备获取设备详细信息'); - if (deviceInfo.value != null) { - // 获取详细设备信息 - // fetchDeviceInfo(); - } } } else { - Logger.error('BLE服务启动失败'); + Logger.e('BleManager', 'BLE服务启动失败'); } return result; diff --git a/lib/data/services/speech_impl/azure_asr_service.dart b/lib/data/services/speech_impl/azure_asr_service.dart index cbb5ebff9..b1e610f88 100644 --- a/lib/data/services/speech_impl/azure_asr_service.dart +++ b/lib/data/services/speech_impl/azure_asr_service.dart @@ -307,44 +307,25 @@ class AzureAsrService extends GetxService implements AsrService { switch (eventType) { case 'audioData': final Uint8List data = eventMap['data'] as Uint8List? ?? Uint8List(0); - final double timestamp = - (eventMap['timestamp'] as num?)?.toDouble() ?? 0.0; - final int size = eventMap['size'] as int? ?? 0; - print('接收到音频数据: 大小=${size}字节, 时间戳=${timestamp}'); - Logger.debug('接收到音频数据: 大小=${size}字节, 时间戳=${timestamp}'); - - // 发送到音频数据流 _audioDataStreamController?.add(data); - break; } } /// 获取音频数据流 Stream? getAudioDataStream() { - print("getAudioDataStream"); _audioDataStreamController ??= StreamController.broadcast(); return _audioDataStreamController?.stream; } /// 处理来自原生端的识别事件 void _handleRecognitionEvent(dynamic event) { - if (event is! Map) { - print('🔴[ASR-DBG] 非 Map 事件被丢弃: ${event.runtimeType}'); - return; - } - if (_eventStreamController == null) { - print('🔴[ASR-DBG] _eventStreamController 为 null,事件被丢弃: $event'); - return; - } + if (event is! Map) return; + if (_eventStreamController == null) return; final Map eventMap = event; final String eventType = eventMap['type'] as String? ?? ''; final String provider = eventMap['provider'] as String? ?? ''; - if (eventType != 'nativeLog' && eventType != 'audioData') { - print( - '🔴[ASR-DBG] 原生事件抵达 azure_asr_service: type=$eventType, provider=$provider, text=${eventMap['text']}'); - } if (provider.isNotEmpty) { if (provider != _latestAsrProvider) { _latestAsrProvider = provider; diff --git a/lib/data/services/speech_impl/azure_ast_service.dart b/lib/data/services/speech_impl/azure_ast_service.dart index 1d2124a08..cbb3364b7 100644 --- a/lib/data/services/speech_impl/azure_ast_service.dart +++ b/lib/data/services/speech_impl/azure_ast_service.dart @@ -122,7 +122,7 @@ class AzureAstService extends GetxService implements AstService { final String utteranceId = eventMap['utteranceId'] as String? ?? ''; final String text = eventMap['text'] as String? ?? ''; final String detectedLanguage = eventMap['language'] as String? ?? ''; - Logger.info('[STS] 识别中 [$serviceId]: text=$text'); + Logger.d('AzureAST', '[STS] 识别中 [$serviceId]: text=$text'); _eventStreamController?.add(ASTEvent( type: ASTEventType.intermediateResult, serviceId: serviceId, @@ -137,7 +137,7 @@ class AzureAstService extends GetxService implements AstService { final String text = eventMap['translatedText'] as String? ?? ''; final String detectedLanguage = eventMap['targetLanguage'] as String? ?? ''; - Logger.info('[STS] 翻译中 [$serviceId]: text=$text'); + Logger.d('AzureAST', '[STS] 翻译中 [$serviceId]: text=$text'); _eventStreamController?.add(ASTEvent( type: ASTEventType.translationInterim, serviceId: serviceId, diff --git a/lib/data/services/usage_stats_service.dart b/lib/data/services/usage_stats_service.dart index 969e2ea55..117539b8a 100644 --- a/lib/data/services/usage_stats_service.dart +++ b/lib/data/services/usage_stats_service.dart @@ -33,7 +33,7 @@ class UsageStatsService extends GetxService { /// 初始化服务 void _initializeService() { _loadTodayTranslationStats(); - Logger.info('lxm--使用量统计服务初始化完成'); + Logger.i('UsageStats', '使用量统计服务初始化完成'); } /// 加载当日翻译统计数据 @@ -243,11 +243,11 @@ class UsageStatsService extends GetxService { }, }; - Logger.info('lxm---MEET用量上报参数: $params'); + Logger.d('UsageStats', 'MEET用量上报参数: $params'); final response = await Api.usagesResPoints(params); - Logger.info('lxm---MEET用量上报响应: $response'); + Logger.d('UsageStats', 'MEET用量上报响应: $response'); _applyUsageResponse(response); } catch (e) { @@ -420,11 +420,11 @@ class UsageStatsService extends GetxService { }, }; - Logger.info('lxm---ASR用量上报参数: $params'); + Logger.d('UsageStats', 'ASR用量上报参数: $params'); final response = await Api.usagesResPoints(params); - Logger.info('lxm---ASR用量上报响应: $response'); + Logger.d('UsageStats', 'ASR用量上报响应: $response'); _applyUsageResponse(response); } catch (e) { diff --git a/lib/data/services/volcano_translation_service.dart b/lib/data/services/volcano_translation_service.dart index 9032dc43a..c6717b3a7 100644 --- a/lib/data/services/volcano_translation_service.dart +++ b/lib/data/services/volcano_translation_service.dart @@ -76,11 +76,10 @@ class VolcanoTranslationService extends GetxService { } _isInitialized = true; - Logger.info( - 'lxm---Volcano Translation Service initialized成功, accessKey: $_accessKey, region: $_region, service: $_service,secretKey: $_secretKey'); + Logger.i('VolcanoTrans', 'Volcano Translation Service initialized 成功'); return true; } catch (e) { - Logger.error('lxm---Volcano Translation Service initialized失败,$e'); + Logger.e('VolcanoTrans', 'Volcano Translation Service 初始化失败: $e'); return false; } } diff --git a/lib/modules/home/controllers/home_controller.dart b/lib/modules/home/controllers/home_controller.dart index 55d431d59..fa75943b7 100644 --- a/lib/modules/home/controllers/home_controller.dart +++ b/lib/modules/home/controllers/home_controller.dart @@ -55,22 +55,6 @@ class HomeController extends GetxController { final firmwareVersion = ''.obs; void updateDeviceInfo(DeviceInfo? newDeviceInfo) { - Logger.d(_tag, 'lxm--updateDeviceInfo被调用'); - Logger.d(_tag, 'lxm--接收到的DeviceInfo: $newDeviceInfo'); - - if (newDeviceInfo != null) { - Logger.d(_tag, 'lxm--原始数据 - 左耳电量: ${newDeviceInfo.leftEarBattery}'); - Logger.d(_tag, 'lxm--原始数据 - 右耳电量: ${newDeviceInfo.rightEarBattery}'); - Logger.d(_tag, 'lxm--原始数据 - 充电仓电量: ${newDeviceInfo.caseBattery}'); - Logger.d(_tag, 'lxm--原始数据 - 左耳充电: ${newDeviceInfo.leftEarCharging}'); - Logger.d(_tag, 'lxm--原始数据 - 右耳充电: ${newDeviceInfo.rightEarCharging}'); - Logger.d(_tag, 'lxm--原始数据 - 充电仓充电: ${newDeviceInfo.caseCharging}'); - Logger.d(_tag, 'lxm--原始数据 - 固件版本: ${newDeviceInfo.firmwareVersion}'); - } else { - Logger.d(_tag, 'lxm--接收到的DeviceInfo为null'); - } - - // 只有当新数据不为0时才更新电池值,否则保持原值 leftEarBattery.value = newDeviceInfo?.leftEarBattery ?? 0; rightEarBattery.value = newDeviceInfo?.rightEarBattery ?? 0; caseBattery.value = newDeviceInfo?.caseBattery ?? 0; @@ -78,16 +62,6 @@ class HomeController extends GetxController { rightEarCharging.value = newDeviceInfo?.rightEarCharging ?? false; caseCharging.value = newDeviceInfo?.caseCharging ?? false; firmwareVersion.value = newDeviceInfo?.firmwareVersion ?? ''; - - Logger.d(_tag, 'lxm--更新后的值 - 左耳电量: ${leftEarBattery.value}'); - Logger.d(_tag, 'lxm--更新后的值 - 右耳电量: ${rightEarBattery.value}'); - Logger.d(_tag, 'lxm--更新后的值 - 充电仓电量: ${caseBattery.value}'); - Logger.d(_tag, 'lxm--更新后的值 - 左耳充电: ${leftEarCharging.value}'); - Logger.d(_tag, 'lxm--更新后的值 - 右耳充电: ${rightEarCharging.value}'); - Logger.d(_tag, 'lxm--更新后的值 - 充电仓充电: ${caseCharging.value}'); - Logger.d(_tag, 'lxm--更新后的值 - 固件版本: ${firmwareVersion.value}'); - // rightEarCharging.refresh(); - //update(); } Worker? _deviceInfoWorker; @@ -138,15 +112,7 @@ class HomeController extends GetxController { void _setupStateListeners() { _deviceInfoWorker = ever(_bleManager.deviceInfo, (DeviceInfo? info) { - Logger.d(_tag, 'lxm--_deviceInfoWorker监听器被触发'); - Logger.d(_tag, 'lxm--从BleManager接收到的DeviceInfo: $info'); - if (info != null) { - Logger.d(_tag, 'lxm--DeviceInfo不为null,调用updateDeviceInfo'); - updateDeviceInfo(info); - } else { - Logger.d(_tag, 'lxm--DeviceInfo为null,跳过更新'); - } - //update(); + if (info != null) updateDeviceInfo(info); }); _classicBluetoothWorker = diff --git a/lib/modules/home/views/home_view.dart b/lib/modules/home/views/home_view.dart index cc2c15243..866c4b868 100644 --- a/lib/modules/home/views/home_view.dart +++ b/lib/modules/home/views/home_view.dart @@ -519,10 +519,6 @@ class HomeView extends GetView { final caseCharging = controller.caseCharging.value; final isConnected = controller.isFullyConnectedRx.value; - print( - 'lxm--电池信息UI - 左耳电量: $leftBattery, 右耳电量: $rightBattery, 充电仓电量: $caseBattery, ' - '充电(L/R/C): $leftEarCharging/$rightEarCharging/$caseCharging, 已连接: $isConnected'); - // 判断是否显示充电盒:充电盒电量大于0且设备已连接 final shouldShowCase = caseBattery > 0 && isConnected; diff --git a/lib/modules/translation/controllers/translation_controller.dart b/lib/modules/translation/controllers/translation_controller.dart index 1fc06d0a9..0962a74f8 100644 --- a/lib/modules/translation/controllers/translation_controller.dart +++ b/lib/modules/translation/controllers/translation_controller.dart @@ -1040,16 +1040,16 @@ class TranslationController extends GetxController with WidgetsBindingObserver { return; } if (currentMode.value == 'simultaneous') { - Logger.info('liwei-------- 开始语音识别,模式:同声传译,ASR phone_call'); + Logger.i('Translation', '开始语音识别,模式:同声传译,ASR phone_call'); await _startAsrService('phone_call'); } else if (currentMode.value == 'faceToFace') { - Logger.info('iwei-------- 开始语音识别,模式:面对面,ASR push_to_talk'); + Logger.i('Translation', '开始语音识别,模式:面对面,ASR push_to_talk'); await _startAsrService('push_to_talk'); } else if (currentMode.value == 'call') { - Logger.info('iwei-------- 通话模式:AST端到端服务已启动,跳过Azure ASR'); + Logger.i('Translation', '通话模式:AST端到端服务已启动,跳过Azure ASR'); } else { - Logger.info( - 'iwei-------- 开始语音识别,模式:${currentMode.value},ASR 模式:normal'); + Logger.i('Translation', + '开始语音识别,模式:${currentMode.value},ASR 模式:normal'); await _startAsrService('normal'); } await _finalizeRecognitionStart(); @@ -1174,10 +1174,10 @@ class TranslationController extends GetxController with WidgetsBindingObserver { /// 处理语音识别事件 /// [event] 识别事件 void _handleRecognitionEvent(RecognitionEvent event) { - print( - '🟣[TRANS-DBG] _handleRecognitionEvent: type=${event.type}, text=${event.text}, provider=${event.provider}, detectedLang=${event.detectedLanguage}, currentMode=${currentMode.value}'); final String asrProvider = event.provider; - if (asrProvider.isNotEmpty) Logger.info('ASR provider: $asrProvider'); + if (asrProvider.isNotEmpty) { + Logger.d('Translation', 'ASR provider: $asrProvider'); + } switch (event.type) { case RecognitionEventType.finalResult: if (event.text.isEmpty) break; @@ -1185,12 +1185,11 @@ class TranslationController extends GetxController with WidgetsBindingObserver { detectedLanguageCode = currentMode.value == 'call' ? targetLanguageCode.value : event.detectedLanguage; - Logger.info("处理识别完成:${event.text}"); + Logger.d('Translation', '处理识别完成: ${event.text}'); if (currentMode.value != 'faceToFace') { handleFinalResult(event.text); } else { faceToFaceRecognitionText.value += event.text; - Logger.info('lxm-面对面翻译识别文本更新: ${faceToFaceRecognitionText.value}'); } if (currentMode.value == 'faceToFace' && activeSpeaker.value == 0) { handleFinalResult(faceToFaceRecognitionText.value); @@ -1203,7 +1202,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { if (event.text.isEmpty) break; //通话模式下:己方语言即为源语言,无需判断 detectedLanguageCode = sourceLanguageCode.value; - Logger.info("lxm---处理己方识别完成:${event.text}"); + Logger.d('Translation', '处理己方识别完成: ${event.text}'); handleFinalResult(event.text); break; @@ -1213,7 +1212,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { detectedLanguageCode = currentMode.value == 'call' ? targetLanguageCode.value : event.detectedLanguage; - Logger.info("处理识别中事件:${event.text}"); + Logger.d('Translation', '处理识别中: ${event.text}'); handleIntermediateResult(event.text); break; @@ -1247,7 +1246,8 @@ class TranslationController extends GetxController with WidgetsBindingObserver { /// 处理 AST(语音识别+翻译一体)事件 /// 按 serviceId 区分双路(A=己方, B=对方),用 utteranceId 匹配同一句话的事件 void _handleAstEvent(ASTEvent event) { - Logger.info('[STS] _handleAstEvent 收到: type=${event.type}, serviceId=${event.serviceId}, text=${event.text}'); + Logger.d('Translation', + '[STS] _handleAstEvent: type=${event.type}, serviceId=${event.serviceId}'); // 根据 serviceId 确定语言方向 final String srcCode = event.serviceId == "A" ? sourceLanguageCode.value @@ -1259,7 +1259,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { switch (event.type) { case ASTEventType.intermediateResult: if (event.text.isEmpty) break; - Logger.info('AST 识别中 [${event.serviceId}]: ${event.text}'); + Logger.d('Translation', 'AST 识别中 [${event.serviceId}]: ${event.text}'); currentSessionId ??= DateTime.now().millisecondsSinceEpoch.toString(); // 按 utteranceId 查找已有项 @@ -1301,7 +1301,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { case ASTEventType.finalResult: if (event.text.isEmpty) break; - Logger.info('AST 识别完成 [${event.serviceId}]: ${event.text}'); + Logger.i('Translation', 'AST 识别完成 [${event.serviceId}]: ${event.text}'); currentSessionId ??= DateTime.now().millisecondsSinceEpoch.toString(); TranslationItem? target; @@ -1352,7 +1352,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { case ASTEventType.translationInterim: if (event.text.isEmpty) break; - Logger.info('AST 翻译中 [${event.serviceId}]: ${event.text}'); + Logger.d('Translation', 'AST 翻译中 [${event.serviceId}]: ${event.text}'); currentSessionId ??= DateTime.now().millisecondsSinceEpoch.toString(); TranslationItem? target; @@ -1390,7 +1390,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { case ASTEventType.translationResult: if (event.text.isEmpty) break; - Logger.info('AST 翻译完成 [${event.serviceId}]: ${event.text}'); + Logger.i('Translation', 'AST 翻译完成 [${event.serviceId}]: ${event.text}'); currentSessionId ??= DateTime.now().millisecondsSinceEpoch.toString(); TranslationItem? target; @@ -1534,17 +1534,12 @@ class TranslationController extends GetxController with WidgetsBindingObserver { // 防抖处理翻译请求 _translationDebounceTimer?.cancel(); _translationDebounceTimer = Timer(const Duration(milliseconds: 300), () { - final lastIsInter = translationHistory.isNotEmpty ? translationHistory.last.isIntermediate : null; - final lastSrc = translationHistory.isNotEmpty ? translationHistory.last.sourceText : ''; - print('🟣[TRANS-DBG] 中间结果防抖触发: histEmpty=${translationHistory.isEmpty}, lastIsInter=$lastIsInter, lastSrcLen=${lastSrc.length}'); if (translationHistory.isNotEmpty && translationHistory.last.isIntermediate && translationHistory.last.sourceText.isNotEmpty) { translateText(translationHistory.last.sourceText, translationHistory.last.timestamp, isFinal: false); - } else { - print('🟣[TRANS-DBG] 中间结果防抖未调用 translateText(条件不满足)'); } }); } @@ -1552,11 +1547,7 @@ class TranslationController extends GetxController with WidgetsBindingObserver { /// 处理最终识别结果 /// [text] 识别的文本 Future handleFinalResult(String text) async { - print('🟣[TRANS-DBG] handleFinalResult 入口: text=$text, mode=${currentMode.value}, historyLen=${translationHistory.length}, lastIntermediate=${translationHistory.isNotEmpty ? translationHistory.last.isIntermediate : "N/A"}'); - if (text.isEmpty) { - print('🟣[TRANS-DBG] handleFinalResult 因 text 为空直接返回'); - return; - } + if (text.isEmpty) return; // 更新当前项 if (translationHistory.isNotEmpty && @@ -1606,30 +1597,22 @@ class TranslationController extends GetxController with WidgetsBindingObserver { /// 返回翻译结果 Future translateText(String sourceText, DateTime timestamp, {bool isFinal = false}) async { - print('🟣[TRANS-DBG] translateText 入口: text=$sourceText, isFinal=$isFinal, mode=${currentMode.value}, src=${sourceLanguageCode.value}, tgt=${targetLanguageCode.value}, detected=$detectedLanguageCode'); - if (sourceText.isEmpty) { - print('🟣[TRANS-DBG] translateText 因 sourceText 为空直接返回'); - return null; - } + if (sourceText.isEmpty) return null; isTranslating.value = true; String? translationResult; try { final languageCodes = _determineLanguageCodes(); - print('🟣[TRANS-DBG] 准备调用翻译 API: src=${languageCodes['source']} tgt=${languageCodes['target']}'); translationResult = await _performTranslation( sourceText, languageCodes['source']!, languageCodes['target']!); - print('🟣[TRANS-DBG] 翻译 API 返回: result=$translationResult'); if (translationResult != null) { await _updateTranslationHistory( sourceText, translationResult, timestamp, languageCodes, isFinal); - } else { - print('🟣[TRANS-DBG] 翻译 API 返回 null,不更新历史也不播报'); } } catch (e, st) { - print('🟣[TRANS-DBG] 翻译失败: ${e.toString()}\n$st'); + Logger.e('Translation', '翻译失败: $e', e, st); } finally { isTranslating.value = false; } @@ -1743,18 +1726,10 @@ class TranslationController extends GetxController with WidgetsBindingObserver { await _updateFloatingWindowWithTranslation(translationHistory[index]); } - // 添加TranslationItem日志打印 if (isFinal) { final item = translationHistory[index]; - Logger.info('lxm-翻译完成 - TranslationItem详情: ' - '源文本: ${item.sourceText}, ' - '翻译文本: ${item.translatedText}, ' - '源语言: ${item.sourceLanguageCode}, ' - '目标语言: ${item.targetLanguageCode}, ' - '时间戳: ${item.timestamp.toIso8601String()}, ' - '会话ID: ${item.sessionId}, ' - '是否会话首项: ${item.isFirstInSession}, ' - '是否中间结果: ${item.isIntermediate}'); + Logger.i('Translation', + '翻译完成: ${item.sourceLanguageCode}→${item.targetLanguageCode} ${item.sourceText.length}字符'); } if (isFinal) { @@ -1805,11 +1780,8 @@ class TranslationController extends GetxController with WidgetsBindingObserver { /// 处理TTS播放 /// [translationResult] 翻译结果 Future _handleTtsPlayback(String translationResult) async { - print('🟣[TRANS-DBG] _handleTtsPlayback 入口: isTtsEnabled=${isTtsEnabled.value}, text=$translationResult'); if (isTtsEnabled.value) { await playTranslatedText(translationResult); - } else { - print('🟣[TRANS-DBG] TTS 已禁用,跳过播报'); } } diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt index e975037c5..281b0dfd8 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt @@ -857,16 +857,12 @@ object AgentService : CoroutineScope { stopIdleCheck() // 先停止现有的检查 if (!isRecognitionActive) return - Log.d(TAG, "启动空闲检测,超时时间: ${idleSeconds}秒,模式: $currentRecognitionMode") - idleCheckJob = launch { try { delay(idleSeconds * 1000L) - Log.d(TAG, "空闲检测触发,isActive: $isActive, isRecognitionActive: $isRecognitionActive, isTtsSpeaking: $isTtsSpeaking, isAiStreaming: $isAiStreaming, mode: $mode") if (isActive && isRecognitionActive) { if (!isTtsSpeaking && !isAiStreaming) { - // 条件满足:TTS未播放且AI未流式输出,执行自动停止 - Log.d(TAG, "空闲检测触发自动停止,模式: $currentRecognitionMode") + Log.i(TAG, "空闲检测触发自动停止,模式: $currentRecognitionMode") BleService.closeCodec() if (currentRecognitionMode != "phone_call"){ stopRecognition() @@ -878,8 +874,6 @@ object AgentService : CoroutineScope { ) ) } else { - // 条件不满足:TTS或AI仍在工作中,重新调度计时器等待下一轮检查 - Log.d(TAG, "空闲检测条件不满足(tts=$isTtsSpeaking, ai=$isAiStreaming),重新调度") startIdleCheck(mode, idleSeconds) } } @@ -897,7 +891,6 @@ object AgentService : CoroutineScope { private fun stopIdleCheck() { idleCheckJob?.cancel() idleCheckJob = null - Log.d(TAG, "空闲检测已停止") } /** @@ -1009,16 +1002,13 @@ object AgentService : CoroutineScope { fun recognizeCallback(): Boolean { try { - Log.d(TAG, "recognizeCallback") val success = azureAsrHelper?.setupEventListeners(object : AzureAsrHelper.ContinuousRecognizeCallback { override fun onRecognizing(sessionid:String, recognizing: String, detectedLanguage: String) { - Log.d(TAG, "liwei-------- onRecognizing: $sessionid") pendingProcessJob?.cancel() if (recognizing.isNotEmpty()&&isKeepResult==true) { // 检测到语音,更新状态 _hasSpeechDetected.set(true) - Log.d(TAG, "ai识别中重置定时器") restartIdleCheck() if(currsessionAsrId.isEmpty()) { currsessionAsrId = sessionid @@ -1147,7 +1137,6 @@ object AgentService : CoroutineScope { if (currentRecognitionMode == "push_to_talk") { //按住说话 if (recognitionResult.isEmpty()){ - Log.d(TAG, "liwei-------- onSessionStopped:currentRecognitionResult $currentRecognitionResult") recognitionResult+= currentRecognitionResult currentRecognitionResult = "" } diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleAgent.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleAgent.kt index cbf330fe2..8a141a592 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleAgent.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/BleAgent.kt @@ -64,7 +64,7 @@ object BleAgent : BleService.Callback, AgentServiceListener { * 设置是否可以唤醒 */ fun setCanWakeUp(canWakeUp: Boolean) { - Log.d(TAG, "liwei--------------设置是否可以唤醒: $canWakeUp") + Log.i(TAG, "设置是否可以唤醒: $canWakeUp") isCanWakeUp = canWakeUp } @@ -153,19 +153,17 @@ object BleAgent : BleService.Callback, AgentServiceListener { } override fun onAudioDataReceived(data: ByteArray, channel: Int) { - // Log.d(TAG, "onAudioDataReceived, data: ${data.size}") AgentService.pushAudioData(data) - // 可选:处理音频数据 } /** * 处理唤醒信号 * 在收到唤醒信号时启动语音识别 */ override fun onWakeupSignalReceived() { - Log.d(TAG, "liwei-------------- 收到唤醒信号,启动语音识别${AgentService.isRecognitionActive}") + Log.i(TAG, "收到唤醒信号,启动语音识别 active=${AgentService.isRecognitionActive}") if (!isCanWakeUp) { - Log.d(TAG, "liwei-------------- 当前不可以唤醒") + Log.i(TAG, "当前不可以唤醒") return } // 停止当前TTS,避免冲突 @@ -184,12 +182,12 @@ object BleAgent : BleService.Callback, AgentServiceListener { * 处理开始 AI 单次对话 */ override fun onStartSingleDialogReceived() { - Log.d(TAG, "liwei-------------- 收到开始 AI 单次对话指令") + Log.i(TAG, "收到开始 AI 单次对话指令") startSingleDialog() } override fun onEndSingleDialogReceived() { - Log.d(TAG, "liwei-------------- 收到结束 AI 单次对话指令") + Log.i(TAG, "收到结束 AI 单次对话指令") // 停止语音识别 stopListening() } diff --git a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt index da25d8224..9a837b134 100644 --- a/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt +++ b/local_plugins/azure_speech/android/src/main/kotlin/com/yunqiinnovation/azure_speech/AzureAsrToAsr.kt @@ -121,11 +121,8 @@ class IntegratedSpeechTranslationService( val sendLen = (ttsdata.size / multiple) * multiple if (sendLen > 0) { val chunk = ttsdata.copyOfRange(0, sendLen) - Log.d(TAG, "按${multiple}字节对齐发送音频: ${chunk.size} 字节,缓存剩余: ${ttsdata.size - sendLen}") eventCallback?.onSynthesisAudioGenerated(utteranceId, text, chunk) ttsdata = ttsdata.copyOfRange(sendLen, ttsdata.size) - } else { - Log.d(TAG, "暂未够${multiple}字节,当前缓存: ${ttsdata.size}") } } /** @@ -397,10 +394,6 @@ class IntegratedSpeechTranslationService( isInUtterance.set(true) } val uttId = currentUtteranceId ?: nextUtteranceId() - Log.d( - TAG, - "识别中事件[${uttId}]: ${event.result.text},serviceConfig.sourceLanguage:${serviceConfig.sourceLanguage}" - ) eventCallback?.onRecognizing( uttId, event.result.text, @@ -413,7 +406,6 @@ class IntegratedSpeechTranslationService( // 取消上一次“识别中翻译”任务,避免旧翻译结果覆盖新结果 recognizingTranslationJob?.cancel() recognizingTranslationJob = launch { - Log.d(TAG, "识别中翻译触发: ${event.result.text}") processTranslationOnly(uttId, event.result.text) } } @@ -433,23 +425,15 @@ class IntegratedSpeechTranslationService( serviceConfig.sourceLanguage, confidence ) - Log.d( - TAG, - "识别完成事件[${uttId}]: ${event.result.text},serviceConfig.sourceLanguage:${serviceConfig.sourceLanguage}" - ) + Log.i(TAG, "识别完成[${uttId}]: ${event.result.text}") // 只有在服务仍在运行时才触发翻译流程 if (serviceState.isRecognizing.get()) { isInUtterance.set(false) currentUtteranceId = null launch { - // 识别完成时,马上打断上一次“识别中”的翻译,但不要在主线程 join cancelRecognizingTranslationJobSafely() - Log.d(TAG, "触发最终翻译流程: ${event.result.text}") processTranslationAndSynthesis(uttId, event.result.text) - } - } else { - Log.d(TAG, "服务已停止,跳过翻译流程: ${event.result.text}") } } } @@ -524,8 +508,7 @@ class IntegratedSpeechTranslationService( // 合成开始事件 SynthesisStarted.addEventListener { _, _ -> - Log.d(TAG, "合成开始事件") - ttsdata = ByteArray(0) + ttsdata = ByteArray(0) serviceState.isSynthesizing.set(true) val uttId = currentSynthesisId ?: "" val text = currentSynthesisText ?: "" @@ -533,11 +516,9 @@ class IntegratedSpeechTranslationService( eventCallback?.onStateChanged("Synthesis", true) } - // 合成进行中事件 + // 合成进行中事件(高频:每音频包触发) Synthesizing.addEventListener { _, event -> - Log.d(TAG, "合成进行中事件") - // 计算进度(简化版) - val progress = 0.5f // 实际应用中可以根据音频数据计算 + val progress = 0.5f val uttId = currentSynthesisId ?: "" val text = currentSynthesisText ?: "" eventCallback?.onSynthesisProgress(uttId, text, progress) @@ -548,7 +529,6 @@ class IntegratedSpeechTranslationService( // 合成完成事件 SynthesisCompleted.addEventListener { _, event -> - Log.d(TAG, "合成完成事件") val uttId = currentSynthesisId ?: "" val text = currentSynthesisText ?: "" eventCallback?.onSynthesisCompleted(uttId, text) @@ -559,7 +539,7 @@ class IntegratedSpeechTranslationService( // 合成取消事件 SynthesisCanceled.addEventListener { _, event -> - Log.d(TAG, "合成取消事件") + Log.w(TAG, "合成取消事件") ttsdata = ByteArray(0) serviceState.isSynthesizing.set(false) val reason = event.result.reason @@ -744,7 +724,6 @@ class IntegratedSpeechTranslationService( serviceState.isTranslating.set(true) eventCallback?.onTranslationStarted(targetUtteranceId, targetText) eventCallback?.onStateChanged("Translation", true) - Log.d(TAG, "翻译开始${targetText}") try { val srcLang = if (serviceConfig.translationSourceLanguage.isNotEmpty()) serviceConfig.translationSourceLanguage else serviceConfig.sourceLanguage val tgtLang = if (serviceConfig.translationTargetLanguage.isNotEmpty()) serviceConfig.translationTargetLanguage else serviceConfig.targetLanguage @@ -767,7 +746,6 @@ class IntegratedSpeechTranslationService( when { translationResult?.success == true && !translationResult.translatedText.isNullOrEmpty() -> { - Log.d(TAG, "翻译成功${translationResult.translatedText}") eventCallback?.onTranslated( targetUtteranceId, targetText, @@ -816,7 +794,6 @@ class IntegratedSpeechTranslationService( } try { - Log.d(TAG, "开始语音合成: $text") serviceState.isSynthesizing.set(true) // 在开始时记录当前合成上下文,并抛出开始事件 @@ -830,16 +807,9 @@ class IntegratedSpeechTranslationService( val result = synthesizer?.SpeakSsmlAsync(ssml)?.get() if (result?.reason == ResultReason.SynthesizingAudioCompleted) { - val playbackStatus = - if (serviceConfig.enableAudioPlayback) "音频已播放" else "音频已合成但未播放" - Log.d(TAG, "语音合成成功,$playbackStatus") - - // 获取原始音频数据 val rawAudioData = result.audioData - - Log.d(TAG, "语音合成成功,发送音频: ${ttsdata.size} 字节,缓存剩余: ${ttsdata.size}") - eventCallback?.onSynthesisAudioGenerated(utteranceId, text, ttsdata) - ttsdata = ByteArray(0) + eventCallback?.onSynthesisAudioGenerated(utteranceId, text, ttsdata) + ttsdata = ByteArray(0) return rawAudioData } else { Log.e(TAG, "语音合成失败: ${result?.reason}") @@ -875,22 +845,12 @@ class IntegratedSpeechTranslationService( * - text: 待翻译的源文本 */ private suspend fun processTranslationOnly(utteranceId: String, text: String) { - // 若服务已停止,直接跳过 - if (!serviceState.isRecognizing.get()) { - Log.d(TAG, "服务已停止,取消识别中翻译流程: $text") - return - } - - // 若已有翻译在进行,直接退出(避免并发) - if (serviceState.isTranslating.get()) { - Log.d(TAG, "已有翻译进行中,识别中翻译跳过: $text") - return - } + if (!serviceState.isRecognizing.get()) return + if (serviceState.isTranslating.get()) return serviceState.isTranslating.set(true) eventCallback?.onTranslationStarted(utteranceId, text) eventCallback?.onStateChanged("Translation", true) - Log.d(TAG, "识别中翻译开始: $text") try { val srcLang = if (serviceConfig.translationSourceLanguage.isNotEmpty()) serviceConfig.translationSourceLanguage else serviceConfig.sourceLanguage @@ -905,8 +865,6 @@ class IntegratedSpeechTranslationService( when { translationResult?.success == true && !translationResult.translatedText.isNullOrEmpty() -> { - Log.d(TAG, "识别中翻译成功: ${translationResult.translatedText}") - // 使用“识别中”专用的临时翻译回调,区分最终翻译 eventCallback?.onInterimTranslated( utteranceId, text, @@ -916,18 +874,15 @@ class IntegratedSpeechTranslationService( } translationResult?.error != null -> { - Log.w(TAG, "识别中翻译失败: ${translationResult.error}") eventCallback?.onTranslationFailed(utteranceId, text, translationResult.error) } else -> { - Log.w(TAG, "识别中翻译返回空结果") eventCallback?.onTranslationFailed(utteranceId, text, "翻译服务返回空结果") } } } catch (e: CancellationException) { // 被识别完成事件或新识别中事件取消,不做失败提示 - Log.d(TAG, "识别中翻译任务已取消: $text") } catch (e: TimeoutCancellationException) { Log.w(TAG, "识别中翻译超时: $text") eventCallback?.onTranslationFailed(utteranceId, text, "翻译超时") diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift index 61590139e..11352b2df 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureAsrHelper.swift @@ -849,15 +849,12 @@ public class AzureAsrHelper: NSObject { return currentLanguage } - print("result: \(result)") - // 备用方案:从属性中获取语言 if let properties = result.properties, let language = properties.getPropertyByName( "speechServiceResponse_RecognitionLanguage"), !language.isEmpty { - print("从属性中检测到语言: \(language)") return language } @@ -865,13 +862,12 @@ public class AzureAsrHelper: NSObject { do { let langResult = try SPXAutoDetectSourceLanguageResult(result) if let language = langResult.language, !language.isEmpty { - print("SDK方法检测到语言: \(language)") return language } } catch { - print("SDK语言检测失败: \(error.localizedDescription)") + os_log("SDK语言检测失败: %{public}@", log: log, type: .error, + error.localizedDescription) } - print("无法检测语言,使用默认语言: \(currentLanguage)") return currentLanguage } @@ -916,8 +912,6 @@ public class AzureAsrHelper: NSObject { * 设置事件监听器 */ public func setupEventListeners(callback: ContinuousRecognizeCallback) -> Bool { - print("设置ssssss监听器:${speechConfig}") - // 保存回调引用用于网络事件 self.continuousCallback = callback @@ -935,9 +929,6 @@ public class AzureAsrHelper: NSObject { // 使用现有的 getDetectedLanguage 方法替代 result.language let detectedLanguage = self.getDetectedLanguage(from: result) - let text = result.text - - print("正在识别事件=检测到语言: \(detectedLanguage), 识别中: \(text)") DispatchQueue.main.async { callback.onRecognizing( @@ -953,42 +944,34 @@ public class AzureAsrHelper: NSObject { !(result.text?.isEmpty ?? true) else { return } - // 使用现有的 getDetectedLanguage 方法替代 result.language let detectedLanguage = self.getDetectedLanguage(from: result) let text = result.text - print("识别完成事件=检测到语言: \(detectedLanguage), 识别中: \(text)") + os_log("识别完成: lang=%{public}@ text=%{public}@", log: self.log, type: .info, + detectedLanguage, text ?? "") - // 在主线程回调结果 DispatchQueue.main.async { callback.onResult( sessionid: self.currsessionId, result.text ?? "", detectedLanguage) self.currsessionId = UUID().uuidString } - } // 会话开始事件 recognizer.addSessionStartedEventHandler { (sender, event) in - // 直接在当前线程调用回调 self.currsessionId = UUID().uuidString callback.onSessionStarted(sessionid: self.currsessionId) - print("会话开始事件:") } // 会话结束事件 recognizer.addSessionStoppedEventHandler { [weak self] (sender, event) in guard let self = self else { return } - print("会话结束事件:") - // 直接在当前线程调用回调 callback.onSessionStopped(sessionid: self.currsessionId) self.audioStream?.isContinuousRecognitionActive = false - //self.stopAudioProcessing() } // 取消事件 recognizer.addCanceledEventHandler { [weak self] (_, event) in guard let self = self else { return } - print("取消事件:") let errorDetails = event.errorDetails ?? "未知错误" let reason = String(describing: event.reason.rawValue) diff --git a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift index caf0bcd23..87c112dc6 100644 --- a/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift +++ b/local_plugins/azure_speech/ios/azure_speech/Sources/azure_speech/AzureTtsHelper.swift @@ -168,8 +168,7 @@ public class AzureTtsHelper: NSObject, ITtsService, AVAudioPlayerDelegate { */ public func startspeak(sessionid: String) -> Bool { self.sessionid = sessionid - print("startspeak sessionid \(sessionid)") - // os_log("调用链: startspeak 设置session=%{public}@", log: log, type: .info, sessionid) + os_log("startspeak session=%{public}@", log: log, type: .info, sessionid) // 重置当前会话的文本计数 self.currentSessionTextCount = 0 self.pendingTextCount = 0 diff --git a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/OpusAudioManager.kt b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/OpusAudioManager.kt index f21c6f431..c9bf22937 100644 --- a/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/OpusAudioManager.kt +++ b/local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/OpusAudioManager.kt @@ -300,16 +300,10 @@ class OpusAudioManager { * @param data 音频数据 (Opus编码) */ fun processAudioData(data: ByteArray) { - if (!isInitialized) { - Log.w(TAG, "OpusAudioManager未初始化,忽略音频数据") - return - } - + if (!isInitialized) return if (decodeOpusManager?.isDecodeStream == true) { // 将数据加入队列进行异步处理 audioDataQueue.offer(data) - } else { - Log.d(TAG, "Opus解码流未启动,忽略音频数据") } } @@ -344,17 +338,8 @@ class OpusAudioManager { Log.d(TAG, "准备开始Opus数据流编码") encodeOpusManager?.startEncodeStream(object : OnEncodeStreamCallback { override fun onEncodeStream(data: ByteArray?) { - Log.d(TAG, "Opus编码回调收到数据,大小: ${data?.size ?: 0} bytes") if (data != null) { - - // 编码完成的数据处理: - // 1. 通知回调 callback?.onAudioDataEncoded(data) - - // // 2. 将编码后的数据加入发送队列进行分块发送 - // addAudioDataToSendQueue(data) - } else { - Log.w(TAG, "编码回调收到空数据") } } @@ -411,13 +396,8 @@ class OpusAudioManager { return } - // 如果已经在编码流中,直接写入数据 if (encodeOpusManager?.isEncodeStream == true) { - Log.d(TAG, "正在进行Opus编码流,写入音频数据") - // 将外部音频数据写入编码流 encodeOpusManager?.writeEncodeStream(data) - } else { - Log.w(TAG, "Opus编码流未启动,无法写入音频数据") } } diff --git a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift index db8323493..a519a03c5 100644 --- a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift +++ b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/BleService.swift @@ -680,12 +680,8 @@ public class BleService: NSObject { // MARK: - 编解码控制 public func writeExternalAudioData(data: Data) { - print("pcm音频进入编码", data.count) - // 确保Opus编码器处于活跃状态(如果不是则启动) - - // 将外部音频数据写入编码流,每次处理1280字节 - opusProcessor?.encodePCMData(data) - + // 将外部音频数据写入编码流 + opusProcessor?.encodePCMData(data) } /// 打开编码器 diff --git a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftOpusAudioProcessor.swift b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftOpusAudioProcessor.swift index 7e0898ec3..3c84f0a62 100644 --- a/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftOpusAudioProcessor.swift +++ b/local_plugins/ble_service/ios/ble_service/Sources/ble_service/SwiftOpusAudioProcessor.swift @@ -443,26 +443,14 @@ class SwiftOpusAudioProcessor: NSObject { /// 编码PCM音频数据 /// - Parameter pcmData: PCM音频数据 func encodePCMData(_ pcmData: Data) { - guard isEncodingActive, let encoder = jlOpusEncoder else { - print("编码器未启动或不可用") - return - } - - guard !pcmData.isEmpty else { - print("PCM数据为空") - return - } - - print("接收PCM数据 - 数据大小: \(pcmData.count) bytes") - + guard isEncodingActive, let encoder = jlOpusEncoder else { return } + guard !pcmData.isEmpty else { return } + // 将新数据加入队列 queueLock.lock() pcmDataQueue.append(pcmData) - let currentQueueSize = pcmDataQueue.count queueLock.unlock() - - print("PCM数据已加入队列 - 当前队列大小: \(currentQueueSize) bytes") - + // 异步处理队列中的数据 processQueuedData() } @@ -479,57 +467,33 @@ class SwiftOpusAudioProcessor: NSObject { } processingQueue?.async { [weak self, weak encoder] in - guard let self = self, let encoder = encoder else { - print("编码器或处理器已释放") - return - } - + guard let self = self, let encoder = encoder else { return } + while self.isEncodingActive { var chunkData: Data? - - // 从队列中取出数据 + self.queueLock.lock() if self.pcmDataQueue.count >= self.chunkSize { - // 取出640字节数据 chunkData = self.pcmDataQueue.subdata(in: 0.. 0 { - // 不足640字节,补齐静音数据 let availableBytes = self.pcmDataQueue.count let silentBytesNeeded = self.chunkSize - availableBytes - - // 创建静音数据(16位PCM静音为0) let silentData = Data(repeating: 0, count: silentBytesNeeded) - - // 组合实际数据和静音数据 chunkData = Data() chunkData?.append(self.pcmDataQueue) chunkData?.append(silentData) - - // 清空队列 self.pcmDataQueue.removeAll() - - print("数据不足640字节,已补齐静音数据 - 实际数据: \(availableBytes) bytes, 静音数据: \(silentBytesNeeded) bytes") } self.queueLock.unlock() - - // 如果有数据需要编码 + if let dataToEncode = chunkData { - guard self.isEncodingActive else { - print("编码已停止,退出处理循环") - break - } - - // 编码数据块 + guard self.isEncodingActive else { break } encoder.opusEncode(dataToEncode) - print("已编码音频块 - 数据大小: \(dataToEncode.count) bytes") } else { - // 队列为空,退出循环 break } } - - print("队列处理完成") } } @@ -563,13 +527,8 @@ extension SwiftOpusAudioProcessor: JLOpusEncoderDelegate { print("Opus编码错误: \(error.localizedDescription)") return } - - guard let opusData = data, !opusData.isEmpty else { - print("编码后的Opus数据为空") - return - } - - print("Opus编码成功 - 数据大小: \(opusData.count) bytes") + + guard let opusData = data, !opusData.isEmpty else { return } // 回调编码后的数据到主线程 DispatchQueue.main.async { [weak self] in diff --git a/local_plugins/volcano_speech/android/src/main/kotlin/com/yunqiinnovation/volcano_speech/VolcanoAsrHelper.kt b/local_plugins/volcano_speech/android/src/main/kotlin/com/yunqiinnovation/volcano_speech/VolcanoAsrHelper.kt index 20f65258a..aeaae51bd 100644 --- a/local_plugins/volcano_speech/android/src/main/kotlin/com/yunqiinnovation/volcano_speech/VolcanoAsrHelper.kt +++ b/local_plugins/volcano_speech/android/src/main/kotlin/com/yunqiinnovation/volcano_speech/VolcanoAsrHelper.kt @@ -636,27 +636,17 @@ class VolcanoAsrHelper(private val context: Context) { } SpeechEngineDefines.MESSAGE_TYPE_PARTIAL_RESULT -> { - // 中间识别结果 - Log.i(TAG, "中间识别结果: $data") + // 中间识别结果(高频,降级为 debug) try { val json = JSONObject(data) if (!json.has("result")) { - Log.w(TAG, "中间结果没有 result 字段: $data") return } - // if (json.has("definite")) { - // Log.i(TAG, "utterances: ${json.getString("utterances")}") - // } - // 从多种可能的格式中获取文本 val text = extractTextFromResult(json) - - // 获取语言信息,如果没有则使用默认语言 val detectedLanguage = json.optString("lang", language) - + if (text.isNotEmpty()) { mainHandler.post { - Log.i(TAG, "提取到中间文本: $text") - // 中间结果 continuousCallback?.onRecognizing(text, detectedLanguage) } } @@ -664,34 +654,25 @@ class VolcanoAsrHelper(private val context: Context) { Log.e(TAG, "解析中间识别结果异常: ${e}") } } - + SpeechEngineDefines.MESSAGE_TYPE_FINAL_RESULT -> { - Log.i(TAG, "最终识别结果: $data") - // 最终识别结果 try { val json = JSONObject(data) if (!json.has("result")) { - Log.w(TAG, "最终结果没有 result 字段: $data") + Log.w(TAG, "最终结果没有 result 字段") return } - - // 从多种可能的格式中获取文本 + val text = extractTextFromResult(json) - - - // 获取语言信息,如果没有则使用默认语言 val detectedLanguage = json.optString("lang", language) - + if (text.isNotEmpty()) { mainHandler.post { if (isContinuousMode) { - Log.i(TAG, "发送最终识别结果: $text (连续模式)") + Log.i(TAG, "最终识别结果(连续): $text") continuousCallback?.onResult(text, detectedLanguage) - - // 在连续模式下,不需要手动触发下一轮识别,引擎会自动继续监听 - // 但如果需要明确标记新一轮开始,可以在此处添加代码 } else { - Log.i(TAG, "发送最终识别结果: $text (单次模式)") + Log.i(TAG, "最终识别结果(单次): $text") recognizeCallback?.onResult(text, detectedLanguage) } }