@adminforth/agent 1.40.4 → 1.41.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/build.log +2 -2
- package/custom/composables/useAgentAudio.ts +1 -1
- package/custom/package.json +1 -0
- package/custom/pnpm-lock.yaml +131 -0
- package/custom/speech_recognition_frontend/MicrophoneButon.vue +4 -8
- package/custom/speech_recognition_frontend/voiceActivityDetection.ts +48 -137
- package/dist/custom/composables/useAgentAudio.ts +1 -1
- package/dist/custom/package.json +1 -0
- package/dist/custom/pnpm-lock.yaml +131 -0
- package/dist/custom/speech_recognition_frontend/MicrophoneButon.vue +4 -8
- package/dist/custom/speech_recognition_frontend/voiceActivityDetection.ts +48 -137
- package/dist/index.js +14 -0
- package/index.ts +17 -0
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -58,5 +58,5 @@ custom/speech_recognition_frontend/voiceActivityDetection.ts
|
|
|
58
58
|
custom/speech_recognition_frontend/types/
|
|
59
59
|
custom/speech_recognition_frontend/types/voice-activity-detection.d.ts
|
|
60
60
|
|
|
61
|
-
sent 1,
|
|
62
|
-
total size is 1,
|
|
61
|
+
sent 1,660,093 bytes received 860 bytes 3,321,906.00 bytes/sec
|
|
62
|
+
total size is 1,656,231 speedup is 1.00
|
|
@@ -67,7 +67,7 @@ export const useAgentAudio = defineStore('agentAudio', () => {
|
|
|
67
67
|
async function sendAudioToServerAndHandleResponse(blob: Blob) {
|
|
68
68
|
currentAbortController = new AbortController();
|
|
69
69
|
const formData = new FormData();
|
|
70
|
-
formData.append('file', blob, 'user_prompt.
|
|
70
|
+
formData.append('file', blob, 'user_prompt.wav');
|
|
71
71
|
formData.append('sessionId', agentStore.activeSessionId);
|
|
72
72
|
formData.append('mode', agentStore.activeModeName ?? '');
|
|
73
73
|
formData.append('timeZone', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
package/custom/package.json
CHANGED
package/custom/pnpm-lock.yaml
CHANGED
|
@@ -17,6 +17,9 @@ importers:
|
|
|
17
17
|
'@incremark/vue':
|
|
18
18
|
specifier: ^1.0.2
|
|
19
19
|
version: 1.0.2(katex@0.16.45)(vue@3.5.32)
|
|
20
|
+
'@ricky0123/vad-web':
|
|
21
|
+
specifier: ^0.0.30
|
|
22
|
+
version: 0.0.30
|
|
20
23
|
'@shikijs/langs':
|
|
21
24
|
specifier: ^4.0.2
|
|
22
25
|
version: 4.0.2
|
|
@@ -139,6 +142,39 @@ packages:
|
|
|
139
142
|
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
|
|
140
143
|
engines: {node: '>=8.0.0'}
|
|
141
144
|
|
|
145
|
+
'@protobufjs/aspromise@1.1.2':
|
|
146
|
+
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
|
147
|
+
|
|
148
|
+
'@protobufjs/base64@1.1.2':
|
|
149
|
+
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
|
150
|
+
|
|
151
|
+
'@protobufjs/codegen@2.0.5':
|
|
152
|
+
resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
|
|
153
|
+
|
|
154
|
+
'@protobufjs/eventemitter@1.1.0':
|
|
155
|
+
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
|
156
|
+
|
|
157
|
+
'@protobufjs/fetch@1.1.0':
|
|
158
|
+
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
|
159
|
+
|
|
160
|
+
'@protobufjs/float@1.0.2':
|
|
161
|
+
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
|
162
|
+
|
|
163
|
+
'@protobufjs/inquire@1.1.1':
|
|
164
|
+
resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==}
|
|
165
|
+
|
|
166
|
+
'@protobufjs/path@1.1.2':
|
|
167
|
+
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
|
168
|
+
|
|
169
|
+
'@protobufjs/pool@1.1.0':
|
|
170
|
+
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
|
171
|
+
|
|
172
|
+
'@protobufjs/utf8@1.1.1':
|
|
173
|
+
resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==}
|
|
174
|
+
|
|
175
|
+
'@ricky0123/vad-web@0.0.30':
|
|
176
|
+
resolution: {integrity: sha512-cJyYrh4YeeUBJcbR9Bic/bFDyB9qBkAepvpuWM3vLxnAi7bC3VHzf51UeNdT+OtY4D7MLAgV8iJMc4z41ZnaWg==}
|
|
177
|
+
|
|
142
178
|
'@shikijs/core@3.23.0':
|
|
143
179
|
resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==}
|
|
144
180
|
|
|
@@ -218,6 +254,9 @@ packages:
|
|
|
218
254
|
'@types/ms@2.1.0':
|
|
219
255
|
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
|
220
256
|
|
|
257
|
+
'@types/node@25.6.0':
|
|
258
|
+
resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==}
|
|
259
|
+
|
|
221
260
|
'@types/trusted-types@2.0.7':
|
|
222
261
|
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
|
223
262
|
|
|
@@ -472,6 +511,9 @@ packages:
|
|
|
472
511
|
fast-json-patch@3.1.1:
|
|
473
512
|
resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==}
|
|
474
513
|
|
|
514
|
+
flatbuffers@25.9.23:
|
|
515
|
+
resolution: {integrity: sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==}
|
|
516
|
+
|
|
475
517
|
get-caller-file@2.0.5:
|
|
476
518
|
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
|
477
519
|
engines: {node: 6.* || 8.* || >= 10.*}
|
|
@@ -480,6 +522,9 @@ packages:
|
|
|
480
522
|
resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==}
|
|
481
523
|
engines: {node: '>=18'}
|
|
482
524
|
|
|
525
|
+
guid-typescript@1.0.9:
|
|
526
|
+
resolution: {integrity: sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==}
|
|
527
|
+
|
|
483
528
|
hast-util-to-html@9.0.5:
|
|
484
529
|
resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
|
|
485
530
|
|
|
@@ -525,6 +570,9 @@ packages:
|
|
|
525
570
|
lodash-es@4.18.1:
|
|
526
571
|
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
|
|
527
572
|
|
|
573
|
+
long@5.3.2:
|
|
574
|
+
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
|
|
575
|
+
|
|
528
576
|
longest-streak@3.1.0:
|
|
529
577
|
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
|
530
578
|
|
|
@@ -690,12 +738,21 @@ packages:
|
|
|
690
738
|
oniguruma-to-es@4.3.5:
|
|
691
739
|
resolution: {integrity: sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==}
|
|
692
740
|
|
|
741
|
+
onnxruntime-common@1.25.1:
|
|
742
|
+
resolution: {integrity: sha512-kKvYQFdos4LWJqhZ+nmKu3NT8NXzw8I5x9fNUKe1rNKcPfNKnYXUtW7JBpcKFsvLtrJashRgVYSbFap4cHxvNg==}
|
|
743
|
+
|
|
744
|
+
onnxruntime-web@1.25.1:
|
|
745
|
+
resolution: {integrity: sha512-mgs61sJ9m3hLa5jGRr9Pen3kkG00vlxmrcRL6FufYpSWBZKaklo0sotQCq2fLjgDVLnW57jrDcLqzYJNKeZskQ==}
|
|
746
|
+
|
|
693
747
|
parse-entities@4.0.2:
|
|
694
748
|
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
|
|
695
749
|
|
|
696
750
|
picocolors@1.1.1:
|
|
697
751
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
|
698
752
|
|
|
753
|
+
platform@1.3.6:
|
|
754
|
+
resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==}
|
|
755
|
+
|
|
699
756
|
postcss@8.5.10:
|
|
700
757
|
resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
|
|
701
758
|
engines: {node: ^10 || ^12 || >=14}
|
|
@@ -703,6 +760,10 @@ packages:
|
|
|
703
760
|
property-information@7.1.0:
|
|
704
761
|
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
|
|
705
762
|
|
|
763
|
+
protobufjs@7.5.6:
|
|
764
|
+
resolution: {integrity: sha512-M71sTMB146U3u0di3yup8iM+zv8yPRNQVr1KK4tyBitl3qFvEGucq/rGDRShD2rsJhtN02RJaJ7j5X5hmy8SJg==}
|
|
765
|
+
engines: {node: '>=12.0.0'}
|
|
766
|
+
|
|
706
767
|
regex-recursion@6.0.2:
|
|
707
768
|
resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
|
|
708
769
|
|
|
@@ -775,6 +836,9 @@ packages:
|
|
|
775
836
|
tslib@2.8.1:
|
|
776
837
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
|
777
838
|
|
|
839
|
+
undici-types@7.19.2:
|
|
840
|
+
resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==}
|
|
841
|
+
|
|
778
842
|
unist-util-is@6.0.1:
|
|
779
843
|
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
|
|
780
844
|
|
|
@@ -1063,6 +1127,33 @@ snapshots:
|
|
|
1063
1127
|
|
|
1064
1128
|
'@opentelemetry/api@1.9.0': {}
|
|
1065
1129
|
|
|
1130
|
+
'@protobufjs/aspromise@1.1.2': {}
|
|
1131
|
+
|
|
1132
|
+
'@protobufjs/base64@1.1.2': {}
|
|
1133
|
+
|
|
1134
|
+
'@protobufjs/codegen@2.0.5': {}
|
|
1135
|
+
|
|
1136
|
+
'@protobufjs/eventemitter@1.1.0': {}
|
|
1137
|
+
|
|
1138
|
+
'@protobufjs/fetch@1.1.0':
|
|
1139
|
+
dependencies:
|
|
1140
|
+
'@protobufjs/aspromise': 1.1.2
|
|
1141
|
+
'@protobufjs/inquire': 1.1.1
|
|
1142
|
+
|
|
1143
|
+
'@protobufjs/float@1.0.2': {}
|
|
1144
|
+
|
|
1145
|
+
'@protobufjs/inquire@1.1.1': {}
|
|
1146
|
+
|
|
1147
|
+
'@protobufjs/path@1.1.2': {}
|
|
1148
|
+
|
|
1149
|
+
'@protobufjs/pool@1.1.0': {}
|
|
1150
|
+
|
|
1151
|
+
'@protobufjs/utf8@1.1.1': {}
|
|
1152
|
+
|
|
1153
|
+
'@ricky0123/vad-web@0.0.30':
|
|
1154
|
+
dependencies:
|
|
1155
|
+
onnxruntime-web: 1.25.1
|
|
1156
|
+
|
|
1066
1157
|
'@shikijs/core@3.23.0':
|
|
1067
1158
|
dependencies:
|
|
1068
1159
|
'@shikijs/types': 3.23.0
|
|
@@ -1162,6 +1253,10 @@ snapshots:
|
|
|
1162
1253
|
|
|
1163
1254
|
'@types/ms@2.1.0': {}
|
|
1164
1255
|
|
|
1256
|
+
'@types/node@25.6.0':
|
|
1257
|
+
dependencies:
|
|
1258
|
+
undici-types: 7.19.2
|
|
1259
|
+
|
|
1165
1260
|
'@types/trusted-types@2.0.7':
|
|
1166
1261
|
optional: true
|
|
1167
1262
|
|
|
@@ -1404,10 +1499,14 @@ snapshots:
|
|
|
1404
1499
|
|
|
1405
1500
|
fast-json-patch@3.1.1: {}
|
|
1406
1501
|
|
|
1502
|
+
flatbuffers@25.9.23: {}
|
|
1503
|
+
|
|
1407
1504
|
get-caller-file@2.0.5: {}
|
|
1408
1505
|
|
|
1409
1506
|
get-east-asian-width@1.5.0: {}
|
|
1410
1507
|
|
|
1508
|
+
guid-typescript@1.0.9: {}
|
|
1509
|
+
|
|
1411
1510
|
hast-util-to-html@9.0.5:
|
|
1412
1511
|
dependencies:
|
|
1413
1512
|
'@types/hast': 3.0.4
|
|
@@ -1457,6 +1556,8 @@ snapshots:
|
|
|
1457
1556
|
|
|
1458
1557
|
lodash-es@4.18.1: {}
|
|
1459
1558
|
|
|
1559
|
+
long@5.3.2: {}
|
|
1560
|
+
|
|
1460
1561
|
longest-streak@3.1.0: {}
|
|
1461
1562
|
|
|
1462
1563
|
magic-string@0.30.21:
|
|
@@ -1832,6 +1933,17 @@ snapshots:
|
|
|
1832
1933
|
regex: 6.1.0
|
|
1833
1934
|
regex-recursion: 6.0.2
|
|
1834
1935
|
|
|
1936
|
+
onnxruntime-common@1.25.1: {}
|
|
1937
|
+
|
|
1938
|
+
onnxruntime-web@1.25.1:
|
|
1939
|
+
dependencies:
|
|
1940
|
+
flatbuffers: 25.9.23
|
|
1941
|
+
guid-typescript: 1.0.9
|
|
1942
|
+
long: 5.3.2
|
|
1943
|
+
onnxruntime-common: 1.25.1
|
|
1944
|
+
platform: 1.3.6
|
|
1945
|
+
protobufjs: 7.5.6
|
|
1946
|
+
|
|
1835
1947
|
parse-entities@4.0.2:
|
|
1836
1948
|
dependencies:
|
|
1837
1949
|
'@types/unist': 2.0.11
|
|
@@ -1844,6 +1956,8 @@ snapshots:
|
|
|
1844
1956
|
|
|
1845
1957
|
picocolors@1.1.1: {}
|
|
1846
1958
|
|
|
1959
|
+
platform@1.3.6: {}
|
|
1960
|
+
|
|
1847
1961
|
postcss@8.5.10:
|
|
1848
1962
|
dependencies:
|
|
1849
1963
|
nanoid: 3.3.11
|
|
@@ -1852,6 +1966,21 @@ snapshots:
|
|
|
1852
1966
|
|
|
1853
1967
|
property-information@7.1.0: {}
|
|
1854
1968
|
|
|
1969
|
+
protobufjs@7.5.6:
|
|
1970
|
+
dependencies:
|
|
1971
|
+
'@protobufjs/aspromise': 1.1.2
|
|
1972
|
+
'@protobufjs/base64': 1.1.2
|
|
1973
|
+
'@protobufjs/codegen': 2.0.5
|
|
1974
|
+
'@protobufjs/eventemitter': 1.1.0
|
|
1975
|
+
'@protobufjs/fetch': 1.1.0
|
|
1976
|
+
'@protobufjs/float': 1.0.2
|
|
1977
|
+
'@protobufjs/inquire': 1.1.1
|
|
1978
|
+
'@protobufjs/path': 1.1.2
|
|
1979
|
+
'@protobufjs/pool': 1.1.0
|
|
1980
|
+
'@protobufjs/utf8': 1.1.1
|
|
1981
|
+
'@types/node': 25.6.0
|
|
1982
|
+
long: 5.3.2
|
|
1983
|
+
|
|
1855
1984
|
regex-recursion@6.0.2:
|
|
1856
1985
|
dependencies:
|
|
1857
1986
|
regex-utilities: 2.3.0
|
|
@@ -1925,6 +2054,8 @@ snapshots:
|
|
|
1925
2054
|
|
|
1926
2055
|
tslib@2.8.1: {}
|
|
1927
2056
|
|
|
2057
|
+
undici-types@7.19.2: {}
|
|
2058
|
+
|
|
1928
2059
|
unist-util-is@6.0.1:
|
|
1929
2060
|
dependencies:
|
|
1930
2061
|
'@types/unist': 3.0.3
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<script setup lang="ts">
|
|
29
29
|
import { computed, onMounted, onBeforeUnmount, ref, watch } from 'vue';
|
|
30
30
|
import debounce from 'lodash.debounce';
|
|
31
|
-
import { requestMicAndStartVAD, stopUserMedia,
|
|
31
|
+
import { requestMicAndStartVAD, stopUserMedia, getRecord } from './voiceActivityDetection';
|
|
32
32
|
import { Spinner } from '@/afcl'
|
|
33
33
|
import { storeToRefs } from 'pinia';
|
|
34
34
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
@@ -41,7 +41,7 @@ const { sendAudioToServerAndHandleResponse } = agentAudio;
|
|
|
41
41
|
const { stopGenerationAndAudio } = agentAudio;
|
|
42
42
|
const { stopCurrentAudioPlayback } = agentAudio;
|
|
43
43
|
const { agentAudioMode } = storeToRefs(agentAudio);
|
|
44
|
-
const microphoneButtonMode = ref<'off' | '
|
|
44
|
+
const microphoneButtonMode = ref<'off' | 'listen' | 'transcribing' | 'generating'>('off');
|
|
45
45
|
const showAudioWavesAnimation = ref(false);
|
|
46
46
|
const audioAmplitude = ref(0);
|
|
47
47
|
const hideAnimationDebounced = debounce(() => {
|
|
@@ -93,14 +93,9 @@ function toggleChatMode() {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
async function onStartRecording() {
|
|
96
|
-
microphoneButtonMode.value = 'calibrating';
|
|
97
96
|
await requestMicAndStartVAD(saidSomething, stopRecording, onAnySound);
|
|
98
|
-
setTimeout(() => {
|
|
99
|
-
if (isAudioChatMode.value) {
|
|
100
97
|
microphoneButtonMode.value = 'listen';
|
|
101
98
|
agentAudio.playBeep(1000);
|
|
102
|
-
}
|
|
103
|
-
}, CALIBRATION_DURATION);
|
|
104
99
|
}
|
|
105
100
|
|
|
106
101
|
function onStopRecording() {
|
|
@@ -145,8 +140,9 @@ function onAnySound(amplitude: number) {
|
|
|
145
140
|
|
|
146
141
|
async function sendRecordForTranscription() {
|
|
147
142
|
showAudioWavesAnimation.value = false;
|
|
148
|
-
const recordBlob = await
|
|
143
|
+
const recordBlob = await getRecord();
|
|
149
144
|
if (recordBlob) {
|
|
145
|
+
console.log('Audio recorded, sending to server for transcription. Audio Blob size:', recordBlob.size, recordBlob.type);
|
|
150
146
|
onStopRecording();
|
|
151
147
|
await sendAudioToServerAndHandleResponse(recordBlob);
|
|
152
148
|
if (agentStore.isAudioChatMode) {
|
|
@@ -1,151 +1,62 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
let
|
|
4
|
-
let
|
|
5
|
-
let
|
|
6
|
-
let
|
|
7
|
-
let
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { MicVAD, utils } from "@ricky0123/vad-web"
|
|
2
|
+
|
|
3
|
+
let VADInstance: MicVAD | null = null;
|
|
4
|
+
let recordedAudioChunks: Float32Array[] = [];
|
|
5
|
+
let onVoiceStopCallback: () => void = () => {};
|
|
6
|
+
let onVoiceStartCallback: () => void = () => {};
|
|
7
|
+
let onUpdateCallback: (amplitude: number) => void = () => {};
|
|
8
|
+
|
|
9
|
+
async function createVADInstance(){
|
|
10
|
+
VADInstance = await MicVAD.new({
|
|
11
|
+
onFrameProcessed: ({ isSpeech }) => {
|
|
12
|
+
onUpdateCallback(isSpeech);
|
|
13
|
+
},
|
|
14
|
+
onSpeechEnd: (audio) => {
|
|
15
|
+
recordedAudioChunks.push(audio);
|
|
16
|
+
onVoiceStopCallback();
|
|
17
|
+
},
|
|
18
|
+
onSpeechStart: () => {
|
|
19
|
+
onVoiceStartCallback();
|
|
20
|
+
},
|
|
21
|
+
onnxWASMBasePath: "https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/",
|
|
22
|
+
baseAssetPath: "https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",
|
|
23
|
+
})
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
export async function requestMicAndStartVAD(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
27
|
+
onVoiceStop: () => void,
|
|
28
|
+
onVoiceStart: () => void,
|
|
29
|
+
onUpdate: (amplitude: number) => void
|
|
16
30
|
) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
navigator.mediaDevices
|
|
22
|
-
.getUserMedia({ audio: true })
|
|
23
|
-
.then((stream) => {
|
|
24
|
-
currentStream = stream;
|
|
25
|
-
startRecording(stream);
|
|
26
|
-
resolve();
|
|
27
|
-
startUserMedia(audioContext as AudioContext, stream, onVoiceStartCallback, onVoiceStopCallback, onUpdateCallback);
|
|
28
|
-
})
|
|
29
|
-
.catch((error) => {
|
|
30
|
-
handleMicConnectError();
|
|
31
|
-
reject(error);
|
|
32
|
-
});
|
|
33
|
-
} catch (e) {
|
|
34
|
-
handleUserMediaError();
|
|
35
|
-
reject(e);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function handleUserMediaError() {
|
|
41
|
-
console.error('Mic input is not supported by the browser.');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function handleMicConnectError() {
|
|
45
|
-
console.error('Could not connect microphone. Possible rejected by the user or is blocked by the browser.');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function stopUserMedia() {
|
|
49
|
-
wasVoiceStarted = false;
|
|
50
|
-
if (vadInstance && vadInstance.destroy) {
|
|
51
|
-
vadInstance.destroy();
|
|
52
|
-
vadInstance = null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (currentStream) {
|
|
56
|
-
currentStream.getTracks().forEach(track => track.stop());
|
|
57
|
-
currentStream = null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (audioContext) {
|
|
61
|
-
audioContext.close();
|
|
62
|
-
audioContext = null;
|
|
63
|
-
}
|
|
31
|
+
onVoiceStopCallback = onVoiceStop;
|
|
32
|
+
onVoiceStartCallback = onVoiceStart;
|
|
33
|
+
onUpdateCallback = onUpdate;
|
|
64
34
|
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
mediaRecorder = null;
|
|
35
|
+
if (!VADInstance) {
|
|
36
|
+
await createVADInstance();
|
|
68
37
|
}
|
|
69
|
-
|
|
38
|
+
VADInstance?.start();
|
|
70
39
|
}
|
|
71
40
|
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
mediaRecorder = new MediaRecorder(stream);
|
|
75
|
-
mediaRecorder.ondataavailable = (event: BlobEvent) => {
|
|
76
|
-
if (event.data.size > 0) {
|
|
77
|
-
recordedChunks.push(event.data);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
mediaRecorder.start();
|
|
41
|
+
export async function stopUserMedia() {
|
|
42
|
+
await VADInstance?.pause();
|
|
81
43
|
}
|
|
82
44
|
|
|
83
|
-
export async function
|
|
84
|
-
|
|
85
|
-
|
|
45
|
+
export async function getRecord() {
|
|
46
|
+
const totalSamples = recordedAudioChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
47
|
+
if (totalSamples === 0) {
|
|
48
|
+
return null;
|
|
86
49
|
}
|
|
87
50
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
recordedChunks = [];
|
|
94
|
-
return blob;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
if (recorder.state === 'inactive') {
|
|
98
|
-
return Promise.resolve(finalizeBlob());
|
|
51
|
+
const mergedAudio = new Float32Array(totalSamples);
|
|
52
|
+
let offset = 0;
|
|
53
|
+
for (const chunk of recordedAudioChunks) {
|
|
54
|
+
mergedAudio.set(chunk, offset);
|
|
55
|
+
offset += chunk.length;
|
|
99
56
|
}
|
|
100
57
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
recorder.onerror = () => {
|
|
106
|
-
recordedChunks = [];
|
|
107
|
-
reject(new Error('Failed to finalize audio recording.'));
|
|
108
|
-
};
|
|
109
|
-
recorder.stop();
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function startUserMedia(
|
|
114
|
-
audioContext: AudioContext,
|
|
115
|
-
stream: MediaStream,
|
|
116
|
-
onVoiceStartCallback: () => void,
|
|
117
|
-
onVoiceStopCallback: () => void,
|
|
118
|
-
onUpdateCallback: (amplitude: number) => void
|
|
119
|
-
) {
|
|
120
|
-
const options = {
|
|
121
|
-
fftSize: 1024,
|
|
122
|
-
bufferLen: 1024,
|
|
123
|
-
smoothingTimeConstant: 0.2,
|
|
124
|
-
minCaptureFreq: 85, // in Hz
|
|
125
|
-
maxCaptureFreq: 255, // in Hz
|
|
126
|
-
noiseCaptureDuration: CALIBRATION_DURATION, // in ms
|
|
127
|
-
minNoiseLevel: 0.5, // from 0 to 1
|
|
128
|
-
maxNoiseLevel: 0.7, // from 0 to 1
|
|
129
|
-
avgNoiseMultiplier: 1.2,
|
|
130
|
-
onVoiceStart() {
|
|
131
|
-
wasVoiceStarted = true;
|
|
132
|
-
if (!mediaRecorder || mediaRecorder.state === 'inactive') {
|
|
133
|
-
startRecording(currentStream as MediaStream);
|
|
134
|
-
}
|
|
135
|
-
console.log('👹👹👹voice start👹👹👹');
|
|
136
|
-
onVoiceStartCallback();
|
|
137
|
-
},
|
|
138
|
-
onVoiceStop() {
|
|
139
|
-
if (!wasVoiceStarted) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
console.log('👿👿👿voice stop👿👿👿');
|
|
143
|
-
onVoiceStopCallback();
|
|
144
|
-
}, //Doesn't work properly, so we will handle it with onUpdate callback
|
|
145
|
-
onUpdate(val: number) {
|
|
146
|
-
onUpdateCallback(val);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
vadInstance = vad(audioContext, stream, options);
|
|
58
|
+
const wavBuffer = utils.encodeWAV(mergedAudio, 1, 16000, 1, 16);
|
|
59
|
+
const recordToReturn = new Blob([wavBuffer], { type: 'audio/wav' });
|
|
60
|
+
recordedAudioChunks = [];
|
|
61
|
+
return recordToReturn;
|
|
151
62
|
}
|
|
@@ -67,7 +67,7 @@ export const useAgentAudio = defineStore('agentAudio', () => {
|
|
|
67
67
|
async function sendAudioToServerAndHandleResponse(blob: Blob) {
|
|
68
68
|
currentAbortController = new AbortController();
|
|
69
69
|
const formData = new FormData();
|
|
70
|
-
formData.append('file', blob, 'user_prompt.
|
|
70
|
+
formData.append('file', blob, 'user_prompt.wav');
|
|
71
71
|
formData.append('sessionId', agentStore.activeSessionId);
|
|
72
72
|
formData.append('mode', agentStore.activeModeName ?? '');
|
|
73
73
|
formData.append('timeZone', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
package/dist/custom/package.json
CHANGED
|
@@ -17,6 +17,9 @@ importers:
|
|
|
17
17
|
'@incremark/vue':
|
|
18
18
|
specifier: ^1.0.2
|
|
19
19
|
version: 1.0.2(katex@0.16.45)(vue@3.5.32)
|
|
20
|
+
'@ricky0123/vad-web':
|
|
21
|
+
specifier: ^0.0.30
|
|
22
|
+
version: 0.0.30
|
|
20
23
|
'@shikijs/langs':
|
|
21
24
|
specifier: ^4.0.2
|
|
22
25
|
version: 4.0.2
|
|
@@ -139,6 +142,39 @@ packages:
|
|
|
139
142
|
resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==}
|
|
140
143
|
engines: {node: '>=8.0.0'}
|
|
141
144
|
|
|
145
|
+
'@protobufjs/aspromise@1.1.2':
|
|
146
|
+
resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==}
|
|
147
|
+
|
|
148
|
+
'@protobufjs/base64@1.1.2':
|
|
149
|
+
resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==}
|
|
150
|
+
|
|
151
|
+
'@protobufjs/codegen@2.0.5':
|
|
152
|
+
resolution: {integrity: sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==}
|
|
153
|
+
|
|
154
|
+
'@protobufjs/eventemitter@1.1.0':
|
|
155
|
+
resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==}
|
|
156
|
+
|
|
157
|
+
'@protobufjs/fetch@1.1.0':
|
|
158
|
+
resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==}
|
|
159
|
+
|
|
160
|
+
'@protobufjs/float@1.0.2':
|
|
161
|
+
resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==}
|
|
162
|
+
|
|
163
|
+
'@protobufjs/inquire@1.1.1':
|
|
164
|
+
resolution: {integrity: sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==}
|
|
165
|
+
|
|
166
|
+
'@protobufjs/path@1.1.2':
|
|
167
|
+
resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==}
|
|
168
|
+
|
|
169
|
+
'@protobufjs/pool@1.1.0':
|
|
170
|
+
resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==}
|
|
171
|
+
|
|
172
|
+
'@protobufjs/utf8@1.1.1':
|
|
173
|
+
resolution: {integrity: sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==}
|
|
174
|
+
|
|
175
|
+
'@ricky0123/vad-web@0.0.30':
|
|
176
|
+
resolution: {integrity: sha512-cJyYrh4YeeUBJcbR9Bic/bFDyB9qBkAepvpuWM3vLxnAi7bC3VHzf51UeNdT+OtY4D7MLAgV8iJMc4z41ZnaWg==}
|
|
177
|
+
|
|
142
178
|
'@shikijs/core@3.23.0':
|
|
143
179
|
resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==}
|
|
144
180
|
|
|
@@ -218,6 +254,9 @@ packages:
|
|
|
218
254
|
'@types/ms@2.1.0':
|
|
219
255
|
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
|
220
256
|
|
|
257
|
+
'@types/node@25.6.0':
|
|
258
|
+
resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==}
|
|
259
|
+
|
|
221
260
|
'@types/trusted-types@2.0.7':
|
|
222
261
|
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
|
223
262
|
|
|
@@ -472,6 +511,9 @@ packages:
|
|
|
472
511
|
fast-json-patch@3.1.1:
|
|
473
512
|
resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==}
|
|
474
513
|
|
|
514
|
+
flatbuffers@25.9.23:
|
|
515
|
+
resolution: {integrity: sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==}
|
|
516
|
+
|
|
475
517
|
get-caller-file@2.0.5:
|
|
476
518
|
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
|
|
477
519
|
engines: {node: 6.* || 8.* || >= 10.*}
|
|
@@ -480,6 +522,9 @@ packages:
|
|
|
480
522
|
resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==}
|
|
481
523
|
engines: {node: '>=18'}
|
|
482
524
|
|
|
525
|
+
guid-typescript@1.0.9:
|
|
526
|
+
resolution: {integrity: sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==}
|
|
527
|
+
|
|
483
528
|
hast-util-to-html@9.0.5:
|
|
484
529
|
resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
|
|
485
530
|
|
|
@@ -525,6 +570,9 @@ packages:
|
|
|
525
570
|
lodash-es@4.18.1:
|
|
526
571
|
resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
|
|
527
572
|
|
|
573
|
+
long@5.3.2:
|
|
574
|
+
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
|
|
575
|
+
|
|
528
576
|
longest-streak@3.1.0:
|
|
529
577
|
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
|
530
578
|
|
|
@@ -690,12 +738,21 @@ packages:
|
|
|
690
738
|
oniguruma-to-es@4.3.5:
|
|
691
739
|
resolution: {integrity: sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==}
|
|
692
740
|
|
|
741
|
+
onnxruntime-common@1.25.1:
|
|
742
|
+
resolution: {integrity: sha512-kKvYQFdos4LWJqhZ+nmKu3NT8NXzw8I5x9fNUKe1rNKcPfNKnYXUtW7JBpcKFsvLtrJashRgVYSbFap4cHxvNg==}
|
|
743
|
+
|
|
744
|
+
onnxruntime-web@1.25.1:
|
|
745
|
+
resolution: {integrity: sha512-mgs61sJ9m3hLa5jGRr9Pen3kkG00vlxmrcRL6FufYpSWBZKaklo0sotQCq2fLjgDVLnW57jrDcLqzYJNKeZskQ==}
|
|
746
|
+
|
|
693
747
|
parse-entities@4.0.2:
|
|
694
748
|
resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
|
|
695
749
|
|
|
696
750
|
picocolors@1.1.1:
|
|
697
751
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
|
698
752
|
|
|
753
|
+
platform@1.3.6:
|
|
754
|
+
resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==}
|
|
755
|
+
|
|
699
756
|
postcss@8.5.10:
|
|
700
757
|
resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
|
|
701
758
|
engines: {node: ^10 || ^12 || >=14}
|
|
@@ -703,6 +760,10 @@ packages:
|
|
|
703
760
|
property-information@7.1.0:
|
|
704
761
|
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
|
|
705
762
|
|
|
763
|
+
protobufjs@7.5.6:
|
|
764
|
+
resolution: {integrity: sha512-M71sTMB146U3u0di3yup8iM+zv8yPRNQVr1KK4tyBitl3qFvEGucq/rGDRShD2rsJhtN02RJaJ7j5X5hmy8SJg==}
|
|
765
|
+
engines: {node: '>=12.0.0'}
|
|
766
|
+
|
|
706
767
|
regex-recursion@6.0.2:
|
|
707
768
|
resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
|
|
708
769
|
|
|
@@ -775,6 +836,9 @@ packages:
|
|
|
775
836
|
tslib@2.8.1:
|
|
776
837
|
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
|
777
838
|
|
|
839
|
+
undici-types@7.19.2:
|
|
840
|
+
resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==}
|
|
841
|
+
|
|
778
842
|
unist-util-is@6.0.1:
|
|
779
843
|
resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
|
|
780
844
|
|
|
@@ -1063,6 +1127,33 @@ snapshots:
|
|
|
1063
1127
|
|
|
1064
1128
|
'@opentelemetry/api@1.9.0': {}
|
|
1065
1129
|
|
|
1130
|
+
'@protobufjs/aspromise@1.1.2': {}
|
|
1131
|
+
|
|
1132
|
+
'@protobufjs/base64@1.1.2': {}
|
|
1133
|
+
|
|
1134
|
+
'@protobufjs/codegen@2.0.5': {}
|
|
1135
|
+
|
|
1136
|
+
'@protobufjs/eventemitter@1.1.0': {}
|
|
1137
|
+
|
|
1138
|
+
'@protobufjs/fetch@1.1.0':
|
|
1139
|
+
dependencies:
|
|
1140
|
+
'@protobufjs/aspromise': 1.1.2
|
|
1141
|
+
'@protobufjs/inquire': 1.1.1
|
|
1142
|
+
|
|
1143
|
+
'@protobufjs/float@1.0.2': {}
|
|
1144
|
+
|
|
1145
|
+
'@protobufjs/inquire@1.1.1': {}
|
|
1146
|
+
|
|
1147
|
+
'@protobufjs/path@1.1.2': {}
|
|
1148
|
+
|
|
1149
|
+
'@protobufjs/pool@1.1.0': {}
|
|
1150
|
+
|
|
1151
|
+
'@protobufjs/utf8@1.1.1': {}
|
|
1152
|
+
|
|
1153
|
+
'@ricky0123/vad-web@0.0.30':
|
|
1154
|
+
dependencies:
|
|
1155
|
+
onnxruntime-web: 1.25.1
|
|
1156
|
+
|
|
1066
1157
|
'@shikijs/core@3.23.0':
|
|
1067
1158
|
dependencies:
|
|
1068
1159
|
'@shikijs/types': 3.23.0
|
|
@@ -1162,6 +1253,10 @@ snapshots:
|
|
|
1162
1253
|
|
|
1163
1254
|
'@types/ms@2.1.0': {}
|
|
1164
1255
|
|
|
1256
|
+
'@types/node@25.6.0':
|
|
1257
|
+
dependencies:
|
|
1258
|
+
undici-types: 7.19.2
|
|
1259
|
+
|
|
1165
1260
|
'@types/trusted-types@2.0.7':
|
|
1166
1261
|
optional: true
|
|
1167
1262
|
|
|
@@ -1404,10 +1499,14 @@ snapshots:
|
|
|
1404
1499
|
|
|
1405
1500
|
fast-json-patch@3.1.1: {}
|
|
1406
1501
|
|
|
1502
|
+
flatbuffers@25.9.23: {}
|
|
1503
|
+
|
|
1407
1504
|
get-caller-file@2.0.5: {}
|
|
1408
1505
|
|
|
1409
1506
|
get-east-asian-width@1.5.0: {}
|
|
1410
1507
|
|
|
1508
|
+
guid-typescript@1.0.9: {}
|
|
1509
|
+
|
|
1411
1510
|
hast-util-to-html@9.0.5:
|
|
1412
1511
|
dependencies:
|
|
1413
1512
|
'@types/hast': 3.0.4
|
|
@@ -1457,6 +1556,8 @@ snapshots:
|
|
|
1457
1556
|
|
|
1458
1557
|
lodash-es@4.18.1: {}
|
|
1459
1558
|
|
|
1559
|
+
long@5.3.2: {}
|
|
1560
|
+
|
|
1460
1561
|
longest-streak@3.1.0: {}
|
|
1461
1562
|
|
|
1462
1563
|
magic-string@0.30.21:
|
|
@@ -1832,6 +1933,17 @@ snapshots:
|
|
|
1832
1933
|
regex: 6.1.0
|
|
1833
1934
|
regex-recursion: 6.0.2
|
|
1834
1935
|
|
|
1936
|
+
onnxruntime-common@1.25.1: {}
|
|
1937
|
+
|
|
1938
|
+
onnxruntime-web@1.25.1:
|
|
1939
|
+
dependencies:
|
|
1940
|
+
flatbuffers: 25.9.23
|
|
1941
|
+
guid-typescript: 1.0.9
|
|
1942
|
+
long: 5.3.2
|
|
1943
|
+
onnxruntime-common: 1.25.1
|
|
1944
|
+
platform: 1.3.6
|
|
1945
|
+
protobufjs: 7.5.6
|
|
1946
|
+
|
|
1835
1947
|
parse-entities@4.0.2:
|
|
1836
1948
|
dependencies:
|
|
1837
1949
|
'@types/unist': 2.0.11
|
|
@@ -1844,6 +1956,8 @@ snapshots:
|
|
|
1844
1956
|
|
|
1845
1957
|
picocolors@1.1.1: {}
|
|
1846
1958
|
|
|
1959
|
+
platform@1.3.6: {}
|
|
1960
|
+
|
|
1847
1961
|
postcss@8.5.10:
|
|
1848
1962
|
dependencies:
|
|
1849
1963
|
nanoid: 3.3.11
|
|
@@ -1852,6 +1966,21 @@ snapshots:
|
|
|
1852
1966
|
|
|
1853
1967
|
property-information@7.1.0: {}
|
|
1854
1968
|
|
|
1969
|
+
protobufjs@7.5.6:
|
|
1970
|
+
dependencies:
|
|
1971
|
+
'@protobufjs/aspromise': 1.1.2
|
|
1972
|
+
'@protobufjs/base64': 1.1.2
|
|
1973
|
+
'@protobufjs/codegen': 2.0.5
|
|
1974
|
+
'@protobufjs/eventemitter': 1.1.0
|
|
1975
|
+
'@protobufjs/fetch': 1.1.0
|
|
1976
|
+
'@protobufjs/float': 1.0.2
|
|
1977
|
+
'@protobufjs/inquire': 1.1.1
|
|
1978
|
+
'@protobufjs/path': 1.1.2
|
|
1979
|
+
'@protobufjs/pool': 1.1.0
|
|
1980
|
+
'@protobufjs/utf8': 1.1.1
|
|
1981
|
+
'@types/node': 25.6.0
|
|
1982
|
+
long: 5.3.2
|
|
1983
|
+
|
|
1855
1984
|
regex-recursion@6.0.2:
|
|
1856
1985
|
dependencies:
|
|
1857
1986
|
regex-utilities: 2.3.0
|
|
@@ -1925,6 +2054,8 @@ snapshots:
|
|
|
1925
2054
|
|
|
1926
2055
|
tslib@2.8.1: {}
|
|
1927
2056
|
|
|
2057
|
+
undici-types@7.19.2: {}
|
|
2058
|
+
|
|
1928
2059
|
unist-util-is@6.0.1:
|
|
1929
2060
|
dependencies:
|
|
1930
2061
|
'@types/unist': 3.0.3
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
<script setup lang="ts">
|
|
29
29
|
import { computed, onMounted, onBeforeUnmount, ref, watch } from 'vue';
|
|
30
30
|
import debounce from 'lodash.debounce';
|
|
31
|
-
import { requestMicAndStartVAD, stopUserMedia,
|
|
31
|
+
import { requestMicAndStartVAD, stopUserMedia, getRecord } from './voiceActivityDetection';
|
|
32
32
|
import { Spinner } from '@/afcl'
|
|
33
33
|
import { storeToRefs } from 'pinia';
|
|
34
34
|
import { useAgentStore } from '../composables/useAgentStore';
|
|
@@ -41,7 +41,7 @@ const { sendAudioToServerAndHandleResponse } = agentAudio;
|
|
|
41
41
|
const { stopGenerationAndAudio } = agentAudio;
|
|
42
42
|
const { stopCurrentAudioPlayback } = agentAudio;
|
|
43
43
|
const { agentAudioMode } = storeToRefs(agentAudio);
|
|
44
|
-
const microphoneButtonMode = ref<'off' | '
|
|
44
|
+
const microphoneButtonMode = ref<'off' | 'listen' | 'transcribing' | 'generating'>('off');
|
|
45
45
|
const showAudioWavesAnimation = ref(false);
|
|
46
46
|
const audioAmplitude = ref(0);
|
|
47
47
|
const hideAnimationDebounced = debounce(() => {
|
|
@@ -93,14 +93,9 @@ function toggleChatMode() {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
async function onStartRecording() {
|
|
96
|
-
microphoneButtonMode.value = 'calibrating';
|
|
97
96
|
await requestMicAndStartVAD(saidSomething, stopRecording, onAnySound);
|
|
98
|
-
setTimeout(() => {
|
|
99
|
-
if (isAudioChatMode.value) {
|
|
100
97
|
microphoneButtonMode.value = 'listen';
|
|
101
98
|
agentAudio.playBeep(1000);
|
|
102
|
-
}
|
|
103
|
-
}, CALIBRATION_DURATION);
|
|
104
99
|
}
|
|
105
100
|
|
|
106
101
|
function onStopRecording() {
|
|
@@ -145,8 +140,9 @@ function onAnySound(amplitude: number) {
|
|
|
145
140
|
|
|
146
141
|
async function sendRecordForTranscription() {
|
|
147
142
|
showAudioWavesAnimation.value = false;
|
|
148
|
-
const recordBlob = await
|
|
143
|
+
const recordBlob = await getRecord();
|
|
149
144
|
if (recordBlob) {
|
|
145
|
+
console.log('Audio recorded, sending to server for transcription. Audio Blob size:', recordBlob.size, recordBlob.type);
|
|
150
146
|
onStopRecording();
|
|
151
147
|
await sendAudioToServerAndHandleResponse(recordBlob);
|
|
152
148
|
if (agentStore.isAudioChatMode) {
|
|
@@ -1,151 +1,62 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
let
|
|
4
|
-
let
|
|
5
|
-
let
|
|
6
|
-
let
|
|
7
|
-
let
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { MicVAD, utils } from "@ricky0123/vad-web"
|
|
2
|
+
|
|
3
|
+
let VADInstance: MicVAD | null = null;
|
|
4
|
+
let recordedAudioChunks: Float32Array[] = [];
|
|
5
|
+
let onVoiceStopCallback: () => void = () => {};
|
|
6
|
+
let onVoiceStartCallback: () => void = () => {};
|
|
7
|
+
let onUpdateCallback: (amplitude: number) => void = () => {};
|
|
8
|
+
|
|
9
|
+
async function createVADInstance(){
|
|
10
|
+
VADInstance = await MicVAD.new({
|
|
11
|
+
onFrameProcessed: ({ isSpeech }) => {
|
|
12
|
+
onUpdateCallback(isSpeech);
|
|
13
|
+
},
|
|
14
|
+
onSpeechEnd: (audio) => {
|
|
15
|
+
recordedAudioChunks.push(audio);
|
|
16
|
+
onVoiceStopCallback();
|
|
17
|
+
},
|
|
18
|
+
onSpeechStart: () => {
|
|
19
|
+
onVoiceStartCallback();
|
|
20
|
+
},
|
|
21
|
+
onnxWASMBasePath: "https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/",
|
|
22
|
+
baseAssetPath: "https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",
|
|
23
|
+
})
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
export async function requestMicAndStartVAD(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
27
|
+
onVoiceStop: () => void,
|
|
28
|
+
onVoiceStart: () => void,
|
|
29
|
+
onUpdate: (amplitude: number) => void
|
|
16
30
|
) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
navigator.mediaDevices
|
|
22
|
-
.getUserMedia({ audio: true })
|
|
23
|
-
.then((stream) => {
|
|
24
|
-
currentStream = stream;
|
|
25
|
-
startRecording(stream);
|
|
26
|
-
resolve();
|
|
27
|
-
startUserMedia(audioContext as AudioContext, stream, onVoiceStartCallback, onVoiceStopCallback, onUpdateCallback);
|
|
28
|
-
})
|
|
29
|
-
.catch((error) => {
|
|
30
|
-
handleMicConnectError();
|
|
31
|
-
reject(error);
|
|
32
|
-
});
|
|
33
|
-
} catch (e) {
|
|
34
|
-
handleUserMediaError();
|
|
35
|
-
reject(e);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function handleUserMediaError() {
|
|
41
|
-
console.error('Mic input is not supported by the browser.');
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function handleMicConnectError() {
|
|
45
|
-
console.error('Could not connect microphone. Possible rejected by the user or is blocked by the browser.');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function stopUserMedia() {
|
|
49
|
-
wasVoiceStarted = false;
|
|
50
|
-
if (vadInstance && vadInstance.destroy) {
|
|
51
|
-
vadInstance.destroy();
|
|
52
|
-
vadInstance = null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (currentStream) {
|
|
56
|
-
currentStream.getTracks().forEach(track => track.stop());
|
|
57
|
-
currentStream = null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (audioContext) {
|
|
61
|
-
audioContext.close();
|
|
62
|
-
audioContext = null;
|
|
63
|
-
}
|
|
31
|
+
onVoiceStopCallback = onVoiceStop;
|
|
32
|
+
onVoiceStartCallback = onVoiceStart;
|
|
33
|
+
onUpdateCallback = onUpdate;
|
|
64
34
|
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
mediaRecorder = null;
|
|
35
|
+
if (!VADInstance) {
|
|
36
|
+
await createVADInstance();
|
|
68
37
|
}
|
|
69
|
-
|
|
38
|
+
VADInstance?.start();
|
|
70
39
|
}
|
|
71
40
|
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
mediaRecorder = new MediaRecorder(stream);
|
|
75
|
-
mediaRecorder.ondataavailable = (event: BlobEvent) => {
|
|
76
|
-
if (event.data.size > 0) {
|
|
77
|
-
recordedChunks.push(event.data);
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
mediaRecorder.start();
|
|
41
|
+
export async function stopUserMedia() {
|
|
42
|
+
await VADInstance?.pause();
|
|
81
43
|
}
|
|
82
44
|
|
|
83
|
-
export async function
|
|
84
|
-
|
|
85
|
-
|
|
45
|
+
export async function getRecord() {
|
|
46
|
+
const totalSamples = recordedAudioChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
47
|
+
if (totalSamples === 0) {
|
|
48
|
+
return null;
|
|
86
49
|
}
|
|
87
50
|
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
recordedChunks = [];
|
|
94
|
-
return blob;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
if (recorder.state === 'inactive') {
|
|
98
|
-
return Promise.resolve(finalizeBlob());
|
|
51
|
+
const mergedAudio = new Float32Array(totalSamples);
|
|
52
|
+
let offset = 0;
|
|
53
|
+
for (const chunk of recordedAudioChunks) {
|
|
54
|
+
mergedAudio.set(chunk, offset);
|
|
55
|
+
offset += chunk.length;
|
|
99
56
|
}
|
|
100
57
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
recorder.onerror = () => {
|
|
106
|
-
recordedChunks = [];
|
|
107
|
-
reject(new Error('Failed to finalize audio recording.'));
|
|
108
|
-
};
|
|
109
|
-
recorder.stop();
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function startUserMedia(
|
|
114
|
-
audioContext: AudioContext,
|
|
115
|
-
stream: MediaStream,
|
|
116
|
-
onVoiceStartCallback: () => void,
|
|
117
|
-
onVoiceStopCallback: () => void,
|
|
118
|
-
onUpdateCallback: (amplitude: number) => void
|
|
119
|
-
) {
|
|
120
|
-
const options = {
|
|
121
|
-
fftSize: 1024,
|
|
122
|
-
bufferLen: 1024,
|
|
123
|
-
smoothingTimeConstant: 0.2,
|
|
124
|
-
minCaptureFreq: 85, // in Hz
|
|
125
|
-
maxCaptureFreq: 255, // in Hz
|
|
126
|
-
noiseCaptureDuration: CALIBRATION_DURATION, // in ms
|
|
127
|
-
minNoiseLevel: 0.5, // from 0 to 1
|
|
128
|
-
maxNoiseLevel: 0.7, // from 0 to 1
|
|
129
|
-
avgNoiseMultiplier: 1.2,
|
|
130
|
-
onVoiceStart() {
|
|
131
|
-
wasVoiceStarted = true;
|
|
132
|
-
if (!mediaRecorder || mediaRecorder.state === 'inactive') {
|
|
133
|
-
startRecording(currentStream as MediaStream);
|
|
134
|
-
}
|
|
135
|
-
console.log('👹👹👹voice start👹👹👹');
|
|
136
|
-
onVoiceStartCallback();
|
|
137
|
-
},
|
|
138
|
-
onVoiceStop() {
|
|
139
|
-
if (!wasVoiceStarted) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
console.log('👿👿👿voice stop👿👿👿');
|
|
143
|
-
onVoiceStopCallback();
|
|
144
|
-
}, //Doesn't work properly, so we will handle it with onUpdate callback
|
|
145
|
-
onUpdate(val: number) {
|
|
146
|
-
onUpdateCallback(val);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
vadInstance = vad(audioContext, stream, options);
|
|
58
|
+
const wavBuffer = utils.encodeWAV(mergedAudio, 1, 16000, 1, 16);
|
|
59
|
+
const recordToReturn = new Blob([wavBuffer], { type: 'audio/wav' });
|
|
60
|
+
recordedAudioChunks = [];
|
|
61
|
+
return recordToReturn;
|
|
151
62
|
}
|
package/dist/index.js
CHANGED
|
@@ -134,6 +134,20 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
134
134
|
hasAudioAdapter: Boolean(this.options.audioAdapter),
|
|
135
135
|
}
|
|
136
136
|
});
|
|
137
|
+
if (!this.adminforth.config.customization.customHeadItems) {
|
|
138
|
+
this.adminforth.config.customization.customHeadItems = [];
|
|
139
|
+
}
|
|
140
|
+
this.adminforth.config.customization.customHeadItems.push({
|
|
141
|
+
tagName: 'script',
|
|
142
|
+
attributes: {
|
|
143
|
+
src: 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/ort.wasm.min.js'
|
|
144
|
+
}
|
|
145
|
+
}, {
|
|
146
|
+
tagName: 'script',
|
|
147
|
+
attributes: {
|
|
148
|
+
src: 'https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/bundle.min.js'
|
|
149
|
+
},
|
|
150
|
+
});
|
|
137
151
|
if (!this.options.sessionResource) {
|
|
138
152
|
throw new Error("sessionResource is required for AdminForthAgentPlugin");
|
|
139
153
|
}
|
package/index.ts
CHANGED
|
@@ -176,6 +176,23 @@ export default class AdminForthAgentPlugin extends AdminForthPlugin {
|
|
|
176
176
|
hasAudioAdapter: Boolean(this.options.audioAdapter),
|
|
177
177
|
}
|
|
178
178
|
});
|
|
179
|
+
if (!this.adminforth.config.customization.customHeadItems) {
|
|
180
|
+
this.adminforth.config.customization.customHeadItems = [];
|
|
181
|
+
}
|
|
182
|
+
this.adminforth.config.customization.customHeadItems.push(
|
|
183
|
+
{
|
|
184
|
+
tagName: 'script',
|
|
185
|
+
attributes: {
|
|
186
|
+
src: 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/ort.wasm.min.js'
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
tagName: 'script',
|
|
191
|
+
attributes: {
|
|
192
|
+
src: 'https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/bundle.min.js'
|
|
193
|
+
},
|
|
194
|
+
}
|
|
195
|
+
);
|
|
179
196
|
if (!this.options.sessionResource) {
|
|
180
197
|
throw new Error("sessionResource is required for AdminForthAgentPlugin");
|
|
181
198
|
}
|