From 3e63a862743a253454b829cd4dc67fc4c96d4007 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Mon, 30 Jun 2025 21:14:57 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E9=9F=B3=E9=A2=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/utils/synchrodata.dart | 6 +- .../meeting_details_controller.dart | 30 ++++++ .../meeting/views/meeting_details_view.dart | 102 ++++++++++++++---- 3 files changed, 116 insertions(+), 22 deletions(-) diff --git a/lib/core/utils/synchrodata.dart b/lib/core/utils/synchrodata.dart index b25638663..6571862c5 100644 --- a/lib/core/utils/synchrodata.dart +++ b/lib/core/utils/synchrodata.dart @@ -128,7 +128,6 @@ class Synchrodata { 'title': element['title'] ?? '', 'type': element['rtype'] ?? '', 'seconds': element['seconds'] ?? 0, - 'filepath': '', 'audiourl': element['audiourl'] ?? '', 'tasktype': element['tasktype'] ?? 0, 'creationtime': element['creationtime'] ?? 0, @@ -157,7 +156,10 @@ class Synchrodata { whereArgs: [element['number']], ); } else { - await txn.insert('meeting', meetingData); + await txn.insert('meeting', { + ...meetingData, + 'filepath': '', + }); await txn.insert('meetingdetails', meetingDetailsData); } if (element['original'].isNotEmpty) { diff --git a/lib/modules/meeting/controllers/meeting_details_controller.dart b/lib/modules/meeting/controllers/meeting_details_controller.dart index 8ac33d0fd..c97e7ed53 100644 --- a/lib/modules/meeting/controllers/meeting_details_controller.dart +++ b/lib/modules/meeting/controllers/meeting_details_controller.dart @@ -1,7 +1,9 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:audio_waveforms/audio_waveforms.dart'; +import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart' show rootBundle; import 'package:flutter_easyloading/flutter_easyloading.dart'; @@ -9,6 +11,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:get_storage/get_storage.dart'; import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; import '../../../core/utils/logger.dart'; import '../../../core/utils/synchrodata.dart'; @@ -58,6 +61,9 @@ class MeetingDetailsController extends GetxController String markmapToolbarJs = ''; String saveSvgAsPngJs = ''; + RxBool isDownload = false.obs; + RxDouble downloadProgress = 0.0.obs; + String _systemPrompt = ''; String _userId = ''; @@ -205,6 +211,30 @@ class MeetingDetailsController extends GetxController await rootBundle.loadString('assets/js/saveSvgAsPng.min.js'); } + void downloadAudio() async { + if (isDownload.value) return; + isDownload.value = true; + final directory = await getApplicationDocumentsDirectory(); + final directoryDir = Directory('${directory.path}/DownloadAudio'); + if (!await directoryDir.exists()) { + await directoryDir.create(recursive: true); + } + final fileName = meetingData.value.audiourl.split('/').last; + final String filePath = '${directory.path}/DownloadAudio/$fileName'; + await Dio().download( + meetingData.value.audiourl, + filePath, + onReceiveProgress: (int received, int total) { + downloadProgress.value = total > 0 ? received / total : 0.0; + }, + ); + meetingData.value.filepath = filePath; + meetingData.refresh(); + _loadPlayerController(); + SqfliteApi.editMeetingTitle(id, {'filePath': filePath}); + isDownload.value = false; + } + void editSpeakerText() async { if (editSpeakerTextId.value != 0 && editSpeakerTextChange.isNotEmpty) { Map? foundElement = editSpeakerTextList.firstWhere( diff --git a/lib/modules/meeting/views/meeting_details_view.dart b/lib/modules/meeting/views/meeting_details_view.dart index 1217d09d2..79640b2a6 100644 --- a/lib/modules/meeting/views/meeting_details_view.dart +++ b/lib/modules/meeting/views/meeting_details_view.dart @@ -81,20 +81,50 @@ class MeetingDetailsView extends GetView { children: [ GestureDetector( onTap: () { - if (controller.isPlay.value) { - controller.playerController.pausePlayer(); + if (controller.meetingData.value.filepath.isEmpty) { + controller.downloadAudio(); } else { - controller.playerController.startPlayer(); + if (controller.isPlay.value) { + controller.playerController.pausePlayer(); + } else { + controller.playerController.startPlayer(); + } } }, child: Obx( - () => Icon( - controller.isPlay.value - ? Icons.pause_circle - : Icons.play_circle, - color: Colors.black, - size: 30.w, - ), + () => !controller.isLoading.value && + controller.meetingData.value.filepath.isEmpty + ? Obx( + () => Stack( + alignment: Alignment.center, + children: [ + if (controller.isDownload.value) + SizedBox( + width: 26.w, + height: 26.w, + child: CircularProgressIndicator( + value: controller.downloadProgress.value, + valueColor: + const AlwaysStoppedAnimation( + Colors.red), + strokeWidth: 2.w, + ), + ), + Icon( + Icons.download_for_offline, + color: Colors.black, + size: 30.w, + ), + ], + ), + ) + : Icon( + controller.isPlay.value + ? Icons.pause_circle + : Icons.play_circle, + color: Colors.black, + size: 30.w, + ), ), ), 4.horizontalSpace, @@ -446,20 +476,52 @@ class MeetingDetailsView extends GetView { ), GestureDetector( onTap: () { - if (controller.isPlay.value) { - controller.playerController.pausePlayer(); + if (controller.meetingData.value.filepath.isEmpty) { + controller.downloadAudio(); } else { - controller.playerController.startPlayer(); + if (controller.isPlay.value) { + controller.playerController.pausePlayer(); + } else { + controller.playerController.startPlayer(); + } } }, child: Obx( - () => Icon( - controller.isPlay.value - ? Icons.pause_circle - : Icons.play_circle, - color: Colors.black, - size: 48.w, - ), + () => !controller.isLoading.value && + controller + .meetingData.value.filepath.isEmpty + ? Obx( + () => Stack( + alignment: Alignment.center, + children: [ + if (controller.isDownload.value) + SizedBox( + width: 42.w, + height: 42.w, + child: CircularProgressIndicator( + value: controller + .downloadProgress.value, + valueColor: + const AlwaysStoppedAnimation< + Color>(Colors.red), + strokeWidth: 3.w, + ), + ), + Icon( + Icons.download_for_offline, + color: Colors.black, + size: 48.w, + ), + ], + ), + ) + : Icon( + controller.isPlay.value + ? Icons.pause_circle + : Icons.play_circle, + color: Colors.black, + size: 48.w, + ), ), ), GestureDetector( From 2d17cb9409d8ef356c137efe505a0cf8bfdbf856 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Mon, 30 Jun 2025 21:44:35 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E8=AE=BE=E7=BD=AEhtml=E7=A6=81=E6=AD=A2?= =?UTF-8?q?=E7=BC=A9=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/meeting/controllers/mind_map_controller.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/modules/meeting/controllers/mind_map_controller.dart b/lib/modules/meeting/controllers/mind_map_controller.dart index 8fe7b67e6..d30244f29 100644 --- a/lib/modules/meeting/controllers/mind_map_controller.dart +++ b/lib/modules/meeting/controllers/mind_map_controller.dart @@ -27,7 +27,7 @@ class MindMapController extends GetxController { - + MindMap From 6026bdbe59ea97a79e61ac8ec7c3e94ac01c1080 Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 1 Jul 2025 15:13:53 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E8=BF=87=E6=BB=A4=E9=80=89=E6=8B=A9?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/modules/meeting/controllers/meeting_controller.dart | 1 + pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/modules/meeting/controllers/meeting_controller.dart b/lib/modules/meeting/controllers/meeting_controller.dart index 955c2b82f..f7c34edbd 100644 --- a/lib/modules/meeting/controllers/meeting_controller.dart +++ b/lib/modules/meeting/controllers/meeting_controller.dart @@ -322,6 +322,7 @@ class MeetingController extends GetxController { } else { FilePickerResult? result = await FilePicker.platform.pickFiles( withData: true, + type: FileType.audio, ); if (result != null) { PlatformFile file = result.files.first; diff --git a/pubspec.yaml b/pubspec.yaml index 0298f6e64..6fb187beb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,7 +36,7 @@ dependencies: webview_flutter: ^4.13.0 flutter_easyloading: ^3.0.5 package_info_plus: ^8.3.0 - file_picker: ^10.1.5 + file_picker: ^10.2.0 haptic_feedback: ^0.5.1+1 tencentcloud_cos_sdk_plugin: ^1.2.3 photo_view: ^0.15.0 From 433c2f24d1bf9766443094df3cd429f1e9c4a1ba Mon Sep 17 00:00:00 2001 From: tanlongsheng <252620078@qq.com> Date: Tue, 1 Jul 2025 15:59:33 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BC=9A=E8=AE=AE?= =?UTF-8?q?=E5=8A=A9=E6=89=8B=E8=BD=AC=E5=86=99=E8=AE=B0=E5=BD=95=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/utils/synchrodata.dart | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/core/utils/synchrodata.dart b/lib/core/utils/synchrodata.dart index 6571862c5..5cca0d2e1 100644 --- a/lib/core/utils/synchrodata.dart +++ b/lib/core/utils/synchrodata.dart @@ -171,19 +171,34 @@ class Synchrodata { List speakerList = jsonDecode(element['original']); if (existSpeakerList.isNotEmpty) { final batch = txn.batch(); - for (var item in speakerList) { - batch.update( - 'meetingspeaker', - item, - where: 'id = ?', - whereArgs: [item['id']], - ); + for (var i = 0; i < existSpeakerList.length; i++) { + Map item = speakerList[i] ?? {}; + if (item.isNotEmpty) { + batch.update( + 'meetingspeaker', + { + 'meetingid': item['meetingid'], + 'content': item['content'], + 'starttime': item['starttime'], + 'endtime': item['endtime'], + 'speaker': item['speaker'], + }, + where: 'id = ?', + whereArgs: [existSpeakerList[i]['id']], + ); + } } await batch.commit(); } else { final batch = txn.batch(); for (var item in speakerList) { - batch.insert('meetingspeaker', item); + batch.insert('meetingspeaker', { + 'meetingid': item['meetingid'], + 'content': item['content'], + 'starttime': item['starttime'], + 'endtime': item['endtime'], + 'speaker': item['speaker'], + }); } await batch.commit(); } 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 5/6] =?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); } From be01dbebe26c9b9603a402acadcb9a6081a35ba5 Mon Sep 17 00:00:00 2001 From: fdp <1286779656@qq.com> Date: Tue, 1 Jul 2025 19:41:24 +0800 Subject: [PATCH 6/6] 1 --- .../controllers/translation_controller.dart | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/lib/modules/translation/controllers/translation_controller.dart b/lib/modules/translation/controllers/translation_controller.dart index f2d3df70c..b40408dbc 100644 --- a/lib/modules/translation/controllers/translation_controller.dart +++ b/lib/modules/translation/controllers/translation_controller.dart @@ -539,14 +539,14 @@ class TranslationController extends GetxController { ); if (currentMode.value == 'faceToFace' && activeSpeaker.value == 0) { _asrService.setPause(); - } else { - translationHistory.add(newItem); - translationHistory.refresh(); - _scrollToBottom(); - saveTranslationHistory(); - // 使用新项目的时间戳进行翻译 - translateText(text, newItem.timestamp, isFinal: true); - } + } //else { + translationHistory.add(newItem); + translationHistory.refresh(); + _scrollToBottom(); + saveTranslationHistory(); + // 使用新项目的时间戳进行翻译 + translateText(text, newItem.timestamp, isFinal: true); + // } } } @@ -612,20 +612,20 @@ class TranslationController extends GetxController { // 更新后滚动到底部 _scrollToBottom(); // 播放TTS - 只在最终结果时播放 - if (isTtsEnabled.value && - isFinal && - currentMode.value != 'faceToFace') { - await playTranslatedText(translationResult); - } else { - fTFTranslationResult = - (fTFTranslationResult ?? '') + translationResult; - - if (activeSpeaker.value == 0 && !isPlayback) { - isPlayback = true; - await _ttsService.setAudioOutputDevice(lastActiveSpeaker.value); - await Future.delayed(const Duration(milliseconds: 1300)); - await playTranslatedText(fTFTranslationResult!); - fTFTranslationResult = ''; + if (isFinal) { + if (isTtsEnabled.value && currentMode.value != 'faceToFace') { + await playTranslatedText(translationResult); + } else { + fTFTranslationResult = + (fTFTranslationResult ?? '') + translationResult; + print("translationResult=$translationResult"); + if (activeSpeaker.value == 0 && !isPlayback) { + isPlayback = true; + await _ttsService.setAudioOutputDevice(lastActiveSpeaker.value); + await Future.delayed(const Duration(milliseconds: 1300)); + await playTranslatedText(fTFTranslationResult!); + fTFTranslationResult = ''; + } } } } else { @@ -653,6 +653,7 @@ class TranslationController extends GetxController { final voiceName = _languageManager .getTtsVoiceNameByAsrCode(detectedTargetLanguageCode) ?? 'en-US-AriaNeural'; + print("voiceName=$voiceName,text$text"); await _ttsService.setVoice(voiceName); await _ttsService.speakOnce(text); } catch (e) {