From 6a86e9b9c01935a2cc86b2afffa68dab3429dc95 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Tue, 30 Sep 2025 15:32:49 +0800 Subject: [PATCH] =?UTF-8?q?=E6=92=AD=E6=8A=A5=E6=89=93=E6=96=AD=E5=BC=80?= =?UTF-8?q?=E5=85=B3=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/controllers/agent_controller.dart | 15 +++++++++ lib/modules/agent/views/agent_view.dart | 33 +++++++++++++++++++ .../agent_service/AgentService.kt | 22 ++++++++++++- .../agent_service/AgentServicePlugin.kt | 9 +++++ .../yunqiinnovation/agent_service/BleAgent.kt | 1 + .../agent_service/lib/agent_service.dart | 9 +++++ 6 files changed, 88 insertions(+), 1 deletion(-) diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index 5f6386cce..98352a7c6 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -80,6 +80,8 @@ class AgentController extends GetxController with WidgetsBindingObserver { final isProcessing = false.obs; // TTS启用状态 final isTtsEnabled = true.obs; + // TTS播报打断启用状态 + final isTtsInterruptEnabled = true.obs; // 图片处理状态 final isImageProcessing = false.obs; @@ -260,6 +262,19 @@ class AgentController extends GetxController with WidgetsBindingObserver { } } + /// 切换TTS播报打断状态 + /// 当启用播报打断时,用户说话会自动停止当前的TTS播放 + Future toggleTtsInterrupt() async { + isTtsInterruptEnabled.toggle(); + + // 保存偏好设置 + try { + await AgentService.isInterrupt(); + } catch (e) { + Logger.e(TAG, '保存TTS播报打断偏好设置失败: $e'); + } + } + // 设置文本输入监听器 void _setupTextInputListener() { textController.addListener(() { diff --git a/lib/modules/agent/views/agent_view.dart b/lib/modules/agent/views/agent_view.dart index c9c456491..564921389 100644 --- a/lib/modules/agent/views/agent_view.dart +++ b/lib/modules/agent/views/agent_view.dart @@ -172,6 +172,39 @@ class _AgentViewState extends State with WidgetsBindingObserver { ), color: isDarkMode ? Colors.grey[800] : Colors.white, itemBuilder: (context) => [ + // 播报打断开关选项 + PopupMenuItem( + child: Obx(() => Row( + children: [ + Icon( + controller.isTtsInterruptEnabled.value + ? Icons.voice_over_off + : Icons.voice_over_off_outlined, + color: controller.isTtsInterruptEnabled.value + ? primaryColor + : (isDarkMode ? Colors.grey[400] : Colors.grey), + size: 20.sp, + ), + SizedBox(width: 8.w), + Text( + //'ttsInterruptToggle'.tr, + "播报打断", + style: TextStyle(fontSize: 14.sp), + ), + const Spacer(), + Switch( + value: controller.isTtsInterruptEnabled.value, + onChanged: (value) => + controller.toggleTtsInterrupt(), + activeColor: primaryColor, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + ), + ], + )), + onTap: () => controller.toggleTtsInterrupt(), + ), + // 清除聊天记录选项 PopupMenuItem( child: Row( children: [ 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 99e0ed8e5..4e37af840 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 @@ -58,6 +58,9 @@ interface AgentServiceListener { object AgentService : CoroutineScope { private val TAG = "AgentService" + + private var _isInterrupt = AtomicBoolean(true) + private var azureSpeechKey: String = "" private var azureSpeechRegion: String = "" @@ -359,6 +362,9 @@ object AgentService : CoroutineScope { sendEvent("playback_started", mapOf("status" to "playback_started")) // 确保气泡音已停止,避免与TTS播放重叠 audioPlayer?.stopAudio() + if(_isInterrupt.get()){ + BleService.closeCodec() + } // 发送AI说话开始广播 val intent = Intent("com.yunqiinnovation.music_service.AI_SAY_START").apply { @@ -382,6 +388,9 @@ object AgentService : CoroutineScope { setPackage(context.packageName) } context.sendBroadcast(intent) + if(currentRecognitionMode == "ble_wakeup"&&_isInterrupt.get()){ + BleService.openEncoder() + } if(isplaymusic){ isplaymusic = false Log.e(TAG, "QQ 音乐恢复播放") @@ -513,7 +522,17 @@ object AgentService : CoroutineScope { startIdleCheckForMode(currentRecognitionMode) } } - + /** + * 切换中断状态 + * 如果当前为false,则设置为true;如果当前为true,则设置为false + * @return 切换后的状态值 + */ + fun isInterrupt(): Boolean { + val currentValue = _isInterrupt.get() + val newValue = !currentValue + _isInterrupt.set(newValue) + return newValue + } /** * 开始语音识别 * @param isExternalActive 是否使用外部音频源(蓝牙) @@ -997,6 +1016,7 @@ object AgentService : CoroutineScope { override fun onComplete(sessionid: String) { try { if (sessionid == currsessionId) { + audioPlayer?.stopAudio() } // 视情况决定是否朗读回复 diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt index 6e369fa68..ea9c27515 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentServicePlugin.kt @@ -128,6 +128,15 @@ class AgentServicePlugin : FlutterPlugin, MethodCallHandler, EventChannel.Stream result.error("START_ERROR", "启动对话失败: ${e.message}", null) } } + "isInterrupt" -> { + try { + val isInterrupt = AgentService.isInterrupt() + result.success(isInterrupt) + } catch (e: Exception) { + Log.e(TAG, "检查是否打断失败", e) + result.error("IS_INTERRUPT_ERROR", "检查是否打断失败: ${e.message}", null) + } + } "recognizeCallback" -> { val isStarted = AgentService.recognizeCallback() result.success(isStarted) 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 80c9b568b..4cddc47ed 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 @@ -66,6 +66,7 @@ object BleAgent : BleService.Callback, AgentServiceListener { return false } Log.d(TAG, "手动启动语音识别: ") + AgentService.interruptCurrentResponse() return AgentService.startRecognition(true, "ble_wakeup") } diff --git a/local_plugins/agent_service/lib/agent_service.dart b/local_plugins/agent_service/lib/agent_service.dart index c2a051c5e..c19eb4d18 100644 --- a/local_plugins/agent_service/lib/agent_service.dart +++ b/local_plugins/agent_service/lib/agent_service.dart @@ -266,6 +266,15 @@ class AgentService { } } + static Future isInterrupt() async { + try { + final bool result = await _channel.invokeMethod('isInterrupt'); + return result; + } on PlatformException catch (e) { + throw AgentServiceException(e.code, e.message ?? '检查是否打断失败', e.details); + } + } + /// 设备识别器 /// /// 启动语音识别,开始监听用户语音输入