speechflow 2.1.0 → 2.1.2
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/CHANGELOG.md +15 -0
- package/README.md +14 -11
- package/package.json +6 -6
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +11 -7
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.d.ts +3 -3
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +117 -100
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
- package/speechflow-cli/dst/{speechflow-node-a2t-assemblyai.d.ts → speechflow-node-t2t-simulator.d.ts} +1 -6
- package/speechflow-cli/dst/speechflow-node-t2t-simulator.js +128 -0
- package/speechflow-cli/dst/speechflow-node-t2t-simulator.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-webrtc.js +2 -2
- package/speechflow-cli/dst/speechflow-node-xio-webrtc.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-queue.d.ts +9 -3
- package/speechflow-cli/dst/speechflow-util-queue.js +39 -17
- package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.js +15 -15
- package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -1
- package/speechflow-cli/etc/oxlint.jsonc +5 -3
- package/speechflow-cli/package.json +26 -23
- package/speechflow-cli/src/speechflow-node-a2a-vad.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +17 -14
- package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +128 -112
- package/speechflow-cli/src/speechflow-node-xio-webrtc.ts +4 -4
- package/speechflow-cli/src/speechflow-util-queue.ts +44 -19
- package/speechflow-cli/src/speechflow-util-stream.ts +15 -15
- package/speechflow-ui-db/dst/app-font-fa-brands-400.woff2 +0 -0
- package/speechflow-ui-db/dst/app-font-fa-regular-400.woff2 +0 -0
- package/speechflow-ui-db/dst/app-font-fa-solid-900.woff2 +0 -0
- package/speechflow-ui-db/dst/app-font-fa-v4compatibility.woff2 +0 -0
- package/speechflow-ui-db/dst/index.css +1 -1
- package/speechflow-ui-db/dst/index.js +47 -46
- package/speechflow-ui-db/package.json +16 -14
- package/speechflow-ui-db/src/app.vue +2 -2
- package/speechflow-ui-st/dst/app-font-fa-brands-400.woff2 +0 -0
- package/speechflow-ui-st/dst/app-font-fa-regular-400.woff2 +0 -0
- package/speechflow-ui-st/dst/app-font-fa-solid-900.woff2 +0 -0
- package/speechflow-ui-st/dst/app-font-fa-v4compatibility.woff2 +0 -0
- package/speechflow-ui-st/dst/index.css +1 -1
- package/speechflow-ui-st/dst/index.js +65 -64
- package/speechflow-ui-st/etc/oxlint.jsonc +2 -1
- package/speechflow-ui-st/package.json +17 -15
- package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.js +0 -275
- package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.js.map +0 -1
- /package/speechflow-cli/package.d/{sherpa-onnx+1.12.23.patch → sherpa-onnx+1.12.25.patch} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speechflow-util-stream.js","sourceRoot":"","sources":["../src/speechflow-util-stream.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBF,oFAkBC;AAKD,oFA4BC;
|
|
1
|
+
{"version":3,"file":"speechflow-util-stream.js","sourceRoot":"","sources":["../src/speechflow-util-stream.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBF,oFAkBC;AAGD,8CAYC;AAKD,oFA4BC;AAaD,8CAkBC;AAGD,8CAsBC;AAgED,sCAmBC;AA3ND,6BAA6B;AAC7B,8DAAiD;AAEjD,6BAA6B;AAC7B,iCAA2C;AAC3C,4CAA2C;AAE3C,6BAA6B;AAC7B,uDAAuD;AACvD,wDAAuD;AAEvD;;2CAE2C;AAC3C,SAAgB,oCAAoC,CAChD,IAAsB,EACtB,qBAA8B;IAE9B,OAAO,IAAI,qBAAM,CAAC,SAAS,CAAC;QACxB,kBAAkB,EAAK,IAAI;QAC3B,kBAAkB,EAAK,KAAK;QAC5B,qBAAqB,EAAE,CAAC;QACxB,qBAAqB,EAAE,qBAAqB,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;QACzG,aAAa,EAAU,KAAK;QAC5B,SAAS,CAAE,KAAsB,EAAE,QAAQ,EAAE,QAAQ;YACjD,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;YACxB,QAAQ,EAAE,CAAA;QACd,CAAC;QACD,KAAK,CAAE,QAAQ;YACX,QAAQ,EAAE,CAAA;QACd,CAAC;KACJ,CAAC,CAAA;AACN,CAAC;AAED,sDAAsD;AACtD,SAAgB,iBAAiB,CAAE,IAAsB,EAAE,KAAwC;IAC/F,IAAI,KAAK,YAAY,iCAAe,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI;YACnB,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,mBAAmB,KAAK,CAAC,IAAI,QAAQ,CAAC,CAAA;IACrG,CAAC;SACI,CAAC;QACF,IAAI,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzC,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;aAC7B,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAChD,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClC,CAAC;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAED;;2CAE2C;AAC3C,SAAgB,oCAAoC,CAChD,IAAsB,EACtB,WAA2B,EAC3B,qBAA8B;IAE9B,OAAO,IAAI,qBAAM,CAAC,SAAS,CAAC;QACxB,kBAAkB,EAAK,KAAK;QAC5B,kBAAkB,EAAK,IAAI;QAC3B,qBAAqB,EAAE,qBAAqB,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;QACzG,qBAAqB,EAAE,CAAC;QACxB,aAAa,EAAU,KAAK;QAC5B,SAAS,CAAE,KAAsB,EAAE,QAAQ,EAAE,QAAQ;YACjD,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;YAC9B,MAAM,KAAK,GAAG,gBAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC3C,IAAI,GAAG,GAAG,KAAK,CAAA;YACf,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;gBACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,KAAe,CAAC,CAAA;gBAC1D,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAA;YACrC,CAAC;YACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,IAAI,EAAE,KAAK,CAAoB,CAAA;YACjE,MAAM,GAAG,GAAG,IAAI,iCAAe,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;YACnE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YACd,QAAQ,EAAE,CAAA;QACd,CAAC;QACD,KAAK,CAAE,QAAQ;YACX,QAAQ,EAAE,CAAA;QACd,CAAC;KACJ,CAAC,CAAA;AACN,CAAC;AAYD,sCAAsC;AACtC,SAAgB,iBAAiB,CAAE,KAAsB;IACrD,IAAI,OAAmB,CAAA;IACvB,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;QAC9B,OAAO,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;SACtC,CAAC;QACF,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;QACjC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAC3C,CAAC;IACD,MAAM,IAAI,GAA8B;QACpC,cAAc,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,EAAE;QAC/C,YAAY,EAAI,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE;QAC7C,IAAI,EAAY,KAAK,CAAC,IAAI;QAC1B,IAAI,EAAY,KAAK,CAAC,IAAI;QAC1B,OAAO;KACV,CAAA;IACD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAA;IAChD,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAC5B,CAAC;AAED,wCAAwC;AACxC,SAAgB,iBAAiB,CAAE,KAAiB;IAChD,IAAI,IAA+B,CAAA;IACnC,IAAI,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,MAAM,CAA4B,KAAK,CAAC,CAAA;IACxD,CAAC;IACD,OAAO,GAAY,EAAE,CAAC;QAClB,MAAM,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAA;IACvD,CAAC;IACD,IAAI,OAAwB,CAAA;IAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;QACrB,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;;QAEnC,OAAO,GAAG,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,MAAM,KAAK,GAAG,IAAI,iCAAe,CAC7B,gBAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,EACxC,gBAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,EACtC,IAAI,CAAC,IAAgC,EACrC,IAAI,CAAC,IAAwB,EAC7B,OAAO,EACP,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAC7C,CAAA;IACD,OAAO,KAAK,CAAA;AAChB,CAAC;AAED,kFAAkF;AAClF,MAAa,aAAc,SAAQ,qBAAM,CAAC,SAAS;IACvC,aAAa,CAAK;IAClB,MAAM,GAAI,CAAC,KAAU,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA,CAAC,CAAC,CAAA;IAC9C,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA,CAAC,CAAC,CAAA;IACrD,KAAK,GAAK,GAAa,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAC,CAAC,CAAA;IACrD,YAAa,aAAkB,EAAE,UAAmC,EAAE;QAClE,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAA;QACjC,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAA;QACjC,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA;QAClC,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YAC9C,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAG,IAAI,CAAC,MAAM,CAAC,CAAA;YAC3C,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;YAC5C,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAI,IAAI,CAAC,KAAK,CAAC,CAAA;QAC9C,CAAC;IACL,CAAC;IACD,UAAU,CAAE,KAAU,EAAE,QAAwB,EAAE,QAAkC;QAChF,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,QAAQ,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAA;YAC/C,OAAM;QACV,CAAC;QACD,IAAI,CAAC;YACD,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;gBACjD,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;gBACnD,IAAI,WAAW;oBACX,QAAQ,EAAE,CAAA;;oBAEV,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;YAClD,CAAC;;gBAEG,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;QAC5D,CAAC;QACD,OAAO,GAAY,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;QACnC,CAAC;IACL,CAAC;IACD,MAAM,CAAE,QAAkC;QACtC,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,QAAQ,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAA;YAC/C,OAAM;QACV,CAAC;QACD,IAAI,CAAC;YACD,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,KAAK,UAAU;gBAC5C,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAA;YAC5B,QAAQ,EAAE,CAAA;QACd,CAAC;QACD,OAAO,GAAY,EAAE,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAA;QACnC,CAAC;IACL,CAAC;IACD,QAAQ,CAAE,KAAmB,EAAE,QAAkC;QAC7D,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,cAAc,KAAK,UAAU,EAAE,CAAC;YAC1D,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM,EAAG,IAAI,CAAC,MAAM,CAAC,CAAA;YACvD,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;YACxD,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,KAAK,EAAI,IAAI,CAAC,KAAK,CAAC,CAAA;QAC1D,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;IACnC,CAAC;CACJ;AA1DD,sCA0DC;AAED,mDAAmD;AAC5C,KAAK,UAAU,aAAa,CAC/B,MAA4E;IAE5E,4CAA4C;IAC5C,IAAI,CAAG,MAAM,YAAY,qBAAM,CAAC,MAAM;WAC/B,MAAM,YAAY,qBAAM,CAAC,SAAS;WAClC,MAAM,YAAY,qBAAM,CAAC,QAAQ,CAAE;WACnC,CAAC,CAAC,MAAM,CAAC,aAAa,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;QAC/C,MAAM,OAAO,CAAC,IAAI,CAAC;YACf,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,CAAA,CAAC,CAAC,CAAC,CAAA;YACnC,CAAC,CAAC;YACF,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,oBAAoB,CAAC;SAC3C,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACV,yDAAyD;QAC7D,CAAC,CAAC,CAAA;IAEN,0BAA0B;IAC1B,MAAM,CAAC,OAAO,EAAE,CAAA;AACpB,CAAC"}
|
|
@@ -135,10 +135,12 @@
|
|
|
135
135
|
"no-inline-comments": "off",
|
|
136
136
|
"max-statements": "off",
|
|
137
137
|
"no-duplicate-imports": "off",
|
|
138
|
+
"no-nodejs-modules": "off",
|
|
139
|
+
"parameter-properties": "off",
|
|
140
|
+
"no-shadow": "off",
|
|
141
|
+
"no-relative-parent-imports": "off",
|
|
138
142
|
|
|
139
|
-
"complexity": [ "error", { "max": 35 } ]
|
|
140
|
-
"complexity/max-cyclomatic": [ "error", { "max": 30 } ],
|
|
141
|
-
"complexity/max-cognitive": [ "error", { "max": 50 } ]
|
|
143
|
+
"complexity": [ "error", { "max": 35 } ]
|
|
142
144
|
}
|
|
143
145
|
}
|
|
144
146
|
|
|
@@ -24,23 +24,23 @@
|
|
|
24
24
|
"shell-parser": "1.0.0",
|
|
25
25
|
"@deepgram/sdk": "4.11.3",
|
|
26
26
|
"deepl-node": "1.24.0",
|
|
27
|
-
"@elevenlabs/elevenlabs-js": "2.
|
|
27
|
+
"@elevenlabs/elevenlabs-js": "2.36.0",
|
|
28
28
|
"get-stream": "9.0.1",
|
|
29
29
|
"@dotenvx/dotenvx": "1.52.0",
|
|
30
30
|
"speex-resampler": "3.0.1",
|
|
31
31
|
"@sapphi-red/speex-preprocess-wasm": "0.4.0",
|
|
32
32
|
"@shiguredo/rnnoise-wasm": "2025.1.5",
|
|
33
|
-
"sherpa-onnx": "1.12.
|
|
34
|
-
"axios": "1.13.
|
|
35
|
-
"@aws-sdk/client-transcribe-streaming": "3.
|
|
36
|
-
"@aws-sdk/client-translate": "3.
|
|
37
|
-
"@aws-sdk/client-polly": "3.
|
|
33
|
+
"sherpa-onnx": "1.12.25",
|
|
34
|
+
"axios": "1.13.5",
|
|
35
|
+
"@aws-sdk/client-transcribe-streaming": "3.992.0",
|
|
36
|
+
"@aws-sdk/client-translate": "3.992.0",
|
|
37
|
+
"@aws-sdk/client-polly": "3.992.0",
|
|
38
38
|
"@google-cloud/translate": "9.3.0",
|
|
39
39
|
"@google-cloud/speech": "7.2.1",
|
|
40
40
|
"@google-cloud/text-to-speech": "6.4.0",
|
|
41
|
-
"node-web-audio-api": "1.0.
|
|
41
|
+
"node-web-audio-api": "1.0.8",
|
|
42
42
|
"object-path": "0.11.8",
|
|
43
|
-
"glob": "13.0.
|
|
43
|
+
"glob": "13.0.5",
|
|
44
44
|
"ws": "8.19.0",
|
|
45
45
|
"bufferutil": "4.1.0",
|
|
46
46
|
"utf-8-validate": "6.0.6",
|
|
@@ -51,15 +51,15 @@
|
|
|
51
51
|
"hapi-plugin-websocket": "2.4.11",
|
|
52
52
|
"@opensumi/reconnecting-websocket": "4.4.0",
|
|
53
53
|
"ollama": "0.6.3",
|
|
54
|
-
"openai": "6.
|
|
55
|
-
"@anthropic-ai/sdk": "0.
|
|
56
|
-
"@google/genai": "1.
|
|
54
|
+
"openai": "6.22.0",
|
|
55
|
+
"@anthropic-ai/sdk": "0.75.0",
|
|
56
|
+
"@google/genai": "1.41.0",
|
|
57
57
|
"@rse/ffmpeg": "1.4.2",
|
|
58
58
|
"ffmpeg-stream": "1.0.1",
|
|
59
59
|
"installed-packages": "1.0.13",
|
|
60
60
|
"syspath": "1.0.8",
|
|
61
61
|
"wav": "1.0.2",
|
|
62
|
-
"mqtt": "5.
|
|
62
|
+
"mqtt": "5.15.0",
|
|
63
63
|
"vban": "1.5.6",
|
|
64
64
|
"cbor2": "2.2.1",
|
|
65
65
|
"arktype": "2.1.29",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"wavefile": "11.0.0",
|
|
68
68
|
"audio-inspect": "0.0.4",
|
|
69
69
|
"@huggingface/transformers": "3.8.1",
|
|
70
|
-
"@huggingface/hub": "2.
|
|
70
|
+
"@huggingface/hub": "2.10.1",
|
|
71
71
|
"kokoro-js": "1.2.1",
|
|
72
72
|
"@ericedouard/vad-node-realtime": "0.2.0",
|
|
73
73
|
"osc-js": "2.4.1",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"@2toad/profanity": "3.2.0",
|
|
79
79
|
"cli-table3": "0.6.5",
|
|
80
80
|
"mkdirp": "3.0.1",
|
|
81
|
-
"@soundtouchjs/audio-worklet": "0.
|
|
82
|
-
"werift": "0.22.
|
|
81
|
+
"@soundtouchjs/audio-worklet": "0.3.0",
|
|
82
|
+
"werift": "0.22.8",
|
|
83
83
|
"@discordjs/opus": "0.10.0",
|
|
84
84
|
"@rse/stx": "1.1.4"
|
|
85
85
|
},
|
|
@@ -90,12 +90,12 @@
|
|
|
90
90
|
"eslint-plugin-promise": "7.2.1",
|
|
91
91
|
"eslint-plugin-import": "2.32.0",
|
|
92
92
|
"eslint-plugin-node": "11.1.0",
|
|
93
|
-
"typescript-eslint": "8.
|
|
94
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
95
|
-
"@typescript-eslint/parser": "8.
|
|
96
|
-
"oxlint": "1.
|
|
97
|
-
"oxlint-plugin-complexity": "0.
|
|
98
|
-
"eslint-plugin-oxlint": "1.
|
|
93
|
+
"typescript-eslint": "8.56.0",
|
|
94
|
+
"@typescript-eslint/eslint-plugin": "8.56.0",
|
|
95
|
+
"@typescript-eslint/parser": "8.56.0",
|
|
96
|
+
"oxlint": "1.48.0",
|
|
97
|
+
"oxlint-plugin-complexity": "2.0.0",
|
|
98
|
+
"eslint-plugin-oxlint": "1.48.0",
|
|
99
99
|
|
|
100
100
|
"@types/node": "24.10.1",
|
|
101
101
|
"@types/yargs": "17.0.35",
|
|
@@ -112,14 +112,17 @@
|
|
|
112
112
|
"stmux": "1.8.11",
|
|
113
113
|
"nodemon": "3.1.11",
|
|
114
114
|
"shx": "0.4.0",
|
|
115
|
-
"@yao-pkg/pkg": "6.
|
|
115
|
+
"@yao-pkg/pkg": "6.14.0",
|
|
116
116
|
"typescript": "5.9.3",
|
|
117
117
|
"delay-cli": "3.0.0",
|
|
118
118
|
"cross-env": "10.1.0"
|
|
119
119
|
},
|
|
120
120
|
"overrides": {
|
|
121
121
|
"@huggingface/transformers": { "onnxruntime-node": "1.22.0", "onnxruntime-web": "1.22.0" },
|
|
122
|
-
"@ericedouard/vad-node-realtime": { "onnxruntime-node": "1.22.0", "onnxruntime-web": "1.22.0" }
|
|
122
|
+
"@ericedouard/vad-node-realtime": { "onnxruntime-node": "1.22.0", "onnxruntime-web": "1.22.0" },
|
|
123
|
+
"eslint-plugin-promise": { "eslint": ">=9.0.0" },
|
|
124
|
+
"eslint-plugin-import": { "eslint": ">=9.0.0" },
|
|
125
|
+
"neostandard": { "eslint": ">=9.0.0" }
|
|
123
126
|
},
|
|
124
127
|
"upd": [
|
|
125
128
|
"!onnxruntime-node",
|
|
@@ -86,6 +86,7 @@ export default class SpeechFlowNodeA2AVAD extends SpeechFlowNode {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/* helper function for tail timer handling */
|
|
89
|
+
let tail = false
|
|
89
90
|
const startTailTimer = () => {
|
|
90
91
|
tail = true
|
|
91
92
|
clearTailTimer()
|
|
@@ -98,7 +99,6 @@ export default class SpeechFlowNodeA2AVAD extends SpeechFlowNode {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
/* establish Voice Activity Detection (VAD) facility */
|
|
101
|
-
let tail = false
|
|
102
102
|
try {
|
|
103
103
|
this.vad = await RealTimeVAD.new({
|
|
104
104
|
model: "v5",
|
|
@@ -32,13 +32,14 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
|
|
|
32
32
|
|
|
33
33
|
/* declare node configuration parameters */
|
|
34
34
|
this.configure({
|
|
35
|
-
key:
|
|
36
|
-
keyAdm:
|
|
37
|
-
model:
|
|
38
|
-
version:
|
|
39
|
-
language:
|
|
40
|
-
interim:
|
|
41
|
-
|
|
35
|
+
key: { type: "string", val: process.env.SPEECHFLOW_DEEPGRAM_KEY },
|
|
36
|
+
keyAdm: { type: "string", val: process.env.SPEECHFLOW_DEEPGRAM_KEY_ADM },
|
|
37
|
+
model: { type: "string", val: "nova-2", pos: 0 },
|
|
38
|
+
version: { type: "string", val: "latest", pos: 1 },
|
|
39
|
+
language: { type: "string", val: "multi", pos: 2 },
|
|
40
|
+
interim: { type: "boolean", val: false, pos: 3 },
|
|
41
|
+
endpointing: { type: "number", val: 0, pos: 4 },
|
|
42
|
+
keywords: { type: "string", val: "", pos: 5 }
|
|
42
43
|
})
|
|
43
44
|
|
|
44
45
|
/* sanity check parameters */
|
|
@@ -88,6 +89,8 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
|
|
|
88
89
|
const metastore = new util.TimeStore<Map<string, any>>()
|
|
89
90
|
|
|
90
91
|
/* configure Deepgram connection options */
|
|
92
|
+
const interim = this.params.interim as boolean
|
|
93
|
+
const endpointing = this.params.endpointing as number
|
|
91
94
|
const options: Deepgram.LiveSchema = {
|
|
92
95
|
mip_opt_out: true,
|
|
93
96
|
model: this.params.model,
|
|
@@ -96,8 +99,8 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
|
|
|
96
99
|
sample_rate: this.config.audioSampleRate,
|
|
97
100
|
encoding: "linear16",
|
|
98
101
|
multichannel: false,
|
|
99
|
-
endpointing: false,
|
|
100
|
-
interim_results:
|
|
102
|
+
endpointing: endpointing > 0 ? endpointing : false,
|
|
103
|
+
interim_results: interim,
|
|
101
104
|
smart_format: false,
|
|
102
105
|
punctuate: true,
|
|
103
106
|
filler_words: true,
|
|
@@ -140,13 +143,14 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
|
|
|
140
143
|
const text = (data.channel?.alternatives[0]?.transcript ?? "") as string
|
|
141
144
|
const words = (data.channel?.alternatives[0]?.words ?? []) as
|
|
142
145
|
{ word: string, punctuated_word?: string, start: number, end: number }[]
|
|
143
|
-
const isFinal
|
|
146
|
+
const isFinal = (data.is_final as boolean) ?? false
|
|
147
|
+
const speechFinal = (data.speech_final as boolean) ?? false
|
|
148
|
+
const kind = ((interim && isFinal) || (endpointing > 0 && speechFinal)) ? "final" : "intermediate"
|
|
144
149
|
if (text === "")
|
|
145
150
|
this.log("info", `empty/dummy text received (start: ${data.start}s, duration: ${data.duration.toFixed(2)}s)`)
|
|
146
151
|
else {
|
|
147
152
|
this.log("info", `text received (start: ${data.start}s, ` +
|
|
148
|
-
`duration: ${data.duration.toFixed(2)}s, ` +
|
|
149
|
-
`kind: ${isFinal ? "final" : "intermediate"}): ` +
|
|
153
|
+
`duration: ${data.duration.toFixed(2)}s, kind: ${kind}): ` +
|
|
150
154
|
`"${text}"`)
|
|
151
155
|
const start = Duration.fromMillis(data.start * 1000).plus(this.timeZeroOffset)
|
|
152
156
|
const end = start.plus({ seconds: data.duration })
|
|
@@ -161,8 +165,7 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
|
|
|
161
165
|
const end = Duration.fromMillis(word.end * 1000).plus(this.timeZeroOffset)
|
|
162
166
|
return { word: word.punctuated_word ?? word.word, start, end }
|
|
163
167
|
}))
|
|
164
|
-
const chunk = new SpeechFlowChunk(start, end,
|
|
165
|
-
isFinal ? "final" : "intermediate", "text", text, meta)
|
|
168
|
+
const chunk = new SpeechFlowChunk(start, end, kind, "text", text, meta)
|
|
166
169
|
this.queue.write(chunk)
|
|
167
170
|
}
|
|
168
171
|
})
|
|
@@ -18,8 +18,7 @@ import * as util from "./speechflow-util"
|
|
|
18
18
|
type TextQueueElement = {
|
|
19
19
|
type: "text-frame",
|
|
20
20
|
chunk: SpeechFlowChunk,
|
|
21
|
-
|
|
22
|
-
complete?: boolean
|
|
21
|
+
complete: boolean
|
|
23
22
|
} | {
|
|
24
23
|
type: "text-eof"
|
|
25
24
|
}
|
|
@@ -31,12 +30,11 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
31
30
|
|
|
32
31
|
/* internal state */
|
|
33
32
|
private queue = new util.Queue<TextQueueElement>()
|
|
34
|
-
private queueRecv = this.queue.pointerUse("recv")
|
|
35
|
-
private queueSplit = this.queue.pointerUse("split")
|
|
36
33
|
private queueSend = this.queue.pointerUse("send")
|
|
37
|
-
private
|
|
34
|
+
private queueSplit = this.queue.pointerUse("split")
|
|
35
|
+
private queueRecv = this.queue.pointerUse("recv")
|
|
36
|
+
private closing = false
|
|
38
37
|
private workingOffTimer: ReturnType<typeof setTimeout> | null = null
|
|
39
|
-
private previewTimer: ReturnType<typeof setTimeout> | null = null
|
|
40
38
|
|
|
41
39
|
/* construct node */
|
|
42
40
|
constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
|
|
@@ -44,7 +42,8 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
44
42
|
|
|
45
43
|
/* declare node configuration parameters */
|
|
46
44
|
this.configure({
|
|
47
|
-
timeout: { type: "number",
|
|
45
|
+
timeout: { type: "number", pos: 0, val: 3 * 1000 },
|
|
46
|
+
interim: { type: "boolean", pos: 1, val: false }
|
|
48
47
|
})
|
|
49
48
|
|
|
50
49
|
/* declare node input/output format */
|
|
@@ -52,6 +51,14 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
52
51
|
this.output = "text"
|
|
53
52
|
}
|
|
54
53
|
|
|
54
|
+
/* concatenate two payloads with proper whitespacing */
|
|
55
|
+
private concatPayload (s1: string, s2: string) {
|
|
56
|
+
if (!(s1.match(/\s+$/) || s2.match(/^\s+/)))
|
|
57
|
+
return `${s1} ${s2}`
|
|
58
|
+
else
|
|
59
|
+
return `${s1}${s2}`
|
|
60
|
+
}
|
|
61
|
+
|
|
55
62
|
/* open node */
|
|
56
63
|
async open () {
|
|
57
64
|
/* clear destruction flag */
|
|
@@ -83,84 +90,101 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
83
90
|
break
|
|
84
91
|
}
|
|
85
92
|
|
|
86
|
-
/*
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (m !== null) {
|
|
91
|
-
/* contains a sentence */
|
|
92
|
-
const [ , sentence, rest ] = m
|
|
93
|
-
if (rest !== "") {
|
|
94
|
-
/* contains more than a sentence */
|
|
95
|
-
const chunk2 = chunk.clone()
|
|
96
|
-
const duration = Duration.fromMillis(
|
|
97
|
-
chunk.timestampEnd.minus(chunk.timestampStart).toMillis() *
|
|
98
|
-
(sentence.length / payload.length))
|
|
99
|
-
chunk2.timestampStart = chunk.timestampStart.plus(duration)
|
|
100
|
-
chunk.timestampEnd = chunk2.timestampStart
|
|
101
|
-
chunk.payload = sentence
|
|
102
|
-
chunk2.payload = rest
|
|
103
|
-
element.complete = true
|
|
104
|
-
this.queueSplit.touch()
|
|
105
|
-
this.queueSplit.walk(+1)
|
|
106
|
-
this.queueSplit.insert({ type: "text-frame", chunk: chunk2 })
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
/* contains just the sentence */
|
|
110
|
-
element.complete = true
|
|
111
|
-
this.queueSplit.touch()
|
|
112
|
-
this.queueSplit.walk(+1)
|
|
113
|
-
}
|
|
93
|
+
/* skip elements already completed */
|
|
94
|
+
if (element.type === "text-frame" && element.chunk.kind === "final" && element.complete === true) {
|
|
95
|
+
this.queueSplit.walk(+1)
|
|
96
|
+
continue
|
|
114
97
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
98
|
+
|
|
99
|
+
/* perform sentence splitting on input chunk */
|
|
100
|
+
if (element.chunk.kind === "final") {
|
|
101
|
+
const chunk = element.chunk
|
|
102
|
+
const payload = chunk.payload as string
|
|
103
|
+
const m = payload.match(/^((?:.|\r?\n)+?[.;?!])(?:\s+((?:.|\r?\n)+)|\s*)$/)
|
|
104
|
+
if (m !== null) {
|
|
105
|
+
/* contains a sentence */
|
|
106
|
+
const [ , sentence, rest ] = m
|
|
107
|
+
if (rest !== undefined && rest !== "") {
|
|
108
|
+
/* contains more than a sentence */
|
|
109
|
+
const chunk2 = chunk.clone()
|
|
110
|
+
const duration = Duration.fromMillis(
|
|
111
|
+
chunk.timestampEnd.minus(chunk.timestampStart).toMillis() *
|
|
112
|
+
(sentence.length / payload.length))
|
|
113
|
+
chunk2.timestampStart = chunk.timestampStart.plus(duration)
|
|
114
|
+
chunk.timestampEnd = chunk2.timestampStart
|
|
115
|
+
chunk.payload = sentence
|
|
116
|
+
chunk2.payload = rest
|
|
126
117
|
element.complete = true
|
|
118
|
+
this.queue.silent(true)
|
|
127
119
|
this.queueSplit.touch()
|
|
120
|
+
this.queue.silent(false)
|
|
128
121
|
this.queueSplit.walk(+1)
|
|
129
|
-
|
|
122
|
+
this.queueSplit.insert({ type: "text-frame", chunk: chunk2, complete: false })
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
/* contains just the sentence */
|
|
126
|
+
element.complete = true
|
|
127
|
+
this.queue.silent(true)
|
|
128
|
+
this.queueSplit.silent(true)
|
|
129
|
+
const position = this.queueSplit.position()
|
|
130
|
+
this.queueSplit.walk(+1)
|
|
131
|
+
this.queue.silent(false)
|
|
132
|
+
this.queueSplit.silent(false)
|
|
133
|
+
this.queueSplit.touch(position)
|
|
130
134
|
}
|
|
131
|
-
|
|
132
|
-
/* merge into following chunk */
|
|
133
|
-
element2.chunk.timestampStart = element.chunk.timestampStart
|
|
134
|
-
element2.chunk.payload =
|
|
135
|
-
(element.chunk.payload as string) + " " +
|
|
136
|
-
(element2.chunk.payload as string)
|
|
137
|
-
|
|
138
|
-
/* reset preview state (merged content needs new preview) */
|
|
139
|
-
element2.preview = undefined
|
|
140
|
-
this.queueSplit.delete()
|
|
141
|
-
this.queueSplit.touch()
|
|
142
135
|
}
|
|
143
136
|
else {
|
|
144
|
-
/*
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
137
|
+
/* contains less than a sentence */
|
|
138
|
+
const position = this.queueSplit.position()
|
|
139
|
+
if (position < this.queueSplit.maxPosition() - 1) {
|
|
140
|
+
/* merge into following chunk */
|
|
141
|
+
const element2 = this.queueSplit.peek(position + 1)
|
|
142
|
+
if (element2 === undefined)
|
|
143
|
+
break
|
|
144
|
+
if (element2.type === "text-eof") {
|
|
145
|
+
/* no more chunks: output as final
|
|
146
|
+
(perhaps incomplete sentence at end of stream) */
|
|
147
|
+
element.complete = true
|
|
148
|
+
this.queueSplit.walk(+1)
|
|
149
|
+
this.queueSplit.touch(this.queueSplit.position() - 1)
|
|
150
|
+
break
|
|
151
|
+
}
|
|
152
|
+
if (element2.chunk.kind === "final") {
|
|
153
|
+
/* merge into following chunk */
|
|
154
|
+
element2.chunk.timestampStart = element.chunk.timestampStart
|
|
155
|
+
element2.chunk.payload = this.concatPayload(element.chunk.payload as string,
|
|
156
|
+
element2.chunk.payload as string)
|
|
157
|
+
|
|
158
|
+
/* remove current element and touch now current element */
|
|
159
|
+
this.queue.silent(true)
|
|
160
|
+
this.queueSplit.delete()
|
|
161
|
+
this.queue.silent(false)
|
|
162
|
+
this.queueSplit.touch()
|
|
163
|
+
}
|
|
164
|
+
else
|
|
165
|
+
break
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
/* no following chunk yet */
|
|
169
|
+
break
|
|
148
170
|
}
|
|
149
|
-
break
|
|
150
171
|
}
|
|
151
172
|
}
|
|
173
|
+
else
|
|
174
|
+
break
|
|
152
175
|
}
|
|
153
176
|
|
|
154
177
|
/* re-initiate working off round (if still not destroyed) */
|
|
155
|
-
workingOff = false
|
|
156
178
|
if (!this.closing) {
|
|
157
179
|
this.workingOffTimer = setTimeout(workOffQueue, 100)
|
|
158
180
|
this.queue.once("write", workOffQueue)
|
|
159
181
|
}
|
|
182
|
+
workingOff = false
|
|
160
183
|
}
|
|
161
184
|
this.queue.once("write", workOffQueue)
|
|
162
185
|
|
|
163
186
|
/* provide Duplex stream and internally attach to classifier */
|
|
187
|
+
let previewed = false
|
|
164
188
|
const self = this
|
|
165
189
|
this.stream = new Stream.Duplex({
|
|
166
190
|
writableObjectMode: true,
|
|
@@ -169,37 +193,38 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
169
193
|
highWaterMark: 1,
|
|
170
194
|
|
|
171
195
|
/* receive text chunk (writable side of stream) */
|
|
172
|
-
write (chunk: SpeechFlowChunk, encoding, callback) {
|
|
196
|
+
write (chunk: SpeechFlowChunk, encoding: BufferEncoding, callback: (error?: Error | null) => void) {
|
|
173
197
|
if (self.closing)
|
|
174
198
|
callback(new Error("stream already destroyed"))
|
|
175
199
|
else if (Buffer.isBuffer(chunk.payload))
|
|
176
200
|
callback(new Error("expected text input as string chunks"))
|
|
177
201
|
else if (chunk.payload.length === 0)
|
|
178
202
|
callback()
|
|
179
|
-
else if (chunk.kind === "intermediate") {
|
|
180
|
-
/* intermediate chunks: pass through immediately (bypass queue) */
|
|
181
|
-
self.log("info", `received text (${chunk.kind}): ${JSON.stringify(chunk.payload)}`)
|
|
182
|
-
self.log("info", `send text (intermediate pass-through): ${JSON.stringify(chunk.payload)}`)
|
|
183
|
-
this.push(chunk)
|
|
184
|
-
callback()
|
|
185
|
-
}
|
|
186
203
|
else {
|
|
187
204
|
/* final chunks: queue for sentence splitting */
|
|
188
205
|
self.log("info", `received text (${chunk.kind}): ${JSON.stringify(chunk.payload)}`)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
206
|
+
const recvPos = self.queueRecv.position()
|
|
207
|
+
if (recvPos > 0) {
|
|
208
|
+
const element = self.queueRecv.peek(recvPos - 1)
|
|
209
|
+
if (element) {
|
|
210
|
+
if (element.type === "text-eof") {
|
|
211
|
+
callback(new Error("received text input after end-of-stream"))
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
if (element.chunk.kind === "intermediate") {
|
|
215
|
+
self.queueRecv.walk(-1)
|
|
216
|
+
self.queueRecv.delete()
|
|
217
|
+
}
|
|
218
|
+
}
|
|
194
219
|
}
|
|
195
|
-
|
|
196
|
-
self.queueRecv.append({ type: "text-frame", chunk })
|
|
220
|
+
previewed = false
|
|
221
|
+
self.queueRecv.append({ type: "text-frame", chunk, complete: false })
|
|
197
222
|
callback()
|
|
198
223
|
}
|
|
199
224
|
},
|
|
200
225
|
|
|
201
226
|
/* receive no more text chunks (writable side of stream) */
|
|
202
|
-
final (callback) {
|
|
227
|
+
final (callback: (error?: Error | null) => void) {
|
|
203
228
|
if (self.closing) {
|
|
204
229
|
callback()
|
|
205
230
|
return
|
|
@@ -227,6 +252,7 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
227
252
|
&& element.type === "text-frame"
|
|
228
253
|
&& element.complete === true) {
|
|
229
254
|
/* send all consecutive complete chunks */
|
|
255
|
+
let eofSeen = false
|
|
230
256
|
while (true) {
|
|
231
257
|
const nextElement = self.queueSend.peek()
|
|
232
258
|
if (nextElement === undefined)
|
|
@@ -234,49 +260,43 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
234
260
|
else if (nextElement.type === "text-eof") {
|
|
235
261
|
this.push(null)
|
|
236
262
|
self.queueSend.walk(+1)
|
|
263
|
+
eofSeen = true
|
|
237
264
|
break
|
|
238
265
|
}
|
|
239
266
|
else if (nextElement.type === "text-frame"
|
|
240
267
|
&& nextElement.complete !== true)
|
|
241
268
|
break
|
|
242
|
-
self.log("info", `send text (${nextElement.chunk.kind}): ${JSON.stringify(nextElement.chunk.payload)}`)
|
|
269
|
+
self.log("info", `send text 1 (${nextElement.chunk.kind}): ${JSON.stringify(nextElement.chunk.payload)} pos=${self.queueSend.position()}`)
|
|
243
270
|
this.push(nextElement.chunk)
|
|
244
271
|
self.queueSend.walk(+1)
|
|
245
272
|
self.queue.trim()
|
|
246
273
|
}
|
|
274
|
+
|
|
275
|
+
/* wait for more data (unless end-of-stream was reached) */
|
|
276
|
+
if (!eofSeen && !self.closing)
|
|
277
|
+
self.queue.once("write", flushPendingChunks)
|
|
247
278
|
}
|
|
248
279
|
else if (element !== undefined
|
|
249
280
|
&& element.type === "text-frame"
|
|
250
|
-
&& element.
|
|
251
|
-
|
|
281
|
+
&& element.complete === false
|
|
282
|
+
&& !previewed
|
|
283
|
+
&& self.params.interim === true) {
|
|
284
|
+
/* merge together all still queued elements and
|
|
285
|
+
send this out as an intermediate chunk as preview */
|
|
252
286
|
const previewChunk = element.chunk.clone()
|
|
253
287
|
previewChunk.kind = "intermediate"
|
|
254
|
-
self.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
self.previewTimer = setTimeout(() => {
|
|
263
|
-
self.previewTimer = null
|
|
264
|
-
if (self.closing)
|
|
265
|
-
return
|
|
266
|
-
|
|
267
|
-
/* promote preview to final chunk */
|
|
268
|
-
const el = self.queueSend.peek()
|
|
269
|
-
if (el !== undefined
|
|
270
|
-
&& el.type === "text-frame"
|
|
271
|
-
&& el.preview === "sent"
|
|
272
|
-
&& el.complete !== true) {
|
|
273
|
-
self.log("info", `timeout: promoting intermediate to final: ${JSON.stringify(el.chunk.payload)}`)
|
|
274
|
-
el.complete = true
|
|
275
|
-
self.queueSend.touch()
|
|
276
|
-
self.queue.emit("write")
|
|
277
|
-
}
|
|
278
|
-
}, timeout)
|
|
288
|
+
for (let pos = self.queueSend.position() + 1; pos < self.queueSend.maxPosition(); pos++) {
|
|
289
|
+
const element2 = self.queueSend.peek(pos)
|
|
290
|
+
if (!element2)
|
|
291
|
+
continue
|
|
292
|
+
if (element2.type === "text-eof")
|
|
293
|
+
break
|
|
294
|
+
previewChunk.payload = self.concatPayload(
|
|
295
|
+
previewChunk.payload as string, element2.chunk.payload as string)
|
|
279
296
|
}
|
|
297
|
+
this.push(previewChunk)
|
|
298
|
+
self.log("info", `send text 2 (intermediate): ${JSON.stringify(previewChunk.payload)}`)
|
|
299
|
+
previewed = true
|
|
280
300
|
|
|
281
301
|
/* wait for more data */
|
|
282
302
|
if (!self.closing)
|
|
@@ -300,10 +320,6 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
|
|
|
300
320
|
clearTimeout(this.workingOffTimer)
|
|
301
321
|
this.workingOffTimer = null
|
|
302
322
|
}
|
|
303
|
-
if (this.previewTimer !== null) {
|
|
304
|
-
clearTimeout(this.previewTimer)
|
|
305
|
-
this.previewTimer = null
|
|
306
|
-
}
|
|
307
323
|
|
|
308
324
|
/* remove any pending event listeners */
|
|
309
325
|
this.queue.removeAllListeners("write")
|
|
@@ -94,6 +94,10 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
|
|
|
94
94
|
const chunks: Buffer[] = []
|
|
95
95
|
const maxBodySize = 1024 * 1024 /* 1 MB limit for SDP */
|
|
96
96
|
let totalSize = 0
|
|
97
|
+
const onError = (err: Error) =>
|
|
98
|
+
reject(err)
|
|
99
|
+
const onEnd = () =>
|
|
100
|
+
resolve(Buffer.concat(chunks).toString("utf8"))
|
|
97
101
|
const onData = (chunk: Buffer) => {
|
|
98
102
|
totalSize += chunk.length
|
|
99
103
|
if (totalSize > maxBodySize) {
|
|
@@ -106,10 +110,6 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
|
|
|
106
110
|
}
|
|
107
111
|
chunks.push(chunk)
|
|
108
112
|
}
|
|
109
|
-
const onEnd = () =>
|
|
110
|
-
resolve(Buffer.concat(chunks).toString("utf8"))
|
|
111
|
-
const onError = (err: Error) =>
|
|
112
|
-
reject(err)
|
|
113
113
|
req.on("data", onData)
|
|
114
114
|
req.on("end", onEnd)
|
|
115
115
|
req.on("error", onError)
|