Flutter/Dart:任何语言的语音转文本(离线和连续)
Flutter/Dart: speech to text (offline and continuous) for any language
是否有任何软件包可用于创建可将语音处理为文本的应用程序?
它应该包括以下功能:
- 离线语音转文本
- 连续收听(10-30分钟)
- 识别器适用于Android/IOS支持的所有语言
到目前为止我找到了这个 https://pub.dev/packages/speech_recognition 但它说:
the iOS API sends intermediate results, On my Android device, only the
final transcription is received
Other limitations: On iOS, by default the plugin is configured for
French, English, Russian, Spanish, Italian. On Android, without
additional installations, it will probably works only with the default
device locale.
有人测试过这个包并且有好的结果?或者您还有其他建议吗?
https://pub.dev/packages/speech_recognition是最好的选择。
它基于 SpeechRecognizer 并提供离线语音到文本。
无法连续收听。即使付费的在线 Cloud Speech-to-Text API 也不允许这样做,因为它很危险(滥用等)。
在 iOS 上,插件默认配置为法语、英语、俄语、西班牙语、意大利语,但您可以将缺少的语言添加到 swift 源文件中。
所以你最终不会找到更好的语音识别插件,即使它并不完美。
我现在正在使用 https://pub.dev/packages/speech_to_text。它得到积极维护并且工作得很好。我觉得可以写一些自定义代码让它连续监听。
编辑:
应要求,请看下面的持续收听逻辑。我只是将它用作概念证明,因此我不会推荐将它用于生产应用程序。据我所知 Android API 不支持开箱即用的连续收听。
SpeechRecognitionBloc
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:template_mobile/core/sevices/speech_recognition_service.dart';
import 'package:template_mobile/core/state/event/speech_recognition_event.dart';
import 'package:template_mobile/core/state/state/speech_recognition_state.dart';
class SpeechRecognitionBloc
extends Bloc<SpeechRecognitionEvent, SpeechRecognitionState> {
final SpeechRecognitionService speechRecognitionService;
SpeechRecognitionBloc({
@required this.speechRecognitionService,
}) : assert(speechRecognitionService != null) {
speechRecognitionService.errors.stream.listen((errorResult) {
add(SpeechRecognitionErrorEvent(
error: "${errorResult.errorMsg} - ${errorResult.permanent}",
));
});
speechRecognitionService.statuses.stream.listen((status) {
if (state is SpeechRecognitionRecognizedState) {
var currentState = state as SpeechRecognitionRecognizedState;
if (currentState.finalResult) {
add(SpeechRecognitionStatusChangedEvent());
}
}
});
speechRecognitionService.words.stream.listen((speechResult) {
add(SpeechRecognitionRecognizedEvent(
words: speechResult.recognizedWords,
finalResult: speechResult.finalResult,
));
});
}
@override
SpeechRecognitionState get initialState =>
SpeechRecognitionUninitializedState();
@override
Stream<SpeechRecognitionState> mapEventToState(
SpeechRecognitionEvent event) async* {
if (event is SpeechRecognitionInitEvent) {
var hasSpeech = await speechRecognitionService.initSpeech();
if (hasSpeech) {
yield SpeechRecognitionAvailableState();
} else {
yield SpeechRecognitionUnavailableState();
}
}
if (event is SpeechRecognitionStartPressEvent) {
yield SpeechRecognitionStartPressedState();
add(SpeechRecognitionStartEvent());
}
if (event is SpeechRecognitionStartEvent) {
speechRecognitionService.startListening();
yield SpeechRecognitionStartedState();
}
if (event is SpeechRecognitionStopPressEvent) {
yield SpeechRecognitionStopPressedState();
add(SpeechRecognitionStopEvent());
}
if (event is SpeechRecognitionStopEvent) {
speechRecognitionService.stopListening();
yield SpeechRecognitionStopedState();
}
if (event is SpeechRecognitionCancelEvent) {
speechRecognitionService.cancelListening();
yield SpeechRecognitionCanceledState();
}
if (event is SpeechRecognitionRecognizedEvent) {
yield SpeechRecognitionRecognizedState(
words: event.words, finalResult: event.finalResult);
if (event.finalResult == true &&
speechRecognitionService.statuses.value == 'notListening') {
await Future.delayed(Duration(milliseconds: 50));
add(SpeechRecognitionStatusChangedEvent());
}
}
if (event is SpeechRecognitionErrorEvent) {
yield SpeechRecognitionErrorState(error: event.error);
// Just for UI updates for the state to propagates
await Future.delayed(Duration(milliseconds: 50));
add(SpeechRecognitionInitEvent());
await Future.delayed(Duration(milliseconds: 50));
add(SpeechRecognitionStartPressEvent());
}
if (event is SpeechRecognitionStatusChangedEvent) {
yield SpeechRecognitionStatusState();
add(SpeechRecognitionStartPressEvent());
}
}
}
语音识别服务
import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
class SpeechRecognitionService {
final SpeechToText speech = SpeechToText();
var errors = StreamController<SpeechRecognitionError>();
var statuses = BehaviorSubject<String>();
var words = StreamController<SpeechRecognitionResult>();
var _localeId = '';
Future<bool> initSpeech() async {
bool hasSpeech = await speech.initialize(
onError: errorListener,
onStatus: statusListener,
);
if (hasSpeech) {
var systemLocale = await speech.systemLocale();
_localeId = systemLocale.localeId;
}
return hasSpeech;
}
void startListening() {
speech.stop();
speech.listen(
onResult: resultListener,
listenFor: Duration(minutes: 1),
localeId: _localeId,
onSoundLevelChange: null,
cancelOnError: true,
partialResults: true);
}
void errorListener(SpeechRecognitionError error) {
errors.add(error);
}
void statusListener(String status) {
statuses.add(status);
}
void resultListener(SpeechRecognitionResult result) {
words.add(result);
}
void stopListening() {
speech.stop();
}
void cancelListening() {
speech.cancel();
}
}
如果您愿意编写自定义平台特定代码https://flutter.dev/docs/development/platform-integration/platform-channels, for Android you can use https://github.com/alphacep/vosk-android-demo来获得您想要的。
另一种方法是构建您自己的键盘 IME 以使用 How Can I Implement Google Voice Typing In My Application? 中建议的语音输入。
是否有任何软件包可用于创建可将语音处理为文本的应用程序?
它应该包括以下功能:
- 离线语音转文本
- 连续收听(10-30分钟)
- 识别器适用于Android/IOS支持的所有语言
到目前为止我找到了这个 https://pub.dev/packages/speech_recognition 但它说:
the iOS API sends intermediate results, On my Android device, only the final transcription is received
Other limitations: On iOS, by default the plugin is configured for French, English, Russian, Spanish, Italian. On Android, without additional installations, it will probably works only with the default device locale.
有人测试过这个包并且有好的结果?或者您还有其他建议吗?
https://pub.dev/packages/speech_recognition是最好的选择。 它基于 SpeechRecognizer 并提供离线语音到文本。
无法连续收听。即使付费的在线 Cloud Speech-to-Text API 也不允许这样做,因为它很危险(滥用等)。
在 iOS 上,插件默认配置为法语、英语、俄语、西班牙语、意大利语,但您可以将缺少的语言添加到 swift 源文件中。
所以你最终不会找到更好的语音识别插件,即使它并不完美。
我现在正在使用 https://pub.dev/packages/speech_to_text。它得到积极维护并且工作得很好。我觉得可以写一些自定义代码让它连续监听。
编辑:
应要求,请看下面的持续收听逻辑。我只是将它用作概念证明,因此我不会推荐将它用于生产应用程序。据我所知 Android API 不支持开箱即用的连续收听。
SpeechRecognitionBloc
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'package:template_mobile/core/sevices/speech_recognition_service.dart';
import 'package:template_mobile/core/state/event/speech_recognition_event.dart';
import 'package:template_mobile/core/state/state/speech_recognition_state.dart';
class SpeechRecognitionBloc
extends Bloc<SpeechRecognitionEvent, SpeechRecognitionState> {
final SpeechRecognitionService speechRecognitionService;
SpeechRecognitionBloc({
@required this.speechRecognitionService,
}) : assert(speechRecognitionService != null) {
speechRecognitionService.errors.stream.listen((errorResult) {
add(SpeechRecognitionErrorEvent(
error: "${errorResult.errorMsg} - ${errorResult.permanent}",
));
});
speechRecognitionService.statuses.stream.listen((status) {
if (state is SpeechRecognitionRecognizedState) {
var currentState = state as SpeechRecognitionRecognizedState;
if (currentState.finalResult) {
add(SpeechRecognitionStatusChangedEvent());
}
}
});
speechRecognitionService.words.stream.listen((speechResult) {
add(SpeechRecognitionRecognizedEvent(
words: speechResult.recognizedWords,
finalResult: speechResult.finalResult,
));
});
}
@override
SpeechRecognitionState get initialState =>
SpeechRecognitionUninitializedState();
@override
Stream<SpeechRecognitionState> mapEventToState(
SpeechRecognitionEvent event) async* {
if (event is SpeechRecognitionInitEvent) {
var hasSpeech = await speechRecognitionService.initSpeech();
if (hasSpeech) {
yield SpeechRecognitionAvailableState();
} else {
yield SpeechRecognitionUnavailableState();
}
}
if (event is SpeechRecognitionStartPressEvent) {
yield SpeechRecognitionStartPressedState();
add(SpeechRecognitionStartEvent());
}
if (event is SpeechRecognitionStartEvent) {
speechRecognitionService.startListening();
yield SpeechRecognitionStartedState();
}
if (event is SpeechRecognitionStopPressEvent) {
yield SpeechRecognitionStopPressedState();
add(SpeechRecognitionStopEvent());
}
if (event is SpeechRecognitionStopEvent) {
speechRecognitionService.stopListening();
yield SpeechRecognitionStopedState();
}
if (event is SpeechRecognitionCancelEvent) {
speechRecognitionService.cancelListening();
yield SpeechRecognitionCanceledState();
}
if (event is SpeechRecognitionRecognizedEvent) {
yield SpeechRecognitionRecognizedState(
words: event.words, finalResult: event.finalResult);
if (event.finalResult == true &&
speechRecognitionService.statuses.value == 'notListening') {
await Future.delayed(Duration(milliseconds: 50));
add(SpeechRecognitionStatusChangedEvent());
}
}
if (event is SpeechRecognitionErrorEvent) {
yield SpeechRecognitionErrorState(error: event.error);
// Just for UI updates for the state to propagates
await Future.delayed(Duration(milliseconds: 50));
add(SpeechRecognitionInitEvent());
await Future.delayed(Duration(milliseconds: 50));
add(SpeechRecognitionStartPressEvent());
}
if (event is SpeechRecognitionStatusChangedEvent) {
yield SpeechRecognitionStatusState();
add(SpeechRecognitionStartPressEvent());
}
}
}
语音识别服务
import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'package:speech_to_text/speech_recognition_error.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
class SpeechRecognitionService {
final SpeechToText speech = SpeechToText();
var errors = StreamController<SpeechRecognitionError>();
var statuses = BehaviorSubject<String>();
var words = StreamController<SpeechRecognitionResult>();
var _localeId = '';
Future<bool> initSpeech() async {
bool hasSpeech = await speech.initialize(
onError: errorListener,
onStatus: statusListener,
);
if (hasSpeech) {
var systemLocale = await speech.systemLocale();
_localeId = systemLocale.localeId;
}
return hasSpeech;
}
void startListening() {
speech.stop();
speech.listen(
onResult: resultListener,
listenFor: Duration(minutes: 1),
localeId: _localeId,
onSoundLevelChange: null,
cancelOnError: true,
partialResults: true);
}
void errorListener(SpeechRecognitionError error) {
errors.add(error);
}
void statusListener(String status) {
statuses.add(status);
}
void resultListener(SpeechRecognitionResult result) {
words.add(result);
}
void stopListening() {
speech.stop();
}
void cancelListening() {
speech.cancel();
}
}
如果您愿意编写自定义平台特定代码https://flutter.dev/docs/development/platform-integration/platform-channels, for Android you can use https://github.com/alphacep/vosk-android-demo来获得您想要的。
另一种方法是构建您自己的键盘 IME 以使用 How Can I Implement Google Voice Typing In My Application? 中建议的语音输入。