// 功能描述:故障描述语音识别适配,应用只复用一个系统识别实例,不保存录音。 // 版本:1.0.0。 import 'package:speech_to_text/speech_to_text.dart'; /// 识别结果为本轮完整短句;调用方负责替换临时结果,不能逐次追加。 abstract interface class RepairSpeech { Future start({ required void Function(String) onWords, required void Function(String) onError, required void Function() onDone, }); Future stop(); Future cancel(); } /// 系统回调只初始化一次,每轮重新绑定当前界面,离页后忽略迟到结果。 class SystemRepairSpeech implements RepairSpeech { SystemRepairSpeech._(); static final SystemRepairSpeech instance = SystemRepairSpeech._(); final SpeechToText _speech = SpeechToText(); void Function(String)? _words, _error; void Function()? _done; int _generation = 0; @override Future start({ required void Function(String) onWords, required void Function(String) onError, required void Function() onDone, }) async { final generation = ++_generation; _words = onWords; _error = onError; _done = onDone; final available = await _speech.initialize( onError: (error) => _error?.call(error.errorMsg), onStatus: (status) { if (status == SpeechToText.doneStatus) _done?.call(); }, options: [SpeechToText.androidNoBluetooth], ); if (generation != _generation || !available) return false; final locales = await _speech.locales(); if (generation != _generation) return false; String? locale; for (final item in locales) { if (item.localeId.toLowerCase().replaceAll('_', '-') == 'zh-cn') { locale = item.localeId; break; } } await _speech.listen( onResult: (result) { if (generation == _generation) _words?.call(result.recognizedWords); }, listenOptions: SpeechListenOptions( localeId: locale, partialResults: true, cancelOnError: true, listenMode: ListenMode.dictation, listenFor: const Duration(seconds: 45), pauseFor: const Duration(seconds: 5), ), ); return generation == _generation; } @override Future stop() => _speech.stop(); @override Future cancel() async { ++_generation; _words = null; _error = null; _done = null; await _speech.cancel(); } }