我正在 Flutter 中开发我的第一个应用程序,我对 Java 和 js 有一点经验,但我以前从未使用 Flutter,很抱歉,如果我的问题对你来说很荒谬。
该应用程序是语音助手聊天机器人,它应该对客户收到的每条新消息执行文本到语音转换,我的问题是,由于我使用的是Firebase消息传递,因此我收到的所有请求都在异步调用中,但是我需要同步对文本到语音服务的访问,否则我会遇到一个文本中断另一个文本的问题。
这是我的代码目前的样子: 火力消息传递:
onMessage: (Map<String, dynamic> message) {
return this.handleBotMessage(appState, message);
},
表示如何处理每个特定消息的方法:
Future handleBotMessage(
Store<AppState> store,
Map<String, dynamic> dataJson,
) {
#logic that convert the message into json and extracts the message type
if (type == MessageType.CHAT_MESSAGE) {
return handleChatMessage(store, subtype, messageMap);
}
}
处理文本消息的方法:
Future<dynamic> handleChatMessage(
Store<AppState> store,
MessageSubtype subtype,
Map<String, dynamic> message,
) {
#Text to speach is build as a singleton and this always returns the same instance
TextToSpeech tts = TextToSpeech();
if (subtype == MessageSubtype.TEXT) {
TextMessage textMessage = TextMessage.fromJson(message);
return tts
.speak(textMessage.text)
.then((result) => store.dispatch(NewBotMessageAction(textMessage)));
} else if (subtype == MessageSubtype.QUICK_REPLY) {
QuickReplyMessage qrMessage = QuickReplyMessage.fromJson(message);
return tts
.speak(qrMessage.text)
.then((result) => store.dispatch(NewQrOptionsAction(qrMessage)));
} else {
throw new Exception('Unexpected message subtype!');
}
}
实际执行文本到语音转换的方法
Future<dynamic> speak(String text) async {
return flutterTts.speak(text).then((resp) {
ttsRunning = false;
print(resp);
return resp;
}, onError: (obj, st) {
ttsRunning = false;
print(obj);
print(st.toString());
});
}
文本到语音初始化
Future init() async {
await flutterTts.setLanguage("en-US");
var res = await flutterTts.isLanguageAvailable("en-US");
print(res);
return res;
}
https://pub.dev/packages/flutter_tts
好的,我已经找到了解决方案,正如 frank06 指出的那样,问题在于 flutter tts 会立即完成未来,而不是在整个短语说完之后。
所以这是我的解决方案,它并不完美,但它有效:
Completer completer;
Future<dynamic> speak(String text) {
print('Started speeking');
print(new DateTime.now().toIso8601String());
if (TextToSpeech.lastRequest == null) {
lastRequest = _executeSpeech(text);
} else {
lastRequest = lastRequest.then((resp) {
return _executeSpeech(text);
});
}
return lastRequest;
}
Future<dynamic> _executeSpeech(String text) {
completer = Completer();
flutterTts.speak(text).then((resp) {
ttsRunning = false;
print(resp);
return resp;
}, onError: (obj, st) {
ttsRunning = false;
print(obj);
print(st.toString());
});
return completer.future;
}
flutterTts.setCompletionHandler(() {
print('Finished speeking');
print(new DateTime.now().toIso8601String());
ttsState = TtsState.stopped;
completer.complete(ttsState);
});
flutterTts.setErrorHandler((msg) {
ttsState = TtsState.stopped;
completer.complete(ttsState);
});
如果您不希望新消息打断正在说出的消息,则可以将它们排队。这样,新消息将等待当前消息完成。看看这种方法:
飞镖的未来队列