78 lines
2.4 KiB
Dart
78 lines
2.4 KiB
Dart
// 功能描述:故障描述语音识别适配,应用只复用一个系统识别实例,不保存录音。
|
||
// 版本: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();
|
||
}
|
||
}
|