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.
This commit is contained in:
parent
ea32370fcc
commit
d63124203b
|
|
@ -160,72 +160,6 @@ class _SpeechRecognitionPageState extends State<SpeechRecognitionPage> {
|
|||
});
|
||||
}
|
||||
|
||||
/// 更新文本控制器内容
|
||||
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<void> _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(
|
||||
|
|
|
|||
|
|
@ -9,10 +9,14 @@ class SpeechRecognitionResult {
|
|||
/// 备选识别结果
|
||||
final List<String> 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<String>.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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> alternatives,
|
||||
bool finalResult = false,
|
||||
}) {
|
||||
debugPrint('📤 [YxAsr] 发送识别结果: "$recognizedWords"');
|
||||
final result = SpeechRecognitionResult(
|
||||
recognizedWords: recognizedWords,
|
||||
confidence: confidence,
|
||||
alternatives: alternatives,
|
||||
finalResult: finalResult,
|
||||
);
|
||||
_resultController.add(result);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue