@tychenjiajun/pi-voice 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -2
- package/catalog/catalog.json +1501 -0
- package/catalog/recommendations.json +67 -27
- package/models/README.md +25 -0
- package/models/silero-vad-v6.2-F32.gguf +0 -0
- package/package.json +8 -6
- package/src/audio-constants.ts +2 -0
- package/src/audio.ts +2 -5
- package/src/catalog.ts +6 -2
- package/src/chinese.ts +17 -6
- package/src/chunking.ts +319 -0
- package/src/dictation-controller.ts +61 -18
- package/src/file-audio.ts +2 -2
- package/src/file-transcription.ts +6 -3
- package/src/language-detection-policy.ts +127 -0
- package/src/languages.ts +4 -3
- package/src/model-activation.ts +50 -4
- package/src/model-cells.ts +28 -6
- package/src/model-picker.ts +29 -12
- package/src/model-selection-controller.ts +14 -9
- package/src/models.ts +15 -1
- package/src/onboarding.ts +13 -1
- package/src/pcm-chunker.ts +14 -4
- package/src/recommendation-picker.ts +9 -7
- package/src/recommendations.ts +4 -2
- package/src/runtime.ts +9 -1
- package/src/settings-menu.ts +49 -11
- package/src/settings.ts +35 -3
- package/src/transcription-service.ts +205 -37
- package/src/transcription.ts +72 -24
- package/src/try-it.ts +11 -2
- package/src/vad.ts +301 -0
- package/src/catalog.generated.ts +0 -1305
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"accuracy": {
|
|
16
16
|
"en": {"error": 3.99, "ciLower": 3.6}
|
|
17
17
|
},
|
|
18
|
-
"performance": {"accelerated":
|
|
18
|
+
"performance": {"accelerated": 25.28, "cpu": 13.955}
|
|
19
19
|
},
|
|
20
20
|
"nemotron-3.5-asr-streaming-0.6b": {
|
|
21
21
|
"accuracy": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"vi": {"error": 13.96, "ciLower": 13.09},
|
|
49
49
|
"zh": {"error": 18.87, "ciLower": 17.82}
|
|
50
50
|
},
|
|
51
|
-
"performance": {"accelerated":
|
|
51
|
+
"performance": {"accelerated": 17.135, "cpu": 10.59}
|
|
52
52
|
},
|
|
53
53
|
"canary-180m-flash": {
|
|
54
54
|
"accuracy": {
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"es": {"error": 6.54, "ciLower": 5.92},
|
|
58
58
|
"fr": {"error": 8.53, "ciLower": 7.78}
|
|
59
59
|
},
|
|
60
|
-
"performance": {"accelerated":
|
|
60
|
+
"performance": {"accelerated": 33.085, "cpu": 21.73}
|
|
61
61
|
},
|
|
62
62
|
"cohere-transcribe-03-2026": {
|
|
63
63
|
"accuracy": {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"vi": {"error": 7.39, "ciLower": 6.8},
|
|
77
77
|
"zh": {"error": 11.18, "ciLower": 10.19}
|
|
78
78
|
},
|
|
79
|
-
"performance": {"accelerated": 8, "cpu":
|
|
79
|
+
"performance": {"accelerated": 8.095, "cpu": 4.31}
|
|
80
80
|
},
|
|
81
81
|
"whisper-medium": {
|
|
82
82
|
"accuracy": {
|
|
@@ -114,6 +114,7 @@
|
|
|
114
114
|
"is": {"error": 51.6, "ciLower": 47.14},
|
|
115
115
|
"it": {"error": 4.17, "ciLower": 3.75},
|
|
116
116
|
"ja": {"error": 7.35, "ciLower": 6.79},
|
|
117
|
+
"jv": {"error": 73.01, "ciLower": 71.38},
|
|
117
118
|
"ka": {"error": 128.01, "ciLower": 123.78},
|
|
118
119
|
"kk": {"error": 53.09, "ciLower": 51.93},
|
|
119
120
|
"km": {"error": 108.92, "ciLower": 106.01},
|
|
@@ -162,7 +163,7 @@
|
|
|
162
163
|
"yo": {"error": 109, "ciLower": 106.23},
|
|
163
164
|
"zh": {"error": 13.13, "ciLower": 11.97}
|
|
164
165
|
},
|
|
165
|
-
"performance": {"accelerated": 4.
|
|
166
|
+
"performance": {"accelerated": 4.085, "cpu": 1.925}
|
|
166
167
|
},
|
|
167
168
|
"Voxtral-Mini-4B-Realtime-2602": {
|
|
168
169
|
"accuracy": {
|
|
@@ -180,7 +181,37 @@
|
|
|
180
181
|
"ru": {"error": 5.41, "ciLower": 4.95},
|
|
181
182
|
"zh": {"error": 10.41, "ciLower": 9.32}
|
|
182
183
|
},
|
|
183
|
-
"performance": {"accelerated": 0.
|
|
184
|
+
"performance": {"accelerated": 0.76, "cpu": 0.585}
|
|
185
|
+
},
|
|
186
|
+
"parakeet-ultra": {
|
|
187
|
+
"accuracy": {
|
|
188
|
+
"bg": {"error": 11.04, "ciLower": 10.32},
|
|
189
|
+
"cs": {"error": 11.04, "ciLower": 10.21},
|
|
190
|
+
"da": {"error": 15.98, "ciLower": 15.28},
|
|
191
|
+
"de": {"error": 4.58, "ciLower": 4.17},
|
|
192
|
+
"el": {"error": 32.25, "ciLower": 31.18},
|
|
193
|
+
"en": {"error": 4.26, "ciLower": 3.84},
|
|
194
|
+
"es": {"error": 3.06, "ciLower": 2.75},
|
|
195
|
+
"et": {"error": 14.44, "ciLower": 13.68},
|
|
196
|
+
"fi": {"error": 11.14, "ciLower": 10.44},
|
|
197
|
+
"fr": {"error": 4.66, "ciLower": 4.21},
|
|
198
|
+
"hr": {"error": 11.3, "ciLower": 10.55},
|
|
199
|
+
"hu": {"error": 13.09, "ciLower": 12.41},
|
|
200
|
+
"it": {"error": 2.34, "ciLower": 2.07},
|
|
201
|
+
"lt": {"error": 17.06, "ciLower": 16.38},
|
|
202
|
+
"lv": {"error": 18.04, "ciLower": 17.22},
|
|
203
|
+
"mt": {"error": 17.01, "ciLower": 16.28},
|
|
204
|
+
"nl": {"error": 6.7, "ciLower": 5.99},
|
|
205
|
+
"pl": {"error": 6.16, "ciLower": 5.64},
|
|
206
|
+
"pt": {"error": 4.16, "ciLower": 3.71},
|
|
207
|
+
"ro": {"error": 10.12, "ciLower": 9.48},
|
|
208
|
+
"ru": {"error": 5.63, "ciLower": 5.2},
|
|
209
|
+
"sk": {"error": 7.83, "ciLower": 7.17},
|
|
210
|
+
"sl": {"error": 18.98, "ciLower": 18.08},
|
|
211
|
+
"sv": {"error": 12.83, "ciLower": 12.09},
|
|
212
|
+
"uk": {"error": 5.71, "ciLower": 5.2}
|
|
213
|
+
},
|
|
214
|
+
"performance": {"accelerated": 23, "cpu": 13.29}
|
|
184
215
|
},
|
|
185
216
|
"parakeet-tdt-0.6b-v3": {
|
|
186
217
|
"accuracy": {
|
|
@@ -210,13 +241,13 @@
|
|
|
210
241
|
"sv": {"error": 15.25, "ciLower": 14.38},
|
|
211
242
|
"uk": {"error": 6.84, "ciLower": 6.25}
|
|
212
243
|
},
|
|
213
|
-
"performance": {"accelerated":
|
|
244
|
+
"performance": {"accelerated": 25.065, "cpu": 13.655}
|
|
214
245
|
},
|
|
215
246
|
"parakeet-tdt-0.6b-v2": {
|
|
216
247
|
"accuracy": {
|
|
217
248
|
"en": {"error": 4.11, "ciLower": 3.71}
|
|
218
249
|
},
|
|
219
|
-
"performance": {"accelerated":
|
|
250
|
+
"performance": {"accelerated": 27.435, "cpu": 14.27}
|
|
220
251
|
},
|
|
221
252
|
"Qwen3-ASR-0.6B": {
|
|
222
253
|
"accuracy": {
|
|
@@ -251,7 +282,7 @@
|
|
|
251
282
|
"yue": {"error": 7.91, "ciLower": 7.28},
|
|
252
283
|
"zh": {"error": 7.57, "ciLower": 6.7}
|
|
253
284
|
},
|
|
254
|
-
"performance": {"accelerated":
|
|
285
|
+
"performance": {"accelerated": 9.705, "cpu": 5.295}
|
|
255
286
|
},
|
|
256
287
|
"Fun-ASR-MLT-Nano-2512": {
|
|
257
288
|
"accuracy": {
|
|
@@ -287,7 +318,7 @@
|
|
|
287
318
|
"yue": {"error": 12.72, "ciLower": 11.82},
|
|
288
319
|
"zh": {"error": 8.64, "ciLower": 7.7}
|
|
289
320
|
},
|
|
290
|
-
"performance": {"accelerated":
|
|
321
|
+
"performance": {"accelerated": 8.835, "cpu": 5.47}
|
|
291
322
|
},
|
|
292
323
|
"canary-1b-v2": {
|
|
293
324
|
"accuracy": {
|
|
@@ -317,20 +348,20 @@
|
|
|
317
348
|
"sv": {"error": 9.74, "ciLower": 9.06},
|
|
318
349
|
"uk": {"error": 10.58, "ciLower": 9.87}
|
|
319
350
|
},
|
|
320
|
-
"performance": {"accelerated": 13
|
|
351
|
+
"performance": {"accelerated": 14.13, "cpu": 8.325}
|
|
321
352
|
},
|
|
322
353
|
"canary-qwen-2.5b": {
|
|
323
354
|
"accuracy": {
|
|
324
355
|
"en": {"error": 3.58, "ciLower": 3.19}
|
|
325
356
|
},
|
|
326
|
-
"performance": {"accelerated":
|
|
357
|
+
"performance": {"accelerated": 3.975, "cpu": 2.51}
|
|
327
358
|
},
|
|
328
359
|
"cohere-transcribe-arabic-07-2026": {
|
|
329
360
|
"accuracy": {
|
|
330
361
|
"ar": {"error": 11.06, "ciLower": 9.62},
|
|
331
362
|
"en": {"error": 4.88, "ciLower": 4.25}
|
|
332
363
|
},
|
|
333
|
-
"performance": {"accelerated": 8, "cpu":
|
|
364
|
+
"performance": {"accelerated": 8.305, "cpu": 4.31}
|
|
334
365
|
},
|
|
335
366
|
"Fun-ASR-Nano-2512": {
|
|
336
367
|
"accuracy": {
|
|
@@ -338,19 +369,25 @@
|
|
|
338
369
|
"ja": {"error": 8.5, "ciLower": 7.86},
|
|
339
370
|
"zh": {"error": 8.59, "ciLower": 7.59}
|
|
340
371
|
},
|
|
341
|
-
"performance": {"accelerated": 10.
|
|
372
|
+
"performance": {"accelerated": 10.73, "cpu": 7.945}
|
|
342
373
|
},
|
|
343
374
|
"gigaam-v3-e2e-ctc": {
|
|
344
375
|
"accuracy": {
|
|
345
376
|
"ru": {"error": 5.53, "ciLower": 5.01}
|
|
346
377
|
},
|
|
347
|
-
"performance": {"accelerated":
|
|
378
|
+
"performance": {"accelerated": 35.375, "cpu": 11.455}
|
|
348
379
|
},
|
|
349
380
|
"gigaam-v3-e2e-rnnt": {
|
|
350
381
|
"accuracy": {
|
|
351
382
|
"ru": {"error": 5.35, "ciLower": 4.85}
|
|
352
383
|
},
|
|
353
|
-
"performance": {"accelerated":
|
|
384
|
+
"performance": {"accelerated": 15.02, "cpu": 7.875}
|
|
385
|
+
},
|
|
386
|
+
"granite-speech-5.0-470m-turboctc": {
|
|
387
|
+
"accuracy": {
|
|
388
|
+
"en": {"error": 4.61, "ciLower": 4.19}
|
|
389
|
+
},
|
|
390
|
+
"performance": {"accelerated": 22.865, "cpu": 17.24}
|
|
354
391
|
},
|
|
355
392
|
"granite-speech-4.1-2b": {
|
|
356
393
|
"accuracy": {
|
|
@@ -361,25 +398,25 @@
|
|
|
361
398
|
"ja": {"error": 6.3, "ciLower": 5.75},
|
|
362
399
|
"pt": {"error": 9.8, "ciLower": 9.08}
|
|
363
400
|
},
|
|
364
|
-
"performance": {"accelerated":
|
|
401
|
+
"performance": {"accelerated": 4.615, "cpu": 2.775}
|
|
365
402
|
},
|
|
366
403
|
"medasr": {
|
|
367
404
|
"accuracy": {
|
|
368
405
|
"en": {"error": 37.48, "ciLower": 35.83}
|
|
369
406
|
},
|
|
370
|
-
"performance": {"accelerated": 71, "cpu":
|
|
407
|
+
"performance": {"accelerated": 71.26, "cpu": 25.865}
|
|
371
408
|
},
|
|
372
409
|
"parakeet-tdt_ctc-110m": {
|
|
373
410
|
"accuracy": {
|
|
374
411
|
"en": {"error": 6.11, "ciLower": 5.59}
|
|
375
412
|
},
|
|
376
|
-
"performance": {"accelerated":
|
|
413
|
+
"performance": {"accelerated": 76.455, "cpu": 50.03}
|
|
377
414
|
},
|
|
378
415
|
"multitalker-parakeet-streaming-0.6b-v1": {
|
|
379
416
|
"accuracy": {
|
|
380
417
|
"en": {"error": 6.52, "ciLower": 5.95}
|
|
381
418
|
},
|
|
382
|
-
"performance": {"accelerated":
|
|
419
|
+
"performance": {"accelerated": 26.345, "cpu": 13.415}
|
|
383
420
|
},
|
|
384
421
|
"Qwen3-ASR-1.7B": {
|
|
385
422
|
"accuracy": {
|
|
@@ -414,7 +451,7 @@
|
|
|
414
451
|
"yue": {"error": 6.13, "ciLower": 5.55},
|
|
415
452
|
"zh": {"error": 7.14, "ciLower": 6.26}
|
|
416
453
|
},
|
|
417
|
-
"performance": {"accelerated":
|
|
454
|
+
"performance": {"accelerated": 4.085, "cpu": 2.47}
|
|
418
455
|
},
|
|
419
456
|
"SenseVoiceSmall": {
|
|
420
457
|
"accuracy": {
|
|
@@ -424,7 +461,7 @@
|
|
|
424
461
|
"yue": {"error": 37.44, "ciLower": 36.69},
|
|
425
462
|
"zh": {"error": 10.12, "ciLower": 9.16}
|
|
426
463
|
},
|
|
427
|
-
"performance": {"accelerated":
|
|
464
|
+
"performance": {"accelerated": 27.69, "cpu": 19.735}
|
|
428
465
|
},
|
|
429
466
|
"Voxtral-Mini-3B-2507": {
|
|
430
467
|
"accuracy": {
|
|
@@ -437,7 +474,7 @@
|
|
|
437
474
|
"nl": {"error": 6.57, "ciLower": 5.84},
|
|
438
475
|
"pt": {"error": 3.84, "ciLower": 3.44}
|
|
439
476
|
},
|
|
440
|
-
"performance": {"accelerated": 1.
|
|
477
|
+
"performance": {"accelerated": 1.085, "cpu": 0.56}
|
|
441
478
|
},
|
|
442
479
|
"whisper-small": {
|
|
443
480
|
"accuracy": {
|
|
@@ -475,6 +512,7 @@
|
|
|
475
512
|
"is": {"error": 74.54, "ciLower": 69.87},
|
|
476
513
|
"it": {"error": 7.97, "ciLower": 7.4},
|
|
477
514
|
"ja": {"error": 12.81, "ciLower": 12.05},
|
|
515
|
+
"jv": {"error": 94.42, "ciLower": 91.78},
|
|
478
516
|
"ka": {"error": 130.64, "ciLower": 125.94},
|
|
479
517
|
"kk": {"error": 73.54, "ciLower": 72.52},
|
|
480
518
|
"km": {"error": 116.96, "ciLower": 113.31},
|
|
@@ -523,7 +561,7 @@
|
|
|
523
561
|
"yo": {"error": 118.5, "ciLower": 114.83},
|
|
524
562
|
"zh": {"error": 23.06, "ciLower": 21.79}
|
|
525
563
|
},
|
|
526
|
-
"performance": {"accelerated":
|
|
564
|
+
"performance": {"accelerated": 11.695, "cpu": 5.86}
|
|
527
565
|
},
|
|
528
566
|
"whisper-large-v3-turbo": {
|
|
529
567
|
"accuracy": {
|
|
@@ -561,6 +599,7 @@
|
|
|
561
599
|
"is": {"error": 21.39, "ciLower": 17.91},
|
|
562
600
|
"it": {"error": 2.77, "ciLower": 2.45},
|
|
563
601
|
"ja": {"error": 4.82, "ciLower": 4.4},
|
|
602
|
+
"jv": {"error": 53.8, "ciLower": 52.56},
|
|
564
603
|
"ka": {"error": 109.21, "ciLower": 107.78},
|
|
565
604
|
"kk": {"error": 21.27, "ciLower": 20.15},
|
|
566
605
|
"km": {"error": 95.2, "ciLower": 93.97},
|
|
@@ -610,14 +649,14 @@
|
|
|
610
649
|
"yue": {"error": 34.62, "ciLower": 33.41},
|
|
611
650
|
"zh": {"error": 8.5, "ciLower": 7.65}
|
|
612
651
|
},
|
|
613
|
-
"performance": {"accelerated": 3.
|
|
652
|
+
"performance": {"accelerated": 3.095, "cpu": 1.43}
|
|
614
653
|
},
|
|
615
654
|
"Breeze-ASR-25": {
|
|
616
655
|
"accuracy": {
|
|
617
656
|
"en": {"error": 4.14, "ciLower": 3.7},
|
|
618
657
|
"zh": {"error": 8.1, "ciLower": 7.28}
|
|
619
658
|
},
|
|
620
|
-
"performance": {"accelerated": 2.
|
|
659
|
+
"performance": {"accelerated": 2.02, "cpu": 0.96}
|
|
621
660
|
},
|
|
622
661
|
"whisper-large-v3": {
|
|
623
662
|
"accuracy": {
|
|
@@ -655,6 +694,7 @@
|
|
|
655
694
|
"is": {"error": 31.85, "ciLower": 27.47},
|
|
656
695
|
"it": {"error": 2.54, "ciLower": 2.16},
|
|
657
696
|
"ja": {"error": 4.81, "ciLower": 4.25},
|
|
697
|
+
"jv": {"error": 64.72, "ciLower": 63.4},
|
|
658
698
|
"ka": {"error": 93.97, "ciLower": 93.03},
|
|
659
699
|
"kk": {"error": 33.07, "ciLower": 32.07},
|
|
660
700
|
"km": {"error": 101.09, "ciLower": 99.27},
|
|
@@ -704,7 +744,7 @@
|
|
|
704
744
|
"yue": {"error": 22.06, "ciLower": 20.16},
|
|
705
745
|
"zh": {"error": 7.98, "ciLower": 7.12}
|
|
706
746
|
},
|
|
707
|
-
"performance": {"accelerated":
|
|
747
|
+
"performance": {"accelerated": 1.995, "cpu": 0.97}
|
|
708
748
|
}
|
|
709
749
|
}
|
|
710
750
|
}
|
package/models/README.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Bundled models
|
|
2
|
+
|
|
3
|
+
`silero-vad-v6.2-F32.gguf` is [Silero VAD](https://github.com/snakers4/silero-vad) 6.2 converted to GGUF for transcribe.cpp, from [handy-computer/silero-vad-v6.2-gguf](https://huggingface.co/handy-computer/silero-vad-v6.2-gguf) at revision `97bbd75179f535e4708bccdf61e9278b8b60dfc7` (SHA-256 `0d871a800c420fdd5d1b17a3aea4296d1c39608f0ff4a9295eb76457eb1c88e6`).
|
|
4
|
+
|
|
5
|
+
MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2020-present Silero Team
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tychenjiajun/pi-voice",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Speech-to-text for Pi (local model or OpenAI-compatible remote ASR, compaction-style post-processing)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
"files": [
|
|
16
16
|
"src",
|
|
17
17
|
"index.ts",
|
|
18
|
+
"catalog/catalog.json",
|
|
18
19
|
"catalog/recommendations.json",
|
|
20
|
+
"models/silero-vad-v6.2-F32.gguf",
|
|
21
|
+
"models/README.md",
|
|
19
22
|
"README.md",
|
|
20
23
|
"LICENSE"
|
|
21
24
|
],
|
|
@@ -37,7 +40,6 @@
|
|
|
37
40
|
"check": "tsc --noEmit",
|
|
38
41
|
"test": "npm run check && node scripts/run-tests.mjs",
|
|
39
42
|
"prepublishOnly": "npm test",
|
|
40
|
-
"catalog:generate": "node scripts/generate-catalog.mjs",
|
|
41
43
|
"recommendations:generate": "node scripts/generate-recommendations.mjs",
|
|
42
44
|
"catalog:verify": "node scripts/catalog-metadata.mjs",
|
|
43
45
|
"catalog:update-metadata": "node scripts/catalog-metadata.mjs --write"
|
|
@@ -53,18 +55,18 @@
|
|
|
53
55
|
"typebox": "*"
|
|
54
56
|
},
|
|
55
57
|
"devDependencies": {
|
|
56
|
-
"@earendil-works/pi-coding-agent": "
|
|
57
|
-
"@earendil-works/pi-tui": "^
|
|
58
|
+
"@earendil-works/pi-coding-agent": "1.3.0",
|
|
59
|
+
"@earendil-works/pi-tui": "^1.3.0",
|
|
58
60
|
"@huggingface/gguf": "^0.4.6",
|
|
59
61
|
"@types/node": "22.20.1",
|
|
60
62
|
"typebox": "^1.3.7",
|
|
61
63
|
"typescript": "5.9.3"
|
|
62
64
|
},
|
|
63
65
|
"dependencies": {
|
|
64
|
-
"@handy-computer/recorder": "0.1
|
|
66
|
+
"@handy-computer/recorder": "0.2.1",
|
|
65
67
|
"@huggingface/hub": "2.15.0",
|
|
66
68
|
"openai": "^7.31.0",
|
|
67
69
|
"opencc-js": "^1.4.1",
|
|
68
|
-
"transcribe-cpp": "0.
|
|
70
|
+
"transcribe-cpp": "0.4.0"
|
|
69
71
|
}
|
|
70
72
|
}
|
package/src/audio-constants.ts
CHANGED
package/src/audio.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type Permission,
|
|
8
8
|
type Recording,
|
|
9
9
|
} from "@handy-computer/recorder";
|
|
10
|
-
import { CAPTURE_SAMPLE_RATE } from "./audio-constants.js";
|
|
10
|
+
import { CAPTURE_CHUNK_SAMPLES, CAPTURE_SAMPLE_RATE } from "./audio-constants.js";
|
|
11
11
|
import type { Capture, CaptureSinks } from "./dictation-controller.js";
|
|
12
12
|
import { logLevel, writeLog } from "./log.js";
|
|
13
13
|
import type { MicrophoneSetting } from "./settings.js";
|
|
@@ -24,9 +24,6 @@ if (level) {
|
|
|
24
24
|
);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/** 32 ms chunks: a power of two, so the meter's FFT uses every sample. */
|
|
28
|
-
const FRAMES_PER_CHUNK = 512;
|
|
29
|
-
|
|
30
27
|
export class MicrophoneUnavailableError extends Error {
|
|
31
28
|
constructor(name: string) {
|
|
32
29
|
super(`Selected microphone is unavailable: ${name}. Open /voice-settings and choose another microphone.`);
|
|
@@ -75,7 +72,7 @@ export async function openMicrophone(microphone: MicrophoneSetting, sinks: Captu
|
|
|
75
72
|
device: device?.id,
|
|
76
73
|
sampleRate: CAPTURE_SAMPLE_RATE,
|
|
77
74
|
channels: "mono",
|
|
78
|
-
framesPerChunk:
|
|
75
|
+
framesPerChunk: CAPTURE_CHUNK_SAMPLES,
|
|
79
76
|
onChunk: ({ samples }) => sinks.onAudio(samples),
|
|
80
77
|
onFailure: (error) => sinks.onFailure(error),
|
|
81
78
|
});
|
package/src/catalog.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import catalog from "../catalog/catalog.json" with { type: "json" };
|
|
2
2
|
import { canonicalLanguage, languageIdentity, resolveModelLanguage } from "./languages.js";
|
|
3
3
|
export { canonicalLanguage, languageIdentity, resolveModelLanguage } from "./languages.js";
|
|
4
4
|
|
|
@@ -23,7 +23,11 @@ export type CatalogModel = {
|
|
|
23
23
|
readonly sha256: string;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export const CATALOG_MODELS: readonly CatalogModel[] =
|
|
26
|
+
export const CATALOG_MODELS: readonly CatalogModel[] = catalog.models;
|
|
27
|
+
|
|
28
|
+
/** Language detection model for transcription models without native
|
|
29
|
+
* language detection. */
|
|
30
|
+
export const LANGUAGE_DETECTION_MODEL: CatalogModel = catalog.languageDetector;
|
|
27
31
|
|
|
28
32
|
const languageNames = new Intl.DisplayNames(["en"], { type: "language" });
|
|
29
33
|
|
package/src/chinese.ts
CHANGED
|
@@ -33,11 +33,8 @@ export function isChineseLanguage(language: string): boolean {
|
|
|
33
33
|
return base === "zh" || base === "yue";
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
* and Ext B+ (surrogate pairs are matched by their lead code unit).
|
|
39
|
-
*/
|
|
40
|
-
const HAN_CHARACTERS = /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\ud840-\ud87f]/;
|
|
36
|
+
const HAN = /\p{Script=Han}/u;
|
|
37
|
+
const KANA = /[\p{Script=Hiragana}\p{Script=Katakana}]/u;
|
|
41
38
|
|
|
42
39
|
/**
|
|
43
40
|
* Remote ASR reports no detected language, so Chinese output is decided by
|
|
@@ -45,7 +42,21 @@ const HAN_CHARACTERS = /[\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\ud840-\ud87f]/;
|
|
|
45
42
|
* text (or the configured language is Chinese) to convert.
|
|
46
43
|
*/
|
|
47
44
|
export function containsChineseCharacters(text: string): boolean {
|
|
48
|
-
return
|
|
45
|
+
return HAN.test(text);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Whether a transcript gets the Chinese script preference. The text decides,
|
|
50
|
+
* not language detection: on short clips the detector often says English for
|
|
51
|
+
* Mandarin, which used to leave the model's Simplified output unconverted.
|
|
52
|
+
* Kana means Japanese, whose kanji OpenCC would mangle (学→學, 図書館→图书馆).
|
|
53
|
+
*/
|
|
54
|
+
export function shouldConvertChinese(
|
|
55
|
+
text: string,
|
|
56
|
+
{ chineseEnabled, language }: { chineseEnabled: boolean; language: string },
|
|
57
|
+
): boolean {
|
|
58
|
+
if (!HAN.test(text) || KANA.test(text)) return false;
|
|
59
|
+
return chineseEnabled || isChineseLanguage(language);
|
|
49
60
|
}
|
|
50
61
|
|
|
51
62
|
export async function convertChineseOutput(
|