Browse Source

feat(translation): 优化通话模式下的翻译项布局和语言处理逻辑

调整翻译项在通话模式下的对齐方式,新增通话模式标记控制显示
重构语音识别事件处理逻辑,优化语言代码确定方式
添加BLE服务音频数据接收日志,便于调试
newdev_shunjiawei
lxm 11 months ago
parent
commit
da130288d0
  1. 112
      lib/modules/translation/controllers/translation_controller.dart
  2. 10
      lib/modules/translation/views/widgets/translation_item_widget.dart
  3. 2
      local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

112
lib/modules/translation/controllers/translation_controller.dart

@ -847,53 +847,64 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
/// 处理语音识别事件
/// [event] 识别事件
void _handleRecognitionEvent(RecognitionEvent event) {
if (event.type == RecognitionEventType.finalResult &&
event.text.isNotEmpty) {
detectedLanguageCode = event.detectedLanguage;
print("处理识别完成:${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);
faceToFaceRecognitionText.value = '';
}
} else if (event.type == RecognitionEventType.finalResult1 &&
event.text.isNotEmpty) {
// 通话模式下:己方(麦克风)识别完成事件
// 若原生未返回检测语言,则兜底为源语言
detectedLanguageCode = event.detectedLanguage.isNotEmpty
? event.detectedLanguage
: sourceLanguageCode.value;
print("处理己方识别完成:${event.text}");
if (currentMode.value != 'faceToFace') {
// Logger.info("处理识别事件:${event}");
switch (event.type) {
case RecognitionEventType.finalResult:
if (event.text.isEmpty) break;
// 通话模式下:目标语言即为识别语言,无需判断
detectedLanguageCode = currentMode.value == 'call'
? targetLanguageCode.value
: event.detectedLanguage;
Logger.info("处理识别完成:${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);
faceToFaceRecognitionText.value = '';
}
break;
case RecognitionEventType.finalResult1:
// 通话模式下:己方(麦克风)识别完成事件(对应ast服务)
if (event.text.isEmpty) break;
//通话模式下:己方语言即为源语言,无需判断
detectedLanguageCode = sourceLanguageCode.value;
Logger.info("处理己方识别完成:${event.text}");
handleFinalResult(event.text);
} else {
faceToFaceRecognitionText.value += event.text;
Logger.info('lxm-面对面翻译识别文本更新(己方): ${faceToFaceRecognitionText.value}');
}
if (currentMode.value == 'faceToFace' && activeSpeaker.value == 0) {
handleFinalResult(faceToFaceRecognitionText.value);
faceToFaceRecognitionText.value = '';
}
} else if (event.type == RecognitionEventType.intermediateResult &&
event.text.isNotEmpty) {
if (event.detectedLanguage.isNotEmpty) {
detectedLanguageCode = event.detectedLanguage;
}
print("处理识别中事件:${event.text}");
handleIntermediateResult(event.text);
} else if (event.type == RecognitionEventType.error) {
Get.snackbar('error'.tr, event.error);
isRecognizing.value = false;
Logger.error('语音识别错误: ${event.error}');
} else if (event.type == RecognitionEventType.canceled) {
isRecognizing.value = false;
Logger.error('语音识别取消: ${event.error}');
break;
case RecognitionEventType.intermediateResult:
if (event.text.isEmpty) break;
// 通话模式下:目标语言即为识别语言,无需判断
detectedLanguageCode = currentMode.value == 'call'
? targetLanguageCode.value
: event.detectedLanguage;
Logger.info("处理识别中事件:${event.text}");
handleIntermediateResult(event.text);
break;
case RecognitionEventType.error:
Get.snackbar('error'.tr, event.error);
isRecognizing.value = false;
Logger.error('语音识别错误: ${event.error}');
break;
case RecognitionEventType.canceled:
isRecognizing.value = false;
Logger.error('语音识别取消: ${event.error}');
break;
case RecognitionEventType.sessionStarted:
// 可按需处理会话开始事件
break;
case RecognitionEventType.sessionStopped:
// 可按需处理会话结束事件
break;
}
}
@ -919,18 +930,21 @@ class TranslationController extends GetxController with WidgetsBindingObserver {
/// [text] 识别的文本
void handleIntermediateResult(String text) {
if (text.isEmpty) return;
print(
Logger.info(
"handleIntermediateResult:${translationHistory.isEmpty}${translationHistory.isNotEmpty ? translationHistory.last.isIntermediate : 'N/A'}");
if (translationHistory.isEmpty ||
(translationHistory.isNotEmpty &&
!translationHistory.last.isIntermediate)) {
currentSessionId ??= DateTime.now().millisecondsSinceEpoch.toString();
// 关键调整:使用与最终结果一致的语言方向,避免左右“跳变”
final languageCodes = _determineLanguageCodes();
final newItem = TranslationItem(
sourceText: text,
translatedText: '',
sourceLanguageCode: sourceLanguageCode.value,
targetLanguageCode: targetLanguageCode.value,
sourceLanguageCode: languageCodes['source']!,
targetLanguageCode: languageCodes['target']!,
timestamp: DateTime.now(),
sessionId: currentSessionId!,
isFirstInSession: translationHistory.isEmpty ||

10
lib/modules/translation/views/widgets/translation_item_widget.dart

@ -49,15 +49,19 @@ class TranslationItemWidget extends GetView<TranslationController> {
// 判断是否是己方的翻译项(依据控制器当前源语言)
final bool isSelf =
item.sourceLanguageCode == controller.sourceLanguageCode.value;
// 新增:通话模式标记,用于控制右侧显示与隐藏中间态
final bool isCallMode = controller.currentMode.value == 'call';
return GestureDetector(
onTap: () => onToggleActionItem(item), // 触碰气泡时切换按钮显隐
onLongPressStart: (details) =>
onLongPressStart(context, isDarkMode, details, item),
child: Align(
alignment: item.isIntermediate
? Alignment.center
: (isSelf ? Alignment.centerLeft : Alignment.centerRight),
alignment: isCallMode
? (isSelf ? Alignment.centerLeft : Alignment.centerRight)
: item.isIntermediate
? Alignment.center
: (isSelf ? Alignment.centerLeft : Alignment.centerRight),
child: Container(
margin: EdgeInsets.only(bottom: 8.h),
padding: EdgeInsets.all(12.w),

2
local_plugins/ble_service/android/src/main/kotlin/com/yunqiinnovation/ble_service/BleService.kt

@ -893,12 +893,14 @@ object BleService {
// 统计接收到的字节数
bytesReceivedInCurrentSecond += data.size
processAudioData(data)
Log.i(TAG, "lxm--收到音频特征数据, 字节数=${data.size}")
}
BleConst.CALL_RECEIVE_AUDIO_CHAR_UUID -> {
// 统计接收到的字节数
bytesReceivedInCurrentSecond += data.size
processAudioData(data)
Log.i(TAG, "lxm--收到通话音频特征数据, 字节数=${data.size}")
}
// 通知特征数据(命令和控制)
BleConst.NOTIFY_CHAR_UUID -> {

Loading…
Cancel
Save