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();
|
|||
|
|
}
|
|||
|
|
}
|