From 2d957da14dd73766f300902e74af256613029192 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Tue, 1 Jul 2025 18:39:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/Runner/GoogleService-Info.plist | 8 +- .../meeting_record_controller.dart | 3 +- .../controllers/translation_controller.dart | 91 ++++++++++++------- .../views/translation_list_view.dart | 8 +- .../translation/views/translation_view.dart | 26 +++--- 5 files changed, 87 insertions(+), 49 deletions(-) diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist index c90ada3a3..590c85a5f 100644 --- a/ios/Runner/GoogleService-Info.plist +++ b/ios/Runner/GoogleService-Info.plist @@ -3,9 +3,9 @@ CLIENT_ID - 907754492821-oc9e77svgmmlgouo0op7vv00e1hb8278.apps.googleusercontent.com + 907754492821-tl2blr39g82re40sttkve36ovt6qcu6c.apps.googleusercontent.com REVERSED_CLIENT_ID - com.googleusercontent.apps.907754492821-oc9e77svgmmlgouo0op7vv00e1hb8278 + com.googleusercontent.apps.907754492821-tl2blr39g82re40sttkve36ovt6qcu6c ANDROID_CLIENT_ID 907754492821-9jakqvathu61e6b8g95i41ssi7o4dnka.apps.googleusercontent.com API_KEY @@ -15,7 +15,7 @@ PLIST_VERSION 1 BUNDLE_ID - com.yunqiinnovation.deepsound + com.chuangxiangyunqi.deapsound PROJECT_ID deepsound-e0e3d STORAGE_BUCKET @@ -31,6 +31,6 @@ IS_SIGNIN_ENABLED GOOGLE_APP_ID - 1:907754492821:ios:246794fc44b23174145c9c + 1:907754492821:ios:e4b4f3b37e58a7d1145c9c \ No newline at end of file diff --git a/lib/modules/meeting/controllers/meeting_record_controller.dart b/lib/modules/meeting/controllers/meeting_record_controller.dart index 1dfe1df3e..8b58e7378 100644 --- a/lib/modules/meeting/controllers/meeting_record_controller.dart +++ b/lib/modules/meeting/controllers/meeting_record_controller.dart @@ -138,6 +138,7 @@ class MeetingRecordController extends GetxController _bleManager.closeCodec(); } _asrService.stopRecord(true); + _asrService.setPause(); _asrService.stopContinuousRecognition(); isRecording.value = false; } @@ -214,7 +215,7 @@ class MeetingRecordController extends GetxController _recognitionSubscription?.cancel(); _recognitionSubscription = recognitionStream.listen(_handleRecognitionEvent); - + _asrService.setContinue(); // Prepare storage directory final appDir = await appDocDir; final dir = Directory("${appDir.path}/MeetingAudio/"); diff --git a/lib/modules/translation/controllers/translation_controller.dart b/lib/modules/translation/controllers/translation_controller.dart index dd1fc980b..f2d3df70c 100644 --- a/lib/modules/translation/controllers/translation_controller.dart +++ b/lib/modules/translation/controllers/translation_controller.dart @@ -106,13 +106,16 @@ class TranslationController extends GetxController { _asrService.setContinue(); lastActiveSpeaker.value = id; } else { - _asrService.setPause(); if (fTFTranslationResult != '' && !isPlayback) { isPlayback = true; await _ttsService.setAudioOutputDevice(lastActiveSpeaker.value); await Future.delayed(const Duration(milliseconds: 1300)); await playTranslatedText(fTFTranslationResult!); fTFTranslationResult = ''; + } else if ((translationHistory.isEmpty || + !translationHistory.last.isIntermediate) && + currentMode.value == 'faceToFace') { + _asrService.setPause(); } } } @@ -165,7 +168,7 @@ class TranslationController extends GetxController { } // 加载历史记录 - //loadTranslationHistory(); + loadTranslationHistory(); // 初始化服务 _initServices(); @@ -462,6 +465,7 @@ class TranslationController extends GetxController { if (translationHistory.isEmpty || !translationHistory.last.isIntermediate) { currentSessionId ??= DateTime.now().millisecondsSinceEpoch.toString(); + final newItem = TranslationItem( sourceText: text, translatedText: '', @@ -474,10 +478,15 @@ class TranslationController extends GetxController { isIntermediate: true, ); // 添加新项后滚动到底部 - translationHistory.add(newItem); + if (currentMode.value == 'faceToFace' && activeSpeaker.value == 0) { + _asrService.setPause(); + } else { + translationHistory.add(newItem); + } _scrollToBottom(); } else { // 更新当前项 + translationHistory.last.sourceText = text; translationHistory.refresh(); // 更新后滚动到底部 @@ -509,7 +518,9 @@ class TranslationController extends GetxController { // 更新后滚动到底部 _scrollToBottom(); saveTranslationHistory(); - + if (activeSpeaker.value == 0 && currentMode.value == 'faceToFace') { + _asrService.setPause(); + } // 使用项目的时间戳进行翻译 translateText(text, translationHistory.last.timestamp, isFinal: true); } else { @@ -526,14 +537,16 @@ class TranslationController extends GetxController { translationHistory.last.sessionId != currentSessionId, isIntermediate: false, ); - - translationHistory.add(newItem); - translationHistory.refresh(); - _scrollToBottom(); - saveTranslationHistory(); - - // 使用新项目的时间戳进行翻译 - translateText(text, newItem.timestamp, isFinal: true); + if (currentMode.value == 'faceToFace' && activeSpeaker.value == 0) { + _asrService.setPause(); + } else { + translationHistory.add(newItem); + translationHistory.refresh(); + _scrollToBottom(); + saveTranslationHistory(); + // 使用新项目的时间戳进行翻译 + translateText(text, newItem.timestamp, isFinal: true); + } } } @@ -546,13 +559,33 @@ class TranslationController extends GetxController { String? translationResult; try { - // 根据检测到的语言确定源语言和目标语言 - final bool shouldSwap = detectedLanguageCode == sourceLanguageCode.value; - final detectedSourceLanguageCode = - shouldSwap ? sourceLanguageCode.value : targetLanguageCode.value; - final detectedTargetLanguageCode = - shouldSwap ? targetLanguageCode.value : sourceLanguageCode.value; - + var detectedSourceLanguageCode; + var detectedTargetLanguageCode; + if ((currentMode.value == 'faceToFace' && activeSpeaker.value == 1) || + (currentMode.value == 'faceToFace' && + activeSpeaker.value == 0 && + lastActiveSpeaker.value == 1)) { + detectedLanguageCode = sourceLanguageCode.value; + detectedSourceLanguageCode = sourceLanguageCode.value; + detectedTargetLanguageCode = targetLanguageCode.value; + } else if ((currentMode.value == 'faceToFace' && + activeSpeaker.value == 2) || + (currentMode.value == 'faceToFace' && + activeSpeaker.value == 0 && + lastActiveSpeaker.value == 2)) { + // 根据检测到的语言确定源语言和目标语言 + detectedLanguageCode = targetLanguageCode.value; + detectedSourceLanguageCode = targetLanguageCode.value; + detectedTargetLanguageCode = sourceLanguageCode.value; + } else { + // 根据检测到的语言确定源语言和目标语言 + final bool shouldSwap = + detectedLanguageCode == sourceLanguageCode.value; + detectedSourceLanguageCode = + shouldSwap ? sourceLanguageCode.value : targetLanguageCode.value; + detectedTargetLanguageCode = + shouldSwap ? targetLanguageCode.value : sourceLanguageCode.value; + } // 调用翻译服务 translationResult = await _translationService.translateText( text: sourceText, @@ -560,6 +593,7 @@ class TranslationController extends GetxController { targetLanguageCode: detectedTargetLanguageCode, ); + /// } if (translationResult != null) { // 查找匹配的项目 - 优先使用timestamp查找 int index = -1; @@ -577,14 +611,16 @@ class TranslationController extends GetxController { saveTranslationHistory(); // 更新后滚动到底部 _scrollToBottom(); - if (isFinal && currentMode.value == 'faceToFace') { - print("音频输出文本2$translationResult"); + // 播放TTS - 只在最终结果时播放 + if (isTtsEnabled.value && + isFinal && + currentMode.value != 'faceToFace') { + await playTranslatedText(translationResult); + } else { fTFTranslationResult = (fTFTranslationResult ?? '') + translationResult; - if (activeSpeaker.value == 0 && - !isPlayback && - currentMode.value == 'faceToFace') { + if (activeSpeaker.value == 0 && !isPlayback) { isPlayback = true; await _ttsService.setAudioOutputDevice(lastActiveSpeaker.value); await Future.delayed(const Duration(milliseconds: 1300)); @@ -592,12 +628,6 @@ class TranslationController extends GetxController { fTFTranslationResult = ''; } } - // 播放TTS - 只在最终结果时播放 - if (isTtsEnabled.value && - isFinal && - currentMode.value != 'faceToFace') { - await playTranslatedText(translationResult); - } } else { Logger.info( '未找到匹配的历史项 ${sourceText} ${timestamp.toIso8601String() ?? "无时间戳"}'); @@ -623,7 +653,6 @@ class TranslationController extends GetxController { final voiceName = _languageManager .getTtsVoiceNameByAsrCode(detectedTargetLanguageCode) ?? 'en-US-AriaNeural'; - await _ttsService.setVoice(voiceName); await _ttsService.speakOnce(text); } catch (e) { diff --git a/lib/modules/translation/views/translation_list_view.dart b/lib/modules/translation/views/translation_list_view.dart index 994882077..dd13b7521 100644 --- a/lib/modules/translation/views/translation_list_view.dart +++ b/lib/modules/translation/views/translation_list_view.dart @@ -340,7 +340,11 @@ class TranslationListView extends GetView { FileSystemEntity file, ) { final TextEditingController _renameController = TextEditingController( - text: file.path.split('/').last, + text: () { + final fileName = file.path.split('/').last; + final dotIndex = fileName.lastIndexOf('.'); + return dotIndex != -1 ? fileName.substring(0, dotIndex) : fileName; + }(), ); Get.bottomSheet( @@ -432,7 +436,7 @@ class TranslationListView extends GetView { if (newName.isEmpty) return; final dir = file.parent.path; - final newPath = '$dir/$newName'; + final newPath = '$dir/$newName.wav'; try { await file.rename(newPath); diff --git a/lib/modules/translation/views/translation_view.dart b/lib/modules/translation/views/translation_view.dart index e2bf87d54..e529bd98d 100644 --- a/lib/modules/translation/views/translation_view.dart +++ b/lib/modules/translation/views/translation_view.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; @@ -528,27 +530,29 @@ class TranslationView extends GetView { }) { bool isActive = activeSpeaker == speakerId; bool isDisabled = activeSpeaker != 0 && activeSpeaker != speakerId; - + Timer? _holdTimer; // 增加延迟触发的计时器 return Listener( onPointerDown: (_) { - if (activeSpeaker == 0) { - // 没有激活的按钮时才能激活 - if (speakerId == 1) { - // 耳机收音 - 恢复原始音频状态 - controller.restoreOriginalAudioState(); - } else { - // 手机收音 - 禁用蓝牙音频 - controller.disableBluetoothAudio(); + // 设置300ms延迟防止误触 + _holdTimer = Timer(const Duration(milliseconds: 200), () { + if (activeSpeaker == 0) { + if (speakerId == 1) { + controller.restoreOriginalAudioState(); + } else { + controller.disableBluetoothAudio(); + } + controller.setActiveSpeaker(speakerId); } - controller.setActiveSpeaker(speakerId); - } + }); }, onPointerUp: (_) { + _holdTimer?.cancel(); if (isActive) { controller.setActiveSpeaker(0); } }, onPointerCancel: (_) { + _holdTimer?.cancel(); if (isActive) { controller.setActiveSpeaker(0); }