speech_page.dart
16.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
import 'package:common_utils/common_utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:one_key/res/colors.dart';
import 'package:one_key/utils/utils.dart';
import 'package:one_key/widgets/round_button.dart';
import 'package:one_key/widgets/v_empty_view.dart';
import 'package:speech_to_text_alibaba/speech_to_text_alibaba.dart';
import 'package:chinese_lunar_calendar/chinese_lunar_calendar.dart';
import 'package:intl/intl.dart';
class SpeechPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return SpeechPageState();
}
}
class SpeechPageState extends State<SpeechPage> {
String result = '';
List<dynamic> resultDate = [];
List<dynamic> resultPnum = [];
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
initAlibaba();
});
}
@override
void dispose() {
super.dispose();
SpeechToTextAlibaba.release();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initAlibaba() async {
await SpeechToTextAlibaba.initialize(
appKey: '88v9LR9mYYyvmSKw', token: '0bbc0ead105041239e2b118b47f30cde');
SpeechToTextAlibaba.setEngineEventHandler(
onCallBegin: () {
// setState(() {
// _isInCall = true;
// print("---------------onCallBegin-----------------");
// });
// _addMessage("通话已开始", false);
},
onCallEnd: () {
// setState(() {
// _isInCall = false;
// });
// print("---------------onCallEnd-----------------");
// _addMessage("通话已结束", false);
},
onError: (error) {
print("---------------发生错误-----------------");
Utils.showToast(error);
// _addMessage("发生错误: $error", false);
},
onPermission: (isPermission) {
print("---------------onPermission-----------------");
// 没有权限的话弹窗提示跳转设置页
},
onStopping: (isStop) {
print("---------------onNetworkQuality-----------------");
// setState(() {
// _networkQuality = quality;
// });
},
onVoiceIdChanged: (voiceId) {
print("---------------onVoiceIdChanged-----------------");
// _addMessage("AI声音已切换: $voiceId", false);
},
onRoleChanged: (role) {
print("---------------onRoleChanged-----------------");
// _addMessage("AI角色已切换: $role", false);
},
onEventAsrStarted: (state) {
print("---------------nEventAsrStarted----------------- $state");
// _addMessage("AI状态变更: $state", false);
},
onVolumeChanged: (Map<String, dynamic> volumeData) {
print("---------------onVolumeChanged-----------------");
// setState(() {
// _currentUid = volumeData['uid'] as String;
// final int volume = volumeData['volume'] as int;
// _isUserSpeaking = volume > 0;
// print('Volume Changed: $volume, Speaking: $_isUserSpeaking');
// });
},
onEventAsrPartitalResult: (String asrData) {
result = asrData;
// setState(() {});
_getDate(result);
print(
"---------------onAIAgentSubtitleNotify${asrData}-----------------");
// setState(() {
// _currentASRText = asrData['text'] as String;
// _addMessage(_currentASRText, false);
// });
},
onEventAsrResult: (String data) {
print("---------------onEventAsrResul${data}-----------------");
setState(() {
result = data;
// _currentUserAsrText = data['text'] as String;
// _isUserSpeakingEnd = data['isSentenceEnd'] as bool;
// _currentSentenceId = data['sentenceId'] as int;
// VoicePrintStatusCode voicePrintStatus = data['voicePrintStatus'];
// switch (voicePrintStatus) {
// case VoicePrintStatusCode.speakerRecognized:
// print('说话人已识别');
// break;
// case VoicePrintStatusCode.speakerNotRecognized:
// print('说话人未识别');
// break;
// case VoicePrintStatusCode.disable:
// print('声纹识别已禁用');
// break;
// case VoicePrintStatusCode.enableWithoutRegister:
// print('声纹识别已启用但未注册');
// break;
// case VoicePrintStatusCode.unknown:
// print('未知状态');
// break;
// }
});
},
);
await SpeechToTextAlibaba.startDialog();
}
Map<String, int> chineseNumberMap = {
'零': 0,
'一': 1,
'二': 2,
'三': 3,
'四': 4,
'五': 5,
'六': 6,
'七': 7,
'八': 8,
'九': 9,
'十': 10,
};
int chineseToArabic(String chineseNumber) {
// 处理多位数字,例如“十一”、“二十三”等
int result = 0;
int currentDigit = 0; // 当前处理的数字值
int multiplier = 1; // 当前的乘数,用于计算十位和百位等
for (int i = chineseNumber.length - 1; i >= 0; i--) {
String digit = chineseNumber[i];
if (chineseNumberMap.containsKey(digit)) {
int value = chineseNumberMap[digit]!;
if (value < 10) {
// 处理个位数和十位数
if (value == 10) {
// 遇到“十”,乘以10但不加到结果中,直到下一个数出现
multiplier = 10;
} else {
// 处理个位数,乘以当前的乘数并加到结果中
result += value * multiplier;
multiplier = 1; // 重置乘数
}
} else {
// 处理多位数字的中间位,例如“十一”中的“一”
result += value * multiplier; // 直接加到结果中,因为已经是正确的值了(如10或100等)
multiplier *= 10; // 增加乘数以准备下一个数字的乘法
}
} else {
// 非数字字符直接忽略,实际应用中可以根据需要处理错误或警告
continue;
}
}
return result;
}
//筛选日期
_getDate(String result) {
result = result.replaceAll('幺', '1');
// 定义正则表达式,匹配“明天”或“春节”
RegExp regExp = RegExp(r"今天 | 明天|后天|大后天|元旦|春节|除夕|国庆");
// 使用RegExp的allMatches方法来找到所有匹配项
Iterable<Match> matches = regExp.allMatches(result);
// 提取所有匹配的文本
List<String?> dates = matches.map((match) => match.group(0)).toList();
// 打印结果
print(dates); // 输出: [明天, 春节]
if (dates.contains('春节')) {
String str = '';
final lunarCalendar = LunarCalendar.from(
utcDateTime: DateTime.now().toUtc(),
);
str = '${lunarCalendar.chineseNewYearString}';
resultDate.add(str);
}
if (dates.contains('国庆')) {
// 获取当前年份的国庆节日期
DateTime nationalDay = DateTime(DateTime.now().year, 10, 1);
// 检查国庆节是否已经到来
if (DateTime.now().isAfter(nationalDay)) {
// '国庆节已经过去,用明年的日期
nationalDay = DateTime(DateTime.now().year + 1, 10, 1);
}
resultDate
.add(DateUtil.formatDate(nationalDay, format: DateFormats.y_mo_d));
}
if (dates.contains('元旦')) {
// 获取当前年份的元旦日期
DateTime nationalDay = DateTime(DateTime.now().year, 1, 1);
// 检查元旦是否已经到来
if (DateTime.now().isAfter(nationalDay)) {
// '元旦已经过去,用明年的日期
nationalDay = DateTime(DateTime.now().year + 1, 1, 1);
}
resultDate
.add(DateUtil.formatDate(nationalDay, format: DateFormats.y_mo_d));
}
if (dates.contains('除夕')) {
final lunarCalendar = LunarCalendar.from(
utcDateTime: DateTime.now().toUtc(),
);
DateTime chuxi = DateUtil.getDateTime(lunarCalendar.chineseNewYearString)
.subtract(Duration(days: 1));
resultDate.add(DateUtil.formatDate(chuxi, format: DateFormats.y_mo_d));
}
//今天
if (dates.contains('今天')) {
// 获取当前日期和时间
DateTime now = DateTime.now();
resultDate.add(DateUtil.formatDate(now, format: DateFormats.y_mo_d));
}
//明天
if (dates.contains('明天')) {
// 获取当前日期和时间
DateTime tomorrow = DateTime.now().add(Duration(days: 1));
resultDate.add(DateUtil.formatDate(tomorrow, format: DateFormats.y_mo_d));
}
//后天
if (dates.contains('后天')) {
// 获取当前日期和时间
DateTime houday = DateTime.now().add(Duration(days: 2));
resultDate.add(DateUtil.formatDate(houday, format: DateFormats.y_mo_d));
}
//大后天
if (dates.contains('大后天')) {
// 获取当前日期和时间
DateTime houday = DateTime.now().add(Duration(days: 3));
resultDate.add(DateUtil.formatDate(houday, format: DateFormats.y_mo_d));
}
// 几月几号
DateTime? dateHao = _haoDate(result);
if (dateHao != null) {
resultDate.add(DateUtil.formatDate(dateHao, format: DateFormats.y_mo_d));
}
//2025年3月5日
_extractDatesFromText(result);
//周几
RegExp regExpWeek = RegExp(r'周一|周二|周三|周四|周五|周六|周日');
Iterable<Match> matchesWeek = regExpWeek.allMatches(result);
DateTime now = DateTime.now();
// 获取当前是周几(0表示周日,1表示周一,依此类推)
int weekday = now.weekday;
for (Match matcht in matchesWeek) {
int? targetWeekday;
String? weekdayText = matcht.group(0); // 获取匹配到的文本
if (weekdayText == '周一') {
targetWeekday = 1; // 周三对应的数字是4(周一为1)
} else if (weekdayText == '周二') {
targetWeekday = 2; // 周三对应的数字是4(周一为1)
} else if (weekdayText == '周三') {
targetWeekday = 3; // 周三对应的数字是4(周一为1)
} else if (weekdayText == '周四') {
targetWeekday = 4; // 周三对应的数字是4(周一为1)
} else if (weekdayText == '周五') {
targetWeekday = 5; // 周三对应的数字是4(周一为1)
} else if (weekdayText == '周六') {
targetWeekday = 6; // 周三对应的数字是4(周一为1)
} else if (weekdayText == '周日') {
targetWeekday = 7; // 周三对应的数字是4(周一为1)
} else {
// 处理其他情况或不做任何操作。
}
if (targetWeekday != null) {
int daysToAdd = (targetWeekday - weekday + 7) % 7; // 计算需要添加的天数
// 计算具体日期
DateTime targetDate = now.add(Duration(days: daysToAdd));
resultDate
.add(DateUtil.formatDate(targetDate, format: DateFormats.y_mo_d));
}
}
//下周几
//姓名(非必填)
//性别(非必填)识别女士、先生、公司
//手机号(非必填)识别手机号、座机号
//到店时间(必填,没有准确到店时间,有日期也行)
//餐段(必填)识别早上|早餐|早饭|上午|中午|午餐|午饭|下午|晚上|晚餐|晚饭
// 合并数组并去重
Set setArr = new Set(); //用set进行去重
setArr.addAll(resultDate); //把数组塞进set里
resultDate = setArr.toList();
//提取人数
RegExp regExpPnum = RegExp(r'\b(几[人个位]{1,2,3})\b');
Iterable<RegExpMatch> matchesPnum = regExpPnum.allMatches(result);
for (RegExpMatch match in matchesPnum) {
resultPnum.add(match.group(1));
}
// 合并数组并去重
Set setArrPnum = new Set(); //用set进行去重
setArrPnum.addAll(resultPnum); //把数组塞进set里
resultPnum = setArrPnum.toList();
setState(() {});
}
//带有“几月几号”日期解析
DateTime? _haoDate(String result) {
RegExp regExp = RegExp(r'(\d+)月(\d+)号'); // 正则表达式匹配数字和“号”
Match? match = regExp.firstMatch(result);
if (match != null) {
int month = int.parse(match.group(1)!); // 获取月份并转换为整数
int day = int.parse(match.group(2)!); // 获取日期并转换为整数
DateTime date =
DateTime(2000, month, day); // 假设年份为2000,根据需要可以调整年份或使用完整日期信息。
return date;
// print("解析后的日期: ${date.toString()}"); // 输出解析后的日期
} else {
print("日期解析失败");
return null;
}
}
_extractDatesFromText(String text) {
// 定义一个正则表达式来匹配日期
// 示例:匹配形如 "2023年3月15日" 或 "15/03/2023" 的日期
RegExp regExp = RegExp(r'\b(\d{1,2})[/-](\d{1,2})[/-]?(\d{4})\b');
// List<DateTime> dates = [];
Iterable<Match> matches = regExp.allMatches(text);
for (Match match in matches) {
String day = match.group(1)!;
String month = match.group(2)!;
String year = match.group(3)!;
// 尝试解析日期
DateTime? date = DateFormat('dd/MM/yyyy').parse('$day/$month/$year');
if (date != null) {
resultDate.add(DateUtil.formatDate(date, format: DateFormats.y_mo_d));
} else {
// 对于不符合格式的日期,可以尝试其他格式
date = DateFormat('yyyy年MM月dd日').parse('$year年$month月$day日');
if (date != null) {
resultDate.add(DateUtil.formatDate(date, format: DateFormats.y_mo_d));
}
}
}
}
// List<DateTime> extractDatesFromText(String text) {
// List<DateTime> dates = [];
// List<String> formats = ['dd/MM/yyyy', 'yyyy年MM月dd日', 'MM-dd-yyyy']; // 添加更多格式如果需要
// for (String format in formats) {
// try {
// DateTime date = DateFormat(format).parseStrict(text); // 使用parseStrict避免部分匹配问题
// dates.add(date);
// } catch (e) {
// // 处理解析失败的情况,例如跳过或记录日志等
// }
// }
// return dates;
// }
@override
Widget build(BuildContext context) {
return Center(
child: SingleChildScrollView(
child: Column(
children: [
Container(
height: ScreenUtil().setWidth(48),
alignment: Alignment.center,
child: Text('请讲话~',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenUtil().setSp(32),
color: MyColours.color_ffffff)),
),
VEmptyView(40),
Container(
// height: ScreenUtil().setWidth(48),
alignment: Alignment.center,
child: Text(result,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenUtil().setSp(32),
color: MyColours.color_ffffff)),
),
VEmptyView(40),
Container(
// height: ScreenUtil().setWidth(48),
alignment: Alignment.center,
child: Text('日期:${resultDate.join('、')}',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenUtil().setSp(32),
color: MyColours.color_ffffff)),
),
VEmptyView(40),
Container(
// height: ScreenUtil().setWidth(48),
alignment: Alignment.center,
child: Text('人数:${resultPnum.join('、')}',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: ScreenUtil().setSp(32),
color: MyColours.color_ffffff)),
),
VEmptyView(40),
RoundButton(
text: '结束识别',
width:
(ScreenUtil().screenWidth - ScreenUtil().setWidth(62) * 2) /
2,
height: ScreenUtil().setWidth(112),
// radius: ScreenUtil().setWidth(10),
gradientStart: Colors.transparent,
gradientEnd: Colors.transparent,
textColor: MyColours.color_ffffff,
isBold: true,
fontSize: 34,
onPressed: () async {
await SpeechToTextAlibaba.stopDialog();
// if (Navigator.canPop(context)) {
// Navigator.pop(context);
// }
}),
],
),
));
}
}