我正在使用Speech_to_文本包将语音识别结果存储在一个字符串变量中,以后可以用于不同的目的,到目前为止,我只想在屏幕上显示该字符串。我想实现与Whatsap录制类似的功能,因此我使用onLongPress
启动录制和onLongPress
停止录制。
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//Variable to show on screen
String text = 'Press the button and start speaking';
bool isListening = false;
final SpeechToText speech = SpeechToText();
String lastError = "";
String lastStatus = "";
String _currentLocaleId = "";
@override
void initState() {
super.initState();
initSpeechState();
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text(MyApp.title),
centerTitle: true,
),
body: SingleChildScrollView(
reverse: true,
padding: const EdgeInsets.all(30).copyWith(bottom: 150),
child: SubstringHighlight(
text: text,
terms: Command.all,
textStyle: TextStyle(
fontSize: 32.0,
color: Colors.black,
fontWeight: FontWeight.w400,
),
textStyleHighlight: TextStyle(
fontSize: 32.0,
color: Colors.red,
fontWeight: FontWeight.w400,
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: AvatarGlow(
animate: isListening,
endRadius: 75,
glowColor: Theme.of(context).primaryColor,
child: GestureDetector(
child: FloatingActionButton(
child: Icon(isListening ? Icons.mic : Icons.mic_none, size: 36),
/*onPressed: () {
toggleRecording();
print(text);
}*/
onPressed: () {},
),
onLongPress: () {
setState(() async {
text = await Speech.startListening();
});
// print(text);
},
onLongPressUp: Speech.stopListening,
//sendMessage(),
),
),
);
Future<void> initSpeechState() async {
bool hasSpeech = await speech.initialize(
onError: errorListener, onStatus: statusListener, debugLogging: false);
}
//Speech to text methods
Future<void> errorListener(SpeechRecognitionError error) async {
print("Received error status: $error, listening: ${speech.isListening}");
if (mounted) {
setState(() {
lastError = "${error.errorMsg} - ${error.permanent}";
print(lastError);
});
}
}
void statusListener(String status) {
setState(() {
print(status);
lastStatus = "$status";
});
}
}
OnLongPress和OnLongPressUp分别调用属于不同类的方法。
class Speech {
static final _speech = SpeechToText();
static String lastWords;
void cancelListening() {
_speech.cancel();
}
static Future startListening() async {
await _speech.listen(
onResult: resultListener,
listenFor: Duration(minutes: 1),
cancelOnError: true,
partialResults: false);
return lastWords;
}
static void stopListening() {
_speech.stop();
}
static resultListener(SpeechRecognitionResult result) {
lastWords = "${result.recognizedWords}";
//print(lastWords);
if (lastWords != '') {
//this is what I want to pass to the Text variable on the Main Widget
print(lastWords);
}
}
}
我认为我只需要将starListning
方法分配给主小部件中的Text变量
onLongPress: () {
setState(() async {
text = await Speech.startListening();
});
给定a
方法html" target="_blank">返回所需的字符串
static Future startListening() async {
await _speech.listen(
onResult: resultListener,
listenFor: Duration(minutes: 1),
cancelOnError: true,
partialResults: false);
return lastWords;
}
但是这种方法导致了一个redScreen错误:
════════ 用手势捕捉异常═══════════════════════════════════════════ 处理手势时引发了以下断言:setState()回调参数返回了Future。
调用_HomePageState#0ff8a上的setState()方法时带有返回Future的闭包或方法。也许它被标记为“异步”。
不要在对setState()的调用中执行异步工作,而是先执行工作(不更新小部件状态),然后在对setState()的调用中同步更新状态。
抛出异常时,这是堆栈的0状态。设定状态。包:flatter/../widgets/framework。dart:1270#1州。setState包:flatter/../widgets/framework。dart:1286#2#主页状态。建筑库\页\主页。dart:75#3手势识别器。invokeCallback包:颤振/../signatures/recognizer。dart:182#4长按手势识别器_选中长按启动程序包:颤振/手势/长按。飞镖:423。。。处理程序:“onLongPress”识别器:LongPressGestureRecognizer#ac97b调试所有者:GestureDetector状态:可能════════════════════════════════════════════════════════════════════════════════ I/flatter(11164):倾听
════════ widgets库捕获到异常═══════════════════════════════════ 对null调用了方法“toLowerCase”。Receiver:null尝试调用:toLowerCase(),相关的错误导致小部件是SubstringHighlight lib\page\home\u page。省道:45════════════════════════════════════════════════════════════════════════════════
,所以我想我可以使用resultListener
,它只有在出现voicerecognition
结果时才会被调用,以将lastwords
字符串发送到主小部件中的文本变量,但我还没有弄清楚如何发送。
P.D.在主窗口小部件上使用所有方法都是可行的,但我正在尝试实现干净的体系结构,所以我希望将该逻辑与Ui窗口小部件分开。
谢谢
//--------更新-----------------
我一直在研究,并找到了一种使用流的方法,
我在Speech类中创建了一个流控制器,然后在结果侦听器中添加了一个接收器。
static resultListener(SpeechRecognitionResult result) {
lastWords = "${result.recognizedWords}";
//print(lastWords);
if (lastWords != '') {
streamController.sink.add(lastWords);
}
在主窗口小部件中,我在OnLongPress函数中实现了流侦听。
onLongPress: () {
Speech.startListening();
Speech.streamController.stream.listen((data) {
print("recibido: $data");
setState(() {
text = data;
});
});
到目前为止,它运行良好,但我不知道这是否是处理数据传输的最佳方式。如果有人知道更好的方法,我将不胜感激,如果这是一个好方法,这将是这个问题的答案。
// .-............... 第二次更新--------------------
这种方法似乎有效,但我意识到,过了一段时间,我开始多次获得相同的数据
I/flatter(20460):监听I/flatter(20460):非监听I/flatter(20460):recibido:123 I/chatty(20460):uid=10166(com.example.speech\u to\u text\u示例)1。ui相同1第2行I/flatter(20460):recibido:123 I/chatty(20460):uid=10166(com.example.speech\u to\u text\u示例)1。ui相同1线I/颤振(20460):recibido:123
对于这个特殊的例子来说,这并不重要,但是如果我想使用这个字符串来做一些事情,比如消费一个网络服务,这是一个问题,我只想在每次开始录制时得到它一次。
谢谢
我以前的解决方案的问题是,我使用StreamController作为广播,每次我使用麦克风按钮时,监听器都会创建一个实例,导致冗余数据。为了解决这种情况,我在Speech类中创建了一个流控制器,然后在结果监听器中添加了一个接收器。
StreamController<String> streamController = StreamController();
static resultListener(SpeechRecognitionResult result) {
lastWords = "${result.recognizedWords}";
//print(lastWords);
if (lastWords != '') {
streamController.sink.add(lastWords);
}
在主窗口小部件中,我在initState中调用了streamController侦听器,因此侦听器只实例化了一次,这防止了冗余数据和“流已经被侦听”错误。
@override
void initState() {
super.initState();
initSpeechState();
speech.streamController.stream.listen((event) {
setState(() {
text = event;
print(text);
});
});
}
我的方法是在将future分配给setstate中的文本之前,使用一个额外的变量来存储future
onLongPress: () async {
var txt = await Speech.startListening();
setState(() {
text = txt;
});
}
我认为如果您想同时显示lastwords,您需要在lastwords更改时通知父类。将语音识别类移动到widget可以实现这一技巧。在顶部创建一个变量,而不是lastwords,并显示在文本小部件中。
void startListening() async {
await _speech.listen(
onResult: (val) =>
setState(() {
_lastwords=val.recognizedWords;
});
cancelOnError: true,
partialResults: false);
}
我是Flutter和Dart的新手。我有一些来自基于api json的数据,数据的变量称为。我从官方flutter留档中获取了这个示例代码,我希望能够使用变量并替换字符串文本,如下所示: 但是,我在第行标题中遇到了一个错误:const Text(data[index][“name]),,错误是类型常量创建的参数必须是常量表达式。此错误来自Android Studio本身(版本3.2) 但当我使用这
问题内容: 目前,我在隐藏的输入字段中回显某些变量,并在需要时使用Javascript读取它们。 我和一个同事现在正在考虑使用PHP生成一个额外的Javascript文件,该文件仅包含Javascript的所有变量。这样,变量已经存在,HTML中没有多余的代码。 有什么好的方法可以将变量从PHP传递到Javascript?我们的解决方案听起来如何? 问题答案: 通用数据传递 JavaScript常
问题内容: 我在PHP中有一个变量,我的JavaScript代码中需要它的值。如何将变量从PHP转换为JavaScript? 我有看起来像这样的代码: 我有需要和看起来类似以下内容的JavaScript代码: 问题答案: 实际上,有几种方法可以做到这一点。有些需要比其他更多的开销,有些被认为比其他更好。 没有特别的顺序: 使用AJAX从服务器获取所需的数据。 将数据回显到页面中的某个位置,然后使用
问题内容: 我想根据例如从jenkins传递的变量来运行测试用例,请选择要运行的测试用例:testcaseOne,testcaseTwo 在pom.xml(maven)中: 我有两个testng @test方法: 还有我的testng.xml文件: 如何根据我要运行的测试数量和数量来传递此参数?也许有完全不同的方式来做到这一点? 问题答案: 您可以在testng.xml文件http://testn
问题内容: 我看过类似的论坛,但无法获得任何有效的解决方案。我正在尝试将变量从Flask传递到我的JavaScript文件。这些值将用于我的JavaScript文件中的PubNub。 这是我的Python代码的一部分: 这是我的JavaScript代码(app.js)的一部分: 如果我在Settings.html文件中使用了此代码,而在app.js文件中却没有使用,则此代码有效。 问题答案: 该m
问题内容: 我正在使用Google Maps制作可以加载数据库中包含经纬度数据的标记的地图。我希望用户可以通过单击按钮来加载三个不同的“图层”。单击该按钮时,将在服务器上执行php函数,从而根据数据库中的信息创建xml文件。然后调用AJAX函数提取此xml数据,然后将其用于创建地图标记。没有为每个“层”使用单独的PHP函数(除了SQL查询所在的行,这是相同的东西),有没有办法将AJAX中的java