Files

78 lines
2.4 KiB
Dart
Raw Permalink Normal View History

// 功能描述:故障描述语音识别适配,应用只复用一个系统识别实例,不保存录音。
// 版本1.0.0。
import 'package:speech_to_text/speech_to_text.dart';
/// 识别结果为本轮完整短句;调用方负责替换临时结果,不能逐次追加。
abstract interface class RepairSpeech {
Future<bool> start({
required void Function(String) onWords,
required void Function(String) onError,
required void Function() onDone,
});
Future<void> stop();
Future<void> 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<bool> 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<void> stop() => _speech.stop();
@override
Future<void> cancel() async {
++_generation;
_words = null;
_error = null;
_done = null;
await _speech.cancel();
}
}