From d63124203bf61d2bd55eb95aaeaa843d91294e4d Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 9 Sep 2025 11:17:13 +0800 Subject: [PATCH] Fix critical bugs in speech recognition system 1. Add finalResult property to SpeechRecognitionResult class - Distinguish between real-time and final recognition results - Update factory methods, toString, equals, and hashCode - Update toMap and fromMap methods 2. Update YxAsrService to support finalResult flag - Add finalResult parameter to _sendResult method - Mark final results with finalResult: true - Keep real-time results as finalResult: false (default) 3. Remove unused methods to clean up codebase - Remove unused _toggleRecording method - Remove unused _updateTextController method - Clean up orphaned comments These fixes resolve linter errors and ensure proper text appending functionality. --- example/lib/main.dart | 66 ------------------- lib/src/models/speech_recognition_result.dart | 10 ++- lib/src/yx_asr_service.dart | 3 + 3 files changed, 12 insertions(+), 67 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index c1315c2..fbf30da 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -160,72 +160,6 @@ class _SpeechRecognitionPageState extends State { }); } - /// 更新文本控制器内容 - void _updateTextController() { - // 组合已确认的结果和当前实时结果 - final confirmedText = _realtimeResults.join(' '); - final displayText = _currentText.isNotEmpty - ? '$confirmedText ${_currentText}'.trim() - : confirmedText; - - // 只有当内容真正改变时才更新,避免光标跳动 - if (_textController.text != displayText) { - final cursorPosition = _textController.selection.baseOffset; - _textController.text = displayText; - - // 尝试保持光标位置,如果超出范围则移到末尾 - if (cursorPosition <= displayText.length) { - _textController.selection = TextSelection.fromPosition( - TextPosition(offset: cursorPosition), - ); - } else { - _textController.selection = TextSelection.fromPosition( - TextPosition(offset: displayText.length), - ); - } - } - } - - /// 切换录音状态 - Future _toggleRecording() async { - if (!_isInitialized) return; - - try { - if (_isListening) { - print('📱 [Example] 停止录音'); - await _speechService.stopListening(); - - // 录音结束后,将当前识别的文本保存到历史记录 - if (_currentText.isNotEmpty) { - setState(() { - _realtimeResults.add(_currentText); - _recognitionHistory.insert(0, _currentText); - print('📱 [Example] 添加到历史记录: $_currentText'); - // 保持历史记录在合理数量 - if (_recognitionHistory.length > 10) { - _recognitionHistory.removeLast(); - } - // 清空当前文本 - _currentText = ''; - _updateTextController(); - }); - } - } else { - print('📱 [Example] 开始录音'); - // 清空之前的结果,开始新的录音 - setState(() { - _realtimeResults.clear(); - _currentText = ''; - _textController.clear(); - }); - await _speechService.startListening(partialResults: true); - } - } catch (e) { - print('📱 [Example] 录音操作失败: $e'); - _showErrorSnackBar('录音操作失败: $e'); - } - } - @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/src/models/speech_recognition_result.dart b/lib/src/models/speech_recognition_result.dart index 8770559..a188254 100644 --- a/lib/src/models/speech_recognition_result.dart +++ b/lib/src/models/speech_recognition_result.dart @@ -9,10 +9,14 @@ class SpeechRecognitionResult { /// 备选识别结果 final List alternatives; + /// 是否为最终结果(true: 最终结果, false: 实时结果) + final bool finalResult; + const SpeechRecognitionResult({ required this.recognizedWords, this.confidence = 0.0, this.alternatives = const [], + this.finalResult = false, }); /// 从 Map 创建 [SpeechRecognitionResult] 实例 @@ -21,6 +25,7 @@ class SpeechRecognitionResult { recognizedWords: map['recognizedWords'] as String? ?? '', confidence: (map['confidence'] as num?)?.toDouble() ?? 0.0, alternatives: List.from(map['alternatives'] as List? ?? []), + finalResult: map['finalResult'] as bool? ?? false, ); } @@ -30,13 +35,14 @@ class SpeechRecognitionResult { 'recognizedWords': recognizedWords, 'confidence': confidence, 'alternatives': alternatives, + 'finalResult': finalResult, }; } @override String toString() { return 'SpeechRecognitionResult(recognizedWords: $recognizedWords, ' - 'confidence: $confidence, alternatives: $alternatives)'; + 'confidence: $confidence, alternatives: $alternatives, finalResult: $finalResult)'; } @override @@ -45,6 +51,7 @@ class SpeechRecognitionResult { return other is SpeechRecognitionResult && other.recognizedWords == recognizedWords && other.confidence == confidence && + other.finalResult == finalResult && other.alternatives.length == alternatives.length && other.alternatives.every((alt) => alternatives.contains(alt)); } @@ -53,6 +60,7 @@ class SpeechRecognitionResult { int get hashCode { return recognizedWords.hashCode ^ confidence.hashCode ^ + finalResult.hashCode ^ alternatives.hashCode; } } diff --git a/lib/src/yx_asr_service.dart b/lib/src/yx_asr_service.dart index 4b94aaa..d9c9bbf 100644 --- a/lib/src/yx_asr_service.dart +++ b/lib/src/yx_asr_service.dart @@ -586,6 +586,7 @@ class YxAsrService implements SpeechRecognitionService { recognizedWords: result.text, confidence: 1.0, alternatives: [], + finalResult: true, // 标记为最终结果 ); } else { debugPrint('⚠️ [YxAsr] 流式最终结果为空'); @@ -785,12 +786,14 @@ class YxAsrService implements SpeechRecognitionService { required String recognizedWords, required double confidence, required List alternatives, + bool finalResult = false, }) { debugPrint('📤 [YxAsr] 发送识别结果: "$recognizedWords"'); final result = SpeechRecognitionResult( recognizedWords: recognizedWords, confidence: confidence, alternatives: alternatives, + finalResult: finalResult, ); _resultController.add(result); }