feat: upgrade local speech recognition engine to SenseVoice-Small with hardware audio enhancements
This commit is contained in:
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,502 +0,0 @@
|
|||||||
<blk> 0
|
|
||||||
<sos/eos> 1
|
|
||||||
<unk> 2
|
|
||||||
S 3
|
|
||||||
▁THE 4
|
|
||||||
▁A 5
|
|
||||||
T 6
|
|
||||||
▁AND 7
|
|
||||||
ED 8
|
|
||||||
▁OF 9
|
|
||||||
▁TO 10
|
|
||||||
E 11
|
|
||||||
D 12
|
|
||||||
N 13
|
|
||||||
ING 14
|
|
||||||
▁IN 15
|
|
||||||
Y 16
|
|
||||||
M 17
|
|
||||||
C 18
|
|
||||||
▁I 19
|
|
||||||
A 20
|
|
||||||
P 21
|
|
||||||
▁HE 22
|
|
||||||
R 23
|
|
||||||
O 24
|
|
||||||
L 25
|
|
||||||
RE 26
|
|
||||||
I 27
|
|
||||||
U 28
|
|
||||||
ER 29
|
|
||||||
▁IT 30
|
|
||||||
LY 31
|
|
||||||
▁THAT 32
|
|
||||||
▁WAS 33
|
|
||||||
▁ 34
|
|
||||||
▁S 35
|
|
||||||
AR 36
|
|
||||||
▁BE 37
|
|
||||||
F 38
|
|
||||||
▁C 39
|
|
||||||
IN 40
|
|
||||||
B 41
|
|
||||||
▁FOR 42
|
|
||||||
OR 43
|
|
||||||
LE 44
|
|
||||||
' 45
|
|
||||||
▁HIS 46
|
|
||||||
▁YOU 47
|
|
||||||
AL 48
|
|
||||||
▁RE 49
|
|
||||||
V 50
|
|
||||||
▁B 51
|
|
||||||
G 52
|
|
||||||
RI 53
|
|
||||||
▁E 54
|
|
||||||
▁WITH 55
|
|
||||||
▁T 56
|
|
||||||
▁AS 57
|
|
||||||
LL 58
|
|
||||||
▁P 59
|
|
||||||
▁HER 60
|
|
||||||
ST 61
|
|
||||||
▁HAD 62
|
|
||||||
▁SO 63
|
|
||||||
▁F 64
|
|
||||||
W 65
|
|
||||||
CE 66
|
|
||||||
▁IS 67
|
|
||||||
ND 68
|
|
||||||
▁NOT 69
|
|
||||||
TH 70
|
|
||||||
▁BUT 71
|
|
||||||
EN 72
|
|
||||||
▁SHE 73
|
|
||||||
▁ON 74
|
|
||||||
VE 75
|
|
||||||
ON 76
|
|
||||||
SE 77
|
|
||||||
▁DE 78
|
|
||||||
UR 79
|
|
||||||
▁G 80
|
|
||||||
CH 81
|
|
||||||
K 82
|
|
||||||
TER 83
|
|
||||||
▁AT 84
|
|
||||||
IT 85
|
|
||||||
▁ME 86
|
|
||||||
RO 87
|
|
||||||
NE 88
|
|
||||||
RA 89
|
|
||||||
ES 90
|
|
||||||
IL 91
|
|
||||||
NG 92
|
|
||||||
IC 93
|
|
||||||
▁NO 94
|
|
||||||
▁HIM 95
|
|
||||||
ENT 96
|
|
||||||
IR 97
|
|
||||||
▁WE 98
|
|
||||||
H 99
|
|
||||||
▁DO 100
|
|
||||||
▁ALL 101
|
|
||||||
▁HAVE 102
|
|
||||||
LO 103
|
|
||||||
▁BY 104
|
|
||||||
▁MY 105
|
|
||||||
▁MO 106
|
|
||||||
▁THIS 107
|
|
||||||
LA 108
|
|
||||||
▁ST 109
|
|
||||||
▁WHICH 110
|
|
||||||
▁CON 111
|
|
||||||
▁THEY 112
|
|
||||||
CK 113
|
|
||||||
TE 114
|
|
||||||
▁SAID 115
|
|
||||||
▁FROM 116
|
|
||||||
▁GO 117
|
|
||||||
▁WHO 118
|
|
||||||
▁TH 119
|
|
||||||
▁OR 120
|
|
||||||
▁D 121
|
|
||||||
▁W 122
|
|
||||||
VER 123
|
|
||||||
LI 124
|
|
||||||
▁SE 125
|
|
||||||
▁ONE 126
|
|
||||||
▁CA 127
|
|
||||||
▁AN 128
|
|
||||||
▁LA 129
|
|
||||||
▁WERE 130
|
|
||||||
EL 131
|
|
||||||
▁HA 132
|
|
||||||
▁MAN 133
|
|
||||||
▁FA 134
|
|
||||||
▁EX 135
|
|
||||||
AD 136
|
|
||||||
▁SU 137
|
|
||||||
RY 138
|
|
||||||
▁MI 139
|
|
||||||
AT 140
|
|
||||||
▁BO 141
|
|
||||||
▁WHEN 142
|
|
||||||
AN 143
|
|
||||||
THER 144
|
|
||||||
PP 145
|
|
||||||
ATION 146
|
|
||||||
▁FI 147
|
|
||||||
▁WOULD 148
|
|
||||||
▁PRO 149
|
|
||||||
OW 150
|
|
||||||
ET 151
|
|
||||||
▁O 152
|
|
||||||
▁THERE 153
|
|
||||||
▁HO 154
|
|
||||||
ION 155
|
|
||||||
▁WHAT 156
|
|
||||||
▁FE 157
|
|
||||||
▁PA 158
|
|
||||||
US 159
|
|
||||||
MENT 160
|
|
||||||
▁MA 161
|
|
||||||
UT 162
|
|
||||||
▁OUT 163
|
|
||||||
▁THEIR 164
|
|
||||||
▁IF 165
|
|
||||||
▁LI 166
|
|
||||||
▁K 167
|
|
||||||
▁WILL 168
|
|
||||||
▁ARE 169
|
|
||||||
ID 170
|
|
||||||
▁RO 171
|
|
||||||
DE 172
|
|
||||||
TION 173
|
|
||||||
▁WA 174
|
|
||||||
PE 175
|
|
||||||
▁UP 176
|
|
||||||
▁SP 177
|
|
||||||
▁PO 178
|
|
||||||
IGHT 179
|
|
||||||
▁UN 180
|
|
||||||
RU 181
|
|
||||||
▁LO 182
|
|
||||||
AS 183
|
|
||||||
OL 184
|
|
||||||
▁LE 185
|
|
||||||
▁BEEN 186
|
|
||||||
▁SH 187
|
|
||||||
▁RA 188
|
|
||||||
▁SEE 189
|
|
||||||
KE 190
|
|
||||||
UL 191
|
|
||||||
TED 192
|
|
||||||
▁SA 193
|
|
||||||
UN 194
|
|
||||||
UND 195
|
|
||||||
ANT 196
|
|
||||||
▁NE 197
|
|
||||||
IS 198
|
|
||||||
▁THEM 199
|
|
||||||
CI 200
|
|
||||||
GE 201
|
|
||||||
▁COULD 202
|
|
||||||
▁DIS 203
|
|
||||||
OM 204
|
|
||||||
ISH 205
|
|
||||||
HE 206
|
|
||||||
EST 207
|
|
||||||
▁SOME 208
|
|
||||||
ENCE 209
|
|
||||||
ITY 210
|
|
||||||
IVE 211
|
|
||||||
▁US 212
|
|
||||||
▁MORE 213
|
|
||||||
▁EN 214
|
|
||||||
ARD 215
|
|
||||||
ATE 216
|
|
||||||
▁YOUR 217
|
|
||||||
▁INTO 218
|
|
||||||
▁KNOW 219
|
|
||||||
▁CO 220
|
|
||||||
ANCE 221
|
|
||||||
▁TIME 222
|
|
||||||
▁WI 223
|
|
||||||
▁YE 224
|
|
||||||
AGE 225
|
|
||||||
▁NOW 226
|
|
||||||
TI 227
|
|
||||||
FF 228
|
|
||||||
ABLE 229
|
|
||||||
▁VERY 230
|
|
||||||
▁LIKE 231
|
|
||||||
AM 232
|
|
||||||
HI 233
|
|
||||||
Z 234
|
|
||||||
▁OTHER 235
|
|
||||||
▁THAN 236
|
|
||||||
▁LITTLE 237
|
|
||||||
▁DID 238
|
|
||||||
▁LOOK 239
|
|
||||||
TY 240
|
|
||||||
ERS 241
|
|
||||||
▁CAN 242
|
|
||||||
▁CHA 243
|
|
||||||
▁AR 244
|
|
||||||
X 245
|
|
||||||
FUL 246
|
|
||||||
UGH 247
|
|
||||||
▁BA 248
|
|
||||||
▁DAY 249
|
|
||||||
▁ABOUT 250
|
|
||||||
TEN 251
|
|
||||||
IM 252
|
|
||||||
▁ANY 253
|
|
||||||
▁PRE 254
|
|
||||||
▁OVER 255
|
|
||||||
IES 256
|
|
||||||
NESS 257
|
|
||||||
ME 258
|
|
||||||
BLE 259
|
|
||||||
▁M 260
|
|
||||||
ROW 261
|
|
||||||
▁HAS 262
|
|
||||||
▁GREAT 263
|
|
||||||
▁VI 264
|
|
||||||
TA 265
|
|
||||||
▁AFTER 266
|
|
||||||
PER 267
|
|
||||||
▁AGAIN 268
|
|
||||||
HO 269
|
|
||||||
SH 270
|
|
||||||
▁UPON 271
|
|
||||||
▁DI 272
|
|
||||||
▁HAND 273
|
|
||||||
▁COM 274
|
|
||||||
IST 275
|
|
||||||
TURE 276
|
|
||||||
▁STA 277
|
|
||||||
▁THEN 278
|
|
||||||
▁SHOULD 279
|
|
||||||
▁GA 280
|
|
||||||
OUS 281
|
|
||||||
OUR 282
|
|
||||||
▁WELL 283
|
|
||||||
▁ONLY 284
|
|
||||||
MAN 285
|
|
||||||
▁GOOD 286
|
|
||||||
▁TWO 287
|
|
||||||
▁MAR 288
|
|
||||||
▁SAY 289
|
|
||||||
▁HU 290
|
|
||||||
TING 291
|
|
||||||
▁OUR 292
|
|
||||||
RESS 293
|
|
||||||
▁DOWN 294
|
|
||||||
IOUS 295
|
|
||||||
▁BEFORE 296
|
|
||||||
▁DA 297
|
|
||||||
▁NA 298
|
|
||||||
QUI 299
|
|
||||||
▁MADE 300
|
|
||||||
▁EVERY 301
|
|
||||||
▁OLD 302
|
|
||||||
▁EVEN 303
|
|
||||||
IG 304
|
|
||||||
▁COME 305
|
|
||||||
▁GRA 306
|
|
||||||
▁RI 307
|
|
||||||
▁LONG 308
|
|
||||||
OT 309
|
|
||||||
SIDE 310
|
|
||||||
WARD 311
|
|
||||||
▁FO 312
|
|
||||||
▁WHERE 313
|
|
||||||
MO 314
|
|
||||||
LESS 315
|
|
||||||
▁SC 316
|
|
||||||
▁MUST 317
|
|
||||||
▁NEVER 318
|
|
||||||
▁HOW 319
|
|
||||||
▁CAME 320
|
|
||||||
▁SUCH 321
|
|
||||||
▁RU 322
|
|
||||||
▁TAKE 323
|
|
||||||
▁WO 324
|
|
||||||
▁CAR 325
|
|
||||||
UM 326
|
|
||||||
AK 327
|
|
||||||
▁THINK 328
|
|
||||||
▁MUCH 329
|
|
||||||
▁MISTER 330
|
|
||||||
▁MAY 331
|
|
||||||
▁JO 332
|
|
||||||
▁WAY 333
|
|
||||||
▁COMP 334
|
|
||||||
▁THOUGHT 335
|
|
||||||
▁STO 336
|
|
||||||
▁MEN 337
|
|
||||||
▁BACK 338
|
|
||||||
▁DON 339
|
|
||||||
J 340
|
|
||||||
▁LET 341
|
|
||||||
▁TRA 342
|
|
||||||
▁FIRST 343
|
|
||||||
▁JUST 344
|
|
||||||
▁VA 345
|
|
||||||
▁OWN 346
|
|
||||||
▁PLA 347
|
|
||||||
▁MAKE 348
|
|
||||||
ATED 349
|
|
||||||
▁HIMSELF 350
|
|
||||||
▁WENT 351
|
|
||||||
▁PI 352
|
|
||||||
GG 353
|
|
||||||
RING 354
|
|
||||||
▁DU 355
|
|
||||||
▁MIGHT 356
|
|
||||||
▁PART 357
|
|
||||||
▁GIVE 358
|
|
||||||
▁IMP 359
|
|
||||||
▁BU 360
|
|
||||||
▁PER 361
|
|
||||||
▁PLACE 362
|
|
||||||
▁HOUSE 363
|
|
||||||
▁THROUGH 364
|
|
||||||
IAN 365
|
|
||||||
▁SW 366
|
|
||||||
▁UNDER 367
|
|
||||||
QUE 368
|
|
||||||
▁AWAY 369
|
|
||||||
▁LOVE 370
|
|
||||||
QUA 371
|
|
||||||
▁LIFE 372
|
|
||||||
▁GET 373
|
|
||||||
▁WITHOUT 374
|
|
||||||
▁PASS 375
|
|
||||||
▁TURN 376
|
|
||||||
IGN 377
|
|
||||||
▁HEAD 378
|
|
||||||
▁MOST 379
|
|
||||||
▁THOSE 380
|
|
||||||
▁SHALL 381
|
|
||||||
▁EYES 382
|
|
||||||
▁COL 383
|
|
||||||
▁STILL 384
|
|
||||||
▁NIGHT 385
|
|
||||||
▁NOTHING 386
|
|
||||||
ITION 387
|
|
||||||
HA 388
|
|
||||||
▁TELL 389
|
|
||||||
▁WORK 390
|
|
||||||
▁LAST 391
|
|
||||||
▁NEW 392
|
|
||||||
▁FACE 393
|
|
||||||
▁HI 394
|
|
||||||
▁WORD 395
|
|
||||||
▁FOUND 396
|
|
||||||
▁COUNT 397
|
|
||||||
▁OB 398
|
|
||||||
▁WHILE 399
|
|
||||||
▁SHA 400
|
|
||||||
▁MEAN 401
|
|
||||||
▁SAW 402
|
|
||||||
▁PEOPLE 403
|
|
||||||
▁FRIEND 404
|
|
||||||
▁THREE 405
|
|
||||||
▁ROOM 406
|
|
||||||
▁SAME 407
|
|
||||||
▁THOUGH 408
|
|
||||||
▁RIGHT 409
|
|
||||||
▁CHILD 410
|
|
||||||
▁FATHER 411
|
|
||||||
▁ANOTHER 412
|
|
||||||
▁HEART 413
|
|
||||||
▁WANT 414
|
|
||||||
▁TOOK 415
|
|
||||||
OOK 416
|
|
||||||
▁LIGHT 417
|
|
||||||
▁MISSUS 418
|
|
||||||
▁OPEN 419
|
|
||||||
▁JU 420
|
|
||||||
▁ASKED 421
|
|
||||||
PORT 422
|
|
||||||
▁LEFT 423
|
|
||||||
▁JA 424
|
|
||||||
▁WORLD 425
|
|
||||||
▁HOME 426
|
|
||||||
▁WHY 427
|
|
||||||
▁ALWAYS 428
|
|
||||||
▁ANSWER 429
|
|
||||||
▁SEEMED 430
|
|
||||||
▁SOMETHING 431
|
|
||||||
▁GIRL 432
|
|
||||||
▁BECAUSE 433
|
|
||||||
▁NAME 434
|
|
||||||
▁TOLD 435
|
|
||||||
▁NI 436
|
|
||||||
▁HIGH 437
|
|
||||||
IZE 438
|
|
||||||
▁WOMAN 439
|
|
||||||
▁FOLLOW 440
|
|
||||||
▁RETURN 441
|
|
||||||
▁KNEW 442
|
|
||||||
▁EACH 443
|
|
||||||
▁KIND 444
|
|
||||||
▁JE 445
|
|
||||||
▁ACT 446
|
|
||||||
▁LU 447
|
|
||||||
▁CERTAIN 448
|
|
||||||
▁YEARS 449
|
|
||||||
▁QUITE 450
|
|
||||||
▁APPEAR 451
|
|
||||||
▁BETTER 452
|
|
||||||
▁HALF 453
|
|
||||||
▁PRESENT 454
|
|
||||||
▁PRINCE 455
|
|
||||||
SHIP 456
|
|
||||||
▁ALSO 457
|
|
||||||
▁BEGAN 458
|
|
||||||
▁HAVING 459
|
|
||||||
▁ENOUGH 460
|
|
||||||
▁PERSON 461
|
|
||||||
▁LADY 462
|
|
||||||
▁WHITE 463
|
|
||||||
▁COURSE 464
|
|
||||||
▁VOICE 465
|
|
||||||
▁SPEAK 466
|
|
||||||
▁POWER 467
|
|
||||||
▁MORNING 468
|
|
||||||
▁BETWEEN 469
|
|
||||||
▁AMONG 470
|
|
||||||
▁KEEP 471
|
|
||||||
▁WALK 472
|
|
||||||
▁MATTER 473
|
|
||||||
▁TEA 474
|
|
||||||
▁BELIEVE 475
|
|
||||||
▁SMALL 476
|
|
||||||
▁TALK 477
|
|
||||||
▁FELT 478
|
|
||||||
▁HORSE 479
|
|
||||||
▁MYSELF 480
|
|
||||||
▁SIX 481
|
|
||||||
▁HOWEVER 482
|
|
||||||
▁FULL 483
|
|
||||||
▁HERSELF 484
|
|
||||||
▁POINT 485
|
|
||||||
▁STOOD 486
|
|
||||||
▁HUNDRED 487
|
|
||||||
▁ALMOST 488
|
|
||||||
▁SINCE 489
|
|
||||||
▁LARGE 490
|
|
||||||
▁LEAVE 491
|
|
||||||
▁PERHAPS 492
|
|
||||||
▁DARK 493
|
|
||||||
▁SUDDEN 494
|
|
||||||
▁REPLIED 495
|
|
||||||
▁ANYTHING 496
|
|
||||||
▁WONDER 497
|
|
||||||
▁UNTIL 498
|
|
||||||
Q 499
|
|
||||||
#0 500
|
|
||||||
#1 501
|
|
||||||
@@ -15,7 +15,7 @@ class SherpaSttService {
|
|||||||
|
|
||||||
bool get isReady => _isInitialized && _recognizer != null;
|
bool get isReady => _isInitialized && _recognizer != null;
|
||||||
|
|
||||||
/// Initializes Sherpa-ONNX bindings and unpacks bundled model assets to local disk if needed.
|
/// Initializes SenseVoice-Small ONNX bindings and unpacks bundled model assets to local disk if needed.
|
||||||
Future<bool> initialize({String? nativeLibDir}) async {
|
Future<bool> initialize({String? nativeLibDir}) async {
|
||||||
if (_isInitialized) return true;
|
if (_isInitialized) return true;
|
||||||
if (_isInitializing) return false;
|
if (_isInitializing) return false;
|
||||||
@@ -29,32 +29,30 @@ class SherpaSttService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final docDir = await getApplicationDocumentsDirectory();
|
final docDir = await getApplicationDocumentsDirectory();
|
||||||
final modelDir = Directory('${docDir.path}/sherpa_models');
|
final modelDir = Directory('${docDir.path}/sense_voice_models');
|
||||||
if (!await modelDir.exists()) {
|
if (!await modelDir.exists()) {
|
||||||
await modelDir.create(recursive: true);
|
await modelDir.create(recursive: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final modelFiles = [
|
final modelFiles = [
|
||||||
'encoder-epoch-99-avg-1.int8.onnx',
|
'model.int8.onnx',
|
||||||
'decoder-epoch-99-avg-1.int8.onnx',
|
|
||||||
'joiner-epoch-99-avg-1.int8.onnx',
|
|
||||||
'tokens.txt',
|
'tokens.txt',
|
||||||
];
|
];
|
||||||
|
|
||||||
for (final filename in modelFiles) {
|
for (final filename in modelFiles) {
|
||||||
final targetFile = File('${modelDir.path}/$filename');
|
final targetFile = File('${modelDir.path}/$filename');
|
||||||
if (!await targetFile.exists() || (await targetFile.length()) == 0) {
|
if (!await targetFile.exists() || (await targetFile.length()) == 0) {
|
||||||
final ByteData data = await rootBundle.load('assets/models/sherpa/$filename');
|
final ByteData data = await rootBundle.load('assets/models/sense_voice/$filename');
|
||||||
final Uint8List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
|
final Uint8List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
|
||||||
await targetFile.writeAsBytes(bytes, flush: true);
|
await targetFile.writeAsBytes(bytes, flush: true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final modelConfig = sherpa_onnx.OfflineModelConfig(
|
final modelConfig = sherpa_onnx.OfflineModelConfig(
|
||||||
transducer: sherpa_onnx.OfflineTransducerModelConfig(
|
senseVoice: sherpa_onnx.OfflineSenseVoiceModelConfig(
|
||||||
encoder: '${modelDir.path}/encoder-epoch-99-avg-1.int8.onnx',
|
model: '${modelDir.path}/model.int8.onnx',
|
||||||
decoder: '${modelDir.path}/decoder-epoch-99-avg-1.int8.onnx',
|
language: 'auto',
|
||||||
joiner: '${modelDir.path}/joiner-epoch-99-avg-1.int8.onnx',
|
useInverseTextNormalization: true,
|
||||||
),
|
),
|
||||||
tokens: '${modelDir.path}/tokens.txt',
|
tokens: '${modelDir.path}/tokens.txt',
|
||||||
numThreads: 2,
|
numThreads: 2,
|
||||||
@@ -69,17 +67,17 @@ class SherpaSttService {
|
|||||||
_recognizer = sherpa_onnx.OfflineRecognizer(recognizerConfig);
|
_recognizer = sherpa_onnx.OfflineRecognizer(recognizerConfig);
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
_isInitializing = false;
|
_isInitializing = false;
|
||||||
debugPrint('[SherpaSttService] Local ONNX ASR engine initialized successfully.');
|
debugPrint('[SherpaSttService] SenseVoice-Small ONNX ASR engine initialized successfully.');
|
||||||
return true;
|
return true;
|
||||||
} catch (e, stack) {
|
} catch (e, stack) {
|
||||||
debugPrint('[SherpaSttService] Failed to initialize local ASR engine: $e\n$stack');
|
debugPrint('[SherpaSttService] Failed to initialize SenseVoice ASR engine: $e\n$stack');
|
||||||
_isInitializing = false;
|
_isInitializing = false;
|
||||||
_isInitialized = false;
|
_isInitialized = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transcribes a local 16kHz mono WAV audio file.
|
/// Transcribes a local 16kHz mono WAV audio file using SenseVoice-Small.
|
||||||
Future<String?> transcribeWav(String wavPath) async {
|
Future<String?> transcribeWav(String wavPath) async {
|
||||||
try {
|
try {
|
||||||
if (!_isInitialized) {
|
if (!_isInitialized) {
|
||||||
@@ -115,14 +113,19 @@ class SherpaSttService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cleans and formats raw recognized text into natural English casing.
|
/// Cleans and formats raw recognized SenseVoice text (strips emotion/event tags, normalizes casing).
|
||||||
String _cleanText(String text) {
|
String _cleanText(String text) {
|
||||||
if (text.isEmpty) return text;
|
if (text.isEmpty) return text;
|
||||||
// Lowercase first to normalize uppercase model output
|
// Strip SenseVoice special tags like <|zh|>, <|en|>, <|NEUTRAL|>, <|HAPPY|>, <|Speech|>, <|withitn|>, <|woitn|>, etc.
|
||||||
final lower = text.toLowerCase().trim();
|
var cleaned = text.replaceAll(RegExp(r'<\|[a-zA-Z0-9_\-\s]+\|>'), '').trim();
|
||||||
if (lower.isEmpty) return lower;
|
if (cleaned.isEmpty) return cleaned;
|
||||||
// Capitalize the first letter
|
// Normalize consecutive spaces
|
||||||
return lower[0].toUpperCase() + lower.substring(1);
|
cleaned = cleaned.replaceAll(RegExp(r'\s+'), ' ').trim();
|
||||||
|
// Capitalize first character if it's a letter
|
||||||
|
if (cleaned.isNotEmpty && cleaned[0].toLowerCase() != cleaned[0].toUpperCase()) {
|
||||||
|
cleaned = cleaned[0].toUpperCase() + cleaned.substring(1);
|
||||||
|
}
|
||||||
|
return cleaned;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ class VoiceService {
|
|||||||
encoder: AudioEncoder.wav,
|
encoder: AudioEncoder.wav,
|
||||||
sampleRate: 16000,
|
sampleRate: 16000,
|
||||||
numChannels: 1,
|
numChannels: 1,
|
||||||
|
noiseSuppress: true,
|
||||||
|
echoCancel: true,
|
||||||
|
autoGain: true,
|
||||||
),
|
),
|
||||||
path: '${recordings.path}/practice_$timestamp.wav',
|
path: '${recordings.path}/practice_$timestamp.wav',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -33,4 +33,4 @@ flutter:
|
|||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- assets/config/
|
- assets/config/
|
||||||
- assets/models/sherpa/
|
- assets/models/sense_voice/
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:kouyu_english/core/sherpa_stt_service.dart';
|
import 'package:kouyu_english/core/sherpa_stt_service.dart';
|
||||||
import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx;
|
import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx;
|
||||||
@@ -7,19 +6,19 @@ import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx;
|
|||||||
void main() {
|
void main() {
|
||||||
TestWidgetsFlutterBinding.ensureInitialized();
|
TestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
test('SherpaSttService transcribes WAV audio file accurately', () async {
|
test('SenseVoice-Small ONNX transcribes WAV audio file accurately', () async {
|
||||||
const macosDir = '/Users/shen/.pub-cache/hosted/pub.dev/sherpa_onnx_macos-1.13.8/macos';
|
const macosDir = '/Users/shen/.pub-cache/hosted/pub.dev/sherpa_onnx_macos-1.13.8/macos';
|
||||||
|
|
||||||
// Test direct Sherpa ASR initialization and decoding with bundled test audio
|
// Test direct Sherpa ASR initialization and decoding with SenseVoice
|
||||||
sherpa_onnx.initBindings(macosDir);
|
sherpa_onnx.initBindings(macosDir);
|
||||||
|
|
||||||
final modelConfig = sherpa_onnx.OfflineModelConfig(
|
final modelConfig = sherpa_onnx.OfflineModelConfig(
|
||||||
transducer: const sherpa_onnx.OfflineTransducerModelConfig(
|
senseVoice: const sherpa_onnx.OfflineSenseVoiceModelConfig(
|
||||||
encoder: 'assets/models/sherpa/encoder-epoch-99-avg-1.int8.onnx',
|
model: 'assets/models/sense_voice/model.int8.onnx',
|
||||||
decoder: 'assets/models/sherpa/decoder-epoch-99-avg-1.int8.onnx',
|
language: 'auto',
|
||||||
joiner: 'assets/models/sherpa/joiner-epoch-99-avg-1.int8.onnx',
|
useInverseTextNormalization: true,
|
||||||
),
|
),
|
||||||
tokens: 'assets/models/sherpa/tokens.txt',
|
tokens: 'assets/models/sense_voice/tokens.txt',
|
||||||
numThreads: 2,
|
numThreads: 2,
|
||||||
debug: false,
|
debug: false,
|
||||||
);
|
);
|
||||||
@@ -40,8 +39,8 @@ void main() {
|
|||||||
stream.acceptWaveform(samples: wave.samples, sampleRate: wave.sampleRate);
|
stream.acceptWaveform(samples: wave.samples, sampleRate: wave.sampleRate);
|
||||||
recognizer.decode(stream);
|
recognizer.decode(stream);
|
||||||
final result = recognizer.getResult(stream);
|
final result = recognizer.getResult(stream);
|
||||||
print("Transcribed result: ${result.text}");
|
print("SenseVoice transcribed result: ${result.text}");
|
||||||
expect(result.text.contains("NIGHTFALL"), isTrue);
|
expect(result.text.toLowerCase().contains("nightfall"), isTrue);
|
||||||
stream.free();
|
stream.free();
|
||||||
}
|
}
|
||||||
recognizer.free();
|
recognizer.free();
|
||||||
|
|||||||
Reference in New Issue
Block a user