import 'dart:async'; import 'dart:typed_data'; import 'package:get/get.dart'; import '../../../core/utils/logger.dart'; import '../../../data/services/asr_service.dart'; import '../../../data/services/speech_impl/xunfei_asr_service.dart'; import '../../../data/services/tts_service.dart'; import '../../../data/services/language_manager.dart'; import '../../../data/services/volcano_translation_service.dart'; class FTFTranslationController extends GetxController with GetSingleTickerProviderStateMixin { final messages = [].obs; final isChineseInput = true.obs; final leftLanguage = '中文'.obs; final rightLanguage = 'English'.obs; final isLeftInput = true.obs; final supportedLanguages = const [ '中文', 'English', '日本語', '한국어', 'Español', ]; late final AsrService _asrService; StreamSubscription? _recognitionSubscription; RxString intermediateContent = ''.obs; RxString finalContent = ''.obs; BytesBuilder _originaBytes = BytesBuilder(); //原始音频 final VolcanoTranslationService _translationService = Get.find(); final LanguageManager _languageManager = Get.find(); // 当前使用的TTS服务 late TtsService _ttsService; final isTranslating = false.obs; final sourceLanguageCode = 'zh-CN'.obs; final targetLanguageCode = 'en-US'.obs; final isTtsEnabled = true.obs; @override void onInit() { super.onInit(); Get.put(XunfeiAsrService()); final TtsService _ttsService = Get.find(); _asrService = Get.find(); _InfoRecorder(); } @override void onClose() { _asrService.dispose(); _recognitionSubscription?.cancel(); super.onClose(); } //开始录音 Future _InfoRecorder() async { final recognitionStream = await _asrService.recognizeCallback(); _recognitionSubscription = recognitionStream.listen( _handleRecognitionEvent, ); } //开始录音 Future _startRecorder() async { await _asrService.startContinuousRecognition(false); } //结束录音 Future _stopRecorder() async { await _asrService.stopContinuousRecognition(); } // 处理语音识别事件 void _handleRecognitionEvent(RecognitionEvent event) { switch (event.type) { case RecognitionEventType.intermediateResult: intermediateContent.value = event.text; handleFinalResult(event.text); break; case RecognitionEventType.finalResult: finalContent.value += _spliceText(event); intermediateContent.value = ''; _originaBytes.add(event.audio!); handleIntermediateResult(event.text); break; default: // 不做任何处理 break; } } // 翻译文本 Future translateText(String sourceText, {bool isFinal = false}) async { if (sourceText.isEmpty) return null; isTranslating.value = true; String? translationResult; try { // 根据检测到的语言确定源语言和目标语言 final bool shouldSwap = intermediateContent.value == sourceLanguageCode.value; final detectedSourceLanguageCode = shouldSwap ? sourceLanguageCode.value : targetLanguageCode.value; final detectedTargetLanguageCode = shouldSwap ? targetLanguageCode.value : sourceLanguageCode.value; // 调用翻译服务 translationResult = await _translationService.translateText( text: sourceText, sourceLanguageCode: detectedSourceLanguageCode, targetLanguageCode: detectedTargetLanguageCode, ); if (translationResult != null) { // 查找匹配的项目 - 优先使用timestamp查找 int index = -1; // 播放TTS - 只在最终结果时播放 if (isTtsEnabled.value && isFinal) { // Logger.info('播放翻译文本: ${translationResult}'); await playTranslatedText(translationResult); } } } catch (e) { Logger.error('翻译失败: ${e.toString()}'); } finally { isTranslating.value = false; } return translationResult; } // 处理中间识别结果 void handleIntermediateResult(String text) { if (text.isEmpty) return; translateText(text, isFinal: false); } // 处理最终识别结果 Future handleFinalResult(String text) async { if (text.isEmpty) return; // 使用项目的时间戳进行翻译 translateText(text, isFinal: true); } // 播放翻译文本 Future playTranslatedText(String text) async { if (text.isEmpty) return; try { final bool shouldSwap = intermediateContent.value == targetLanguageCode.value; final detectedTargetLanguageCode = shouldSwap ? sourceLanguageCode.value : targetLanguageCode.value; final voiceName = _languageManager .getTtsVoiceNameByAsrCode(detectedTargetLanguageCode) ?? 'en-US-AriaNeural'; await _ttsService.setVoice(voiceName); await _ttsService.speakOnce(text); } catch (e) { Logger.error('播放翻译失败: ${e.toString()}'); } } String _spliceText(RecognitionEvent event) { String eventText = event.text; String text = ''; if (finalContent.value.isNotEmpty) { if (event.role != '') { final punctuations = { ',', '。', '!', '?', ';', ':', ',', '.', ':', ';', '!', '?' }; final firstChar = eventText[0]; if (punctuations.contains(firstChar)) { text += '$firstChar\n'; eventText = eventText.substring(1); } else { text += '\n'; } text += '说话人${event.role}:'; } } else { text += '说话人${event.role}:'; } text += eventText; return text; } void addMessage(String text) { final fromLang = isLeftInput.value ? leftLanguage.value : rightLanguage.value; final toLang = isLeftInput.value ? rightLanguage.value : leftLanguage.value; messages.add( FTFTranslationMessage( original: text, translated: '[$fromLang → $toLang] $text (翻译模拟)', isChineseSpeaker: isLeftInput.value, ), ); } void swapLanguages() { final temp = leftLanguage.value; leftLanguage.value = rightLanguage.value; rightLanguage.value = temp; isLeftInput.value = !isLeftInput.value; } void toggleInputSide(bool isLeft) => isLeftInput.value = isLeft; } class FTFTranslationMessage { final String original; final String translated; final bool isChineseSpeaker; FTFTranslationMessage({ required this.original, required this.translated, required this.isChineseSpeaker, }); }