speechflow 1.4.5 → 1.5.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/CHANGELOG.md +28 -0
- package/README.md +220 -7
- package/etc/claude.md +70 -0
- package/etc/speechflow.yaml +5 -3
- package/etc/stx.conf +7 -0
- package/package.json +7 -6
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +155 -0
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.d.ts +15 -0
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +287 -0
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.js +208 -0
- package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-dynamics.d.ts +15 -0
- package/speechflow-cli/dst/speechflow-node-a2a-dynamics.js +312 -0
- package/speechflow-cli/dst/speechflow-node-a2a-dynamics.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +161 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js +208 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js +13 -3
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-filler.d.ts +14 -0
- package/speechflow-cli/dst/speechflow-node-a2a-filler.js +233 -0
- package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gain.d.ts +12 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gain.js +125 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gain.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gender.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js +28 -12
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-meter.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +12 -8
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js +2 -1
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js +55 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.d.ts +14 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +184 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-speex.d.ts +14 -0
- package/speechflow-cli/dst/speechflow-node-a2a-speex.js +156 -0
- package/speechflow-cli/dst/speechflow-node-a2a-speex.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js +3 -3
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js +22 -17
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.d.ts +18 -0
- package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.js +317 -0
- package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +15 -13
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.d.ts +19 -0
- package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.js +351 -0
- package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2a-awspolly.d.ts +16 -0
- package/speechflow-cli/dst/speechflow-node-t2a-awspolly.js +171 -0
- package/speechflow-cli/dst/speechflow-node-t2a-awspolly.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +19 -14
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +11 -6
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.js +141 -0
- package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +13 -15
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-format.js +10 -15
- package/speechflow-cli/dst/speechflow-node-t2t-format.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.js +44 -31
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-openai.js +44 -45
- package/speechflow-cli/dst/speechflow-node-t2t-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +8 -8
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +10 -12
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-transformers.js +22 -27
- package/speechflow-cli/dst/speechflow-node-t2t-transformers.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-filter.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js +50 -15
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js +17 -18
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-device.js +13 -21
- package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js +22 -16
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js +19 -19
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node.d.ts +6 -3
- package/speechflow-cli/dst/speechflow-node.js +13 -2
- package/speechflow-cli/dst/speechflow-node.js.map +1 -1
- package/speechflow-cli/dst/speechflow-utils-audio-wt.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-utils-audio-wt.js +124 -0
- package/speechflow-cli/dst/speechflow-utils-audio-wt.js.map +1 -0
- package/speechflow-cli/dst/speechflow-utils-audio.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-utils-audio.js +137 -0
- package/speechflow-cli/dst/speechflow-utils-audio.js.map +1 -0
- package/speechflow-cli/dst/speechflow-utils.d.ts +18 -0
- package/speechflow-cli/dst/speechflow-utils.js +123 -35
- package/speechflow-cli/dst/speechflow-utils.js.map +1 -1
- package/speechflow-cli/dst/speechflow.js +69 -14
- package/speechflow-cli/dst/speechflow.js.map +1 -1
- package/speechflow-cli/etc/oxlint.jsonc +112 -11
- package/speechflow-cli/etc/stx.conf +2 -2
- package/speechflow-cli/etc/tsconfig.json +1 -1
- package/speechflow-cli/package.d/@shiguredo+rnnoise-wasm+2025.1.5.patch +25 -0
- package/speechflow-cli/package.json +102 -94
- package/speechflow-cli/src/lib.d.ts +24 -0
- package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +151 -0
- package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +303 -0
- package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +158 -0
- package/speechflow-cli/src/speechflow-node-a2a-expander.ts +212 -0
- package/speechflow-cli/src/speechflow-node-a2a-ffmpeg.ts +13 -3
- package/speechflow-cli/src/speechflow-node-a2a-filler.ts +223 -0
- package/speechflow-cli/src/speechflow-node-a2a-gain.ts +98 -0
- package/speechflow-cli/src/speechflow-node-a2a-gender.ts +31 -17
- package/speechflow-cli/src/speechflow-node-a2a-meter.ts +13 -9
- package/speechflow-cli/src/speechflow-node-a2a-mute.ts +3 -2
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise-wt.ts +62 -0
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +164 -0
- package/speechflow-cli/src/speechflow-node-a2a-speex.ts +137 -0
- package/speechflow-cli/src/speechflow-node-a2a-vad.ts +3 -3
- package/speechflow-cli/src/speechflow-node-a2a-wav.ts +20 -13
- package/speechflow-cli/src/speechflow-node-a2t-awstranscribe.ts +308 -0
- package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +15 -13
- package/speechflow-cli/src/speechflow-node-a2t-openaitranscribe.ts +337 -0
- package/speechflow-cli/src/speechflow-node-t2a-awspolly.ts +187 -0
- package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +19 -14
- package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +12 -7
- package/speechflow-cli/src/speechflow-node-t2t-awstranslate.ts +152 -0
- package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +13 -15
- package/speechflow-cli/src/speechflow-node-t2t-format.ts +10 -15
- package/speechflow-cli/src/speechflow-node-t2t-ollama.ts +55 -42
- package/speechflow-cli/src/speechflow-node-t2t-openai.ts +58 -58
- package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +10 -10
- package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +15 -16
- package/speechflow-cli/src/speechflow-node-t2t-transformers.ts +27 -32
- package/speechflow-cli/src/speechflow-node-x2x-filter.ts +20 -16
- package/speechflow-cli/src/speechflow-node-x2x-trace.ts +20 -19
- package/speechflow-cli/src/speechflow-node-xio-device.ts +15 -23
- package/speechflow-cli/src/speechflow-node-xio-mqtt.ts +23 -16
- package/speechflow-cli/src/speechflow-node-xio-websocket.ts +19 -19
- package/speechflow-cli/src/speechflow-node.ts +21 -8
- package/speechflow-cli/src/speechflow-utils-audio-wt.ts +172 -0
- package/speechflow-cli/src/speechflow-utils-audio.ts +147 -0
- package/speechflow-cli/src/speechflow-utils.ts +125 -32
- package/speechflow-cli/src/speechflow.ts +74 -17
- package/speechflow-ui-db/dst/index.js +31 -31
- package/speechflow-ui-db/etc/eslint.mjs +0 -1
- package/speechflow-ui-db/etc/tsc-client.json +3 -3
- package/speechflow-ui-db/package.json +11 -10
- package/speechflow-ui-db/src/app.vue +20 -6
- package/speechflow-ui-st/dst/index.js +26 -26
- package/speechflow-ui-st/etc/eslint.mjs +0 -1
- package/speechflow-ui-st/etc/tsc-client.json +3 -3
- package/speechflow-ui-st/package.json +11 -10
- package/speechflow-ui-st/src/app.vue +5 -12
|
@@ -1,116 +1,124 @@
|
|
|
1
1
|
{
|
|
2
|
-
"private":
|
|
3
|
-
"name":
|
|
4
|
-
"version":
|
|
5
|
-
"homepage":
|
|
6
|
-
"description":
|
|
7
|
-
"license":
|
|
2
|
+
"private": true,
|
|
3
|
+
"name": "speechflow",
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"homepage": "https://github.com/rse/speechflow",
|
|
6
|
+
"description": "Speech Processing Flow Graph",
|
|
7
|
+
"license": "GPL-3.0-only",
|
|
8
8
|
"author": {
|
|
9
|
-
"name":
|
|
10
|
-
"email":
|
|
11
|
-
"url":
|
|
9
|
+
"name": "Dr. Ralf S. Engelschall",
|
|
10
|
+
"email": "rse@engelschall.com",
|
|
11
|
+
"url": "http://engelschall.com"
|
|
12
12
|
},
|
|
13
13
|
"repository": {
|
|
14
|
-
"type":
|
|
15
|
-
"url":
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/rse/speechflow.git"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"cli-io":
|
|
19
|
-
"yargs":
|
|
20
|
-
"flowlink":
|
|
21
|
-
"js-yaml":
|
|
22
|
-
"@gpeng/naudiodon":
|
|
23
|
-
"@deepgram/sdk":
|
|
24
|
-
"deepl-node":
|
|
25
|
-
"@elevenlabs/elevenlabs-js":
|
|
26
|
-
"stream-transform":
|
|
27
|
-
"get-stream":
|
|
28
|
-
"@dotenvx/dotenvx":
|
|
29
|
-
"speex-resampler":
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"@
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"@
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
18
|
+
"cli-io": "0.9.13",
|
|
19
|
+
"yargs": "18.0.0",
|
|
20
|
+
"flowlink": "1.2.1",
|
|
21
|
+
"js-yaml": "4.1.0",
|
|
22
|
+
"@gpeng/naudiodon": "2.4.1",
|
|
23
|
+
"@deepgram/sdk": "4.11.2",
|
|
24
|
+
"deepl-node": "1.19.0",
|
|
25
|
+
"@elevenlabs/elevenlabs-js": "2.13.0",
|
|
26
|
+
"stream-transform": "3.4.0",
|
|
27
|
+
"get-stream": "9.0.1",
|
|
28
|
+
"@dotenvx/dotenvx": "1.49.0",
|
|
29
|
+
"speex-resampler": "3.0.1",
|
|
30
|
+
"@sapphi-red/speex-preprocess-wasm": "0.4.0",
|
|
31
|
+
"@shiguredo/rnnoise-wasm": "2025.1.5",
|
|
32
|
+
"@aws-sdk/client-transcribe-streaming": "3.879.0",
|
|
33
|
+
"@aws-sdk/client-translate": "3.879.0",
|
|
34
|
+
"@aws-sdk/client-polly": "3.879.0",
|
|
35
|
+
"node-web-audio-api": "1.0.4",
|
|
36
|
+
"object-path": "0.11.8",
|
|
37
|
+
"ws": "8.18.3",
|
|
38
|
+
"bufferutil": "4.0.9",
|
|
39
|
+
"utf-8-validate": "6.0.5",
|
|
40
|
+
"@hapi/hapi": "21.4.3",
|
|
41
|
+
"@hapi/boom": "10.0.1",
|
|
42
|
+
"@hapi/inert": "7.1.0",
|
|
43
|
+
"hapi-plugin-header": "1.1.8",
|
|
44
|
+
"hapi-plugin-websocket": "2.4.11",
|
|
45
|
+
"@opensumi/reconnecting-websocket": "4.4.0",
|
|
46
|
+
"ollama": "0.5.17",
|
|
47
|
+
"openai": "5.16.0",
|
|
48
|
+
"@rse/ffmpeg": "1.4.2",
|
|
49
|
+
"ffmpeg-stream": "1.0.1",
|
|
50
|
+
"installed-packages": "1.0.13",
|
|
51
|
+
"syspath": "1.0.8",
|
|
52
|
+
"wav": "1.0.2",
|
|
53
|
+
"mqtt": "5.14.0",
|
|
54
|
+
"cbor2": "2.0.1",
|
|
55
|
+
"arktype": "2.1.20",
|
|
56
|
+
"pure-uuid": "1.8.1",
|
|
57
|
+
"wavefile": "11.0.0",
|
|
58
|
+
"audio-inspect": "0.0.4",
|
|
59
|
+
"@huggingface/transformers": "3.7.2",
|
|
60
|
+
"kokoro-js": "1.2.1",
|
|
61
|
+
"@ericedouard/vad-node-realtime": "0.2.0",
|
|
62
|
+
"osc-js": "2.4.1",
|
|
63
|
+
"luxon": "3.7.1",
|
|
64
|
+
"node-interval-tree": "2.1.2",
|
|
65
|
+
"wrap-text": "1.0.10",
|
|
66
|
+
"cli-table3": "0.6.5",
|
|
67
|
+
"@rse/stx": "1.0.9"
|
|
61
68
|
},
|
|
62
69
|
"devDependencies": {
|
|
63
|
-
"eslint":
|
|
64
|
-
"@eslint/js":
|
|
65
|
-
"neostandard":
|
|
66
|
-
"eslint-plugin-promise":
|
|
67
|
-
"eslint-plugin-import":
|
|
68
|
-
"eslint-plugin-node":
|
|
69
|
-
"
|
|
70
|
-
"@typescript-eslint/
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
70
|
+
"eslint": "9.34.0",
|
|
71
|
+
"@eslint/js": "9.34.0",
|
|
72
|
+
"neostandard": "0.12.2",
|
|
73
|
+
"eslint-plugin-promise": "7.2.1",
|
|
74
|
+
"eslint-plugin-import": "2.32.0",
|
|
75
|
+
"eslint-plugin-node": "11.1.0",
|
|
76
|
+
"typescript-eslint": "8.41.0",
|
|
77
|
+
"@typescript-eslint/eslint-plugin": "8.41.0",
|
|
78
|
+
"@typescript-eslint/parser": "8.41.0",
|
|
79
|
+
"oxlint": "1.14.0",
|
|
80
|
+
"eslint-plugin-oxlint": "1.14.0",
|
|
81
|
+
"@biomejs/biome": "2.0.6",
|
|
82
|
+
"eslint-config-biome": "2.1.3",
|
|
75
83
|
|
|
76
|
-
"@types/node":
|
|
77
|
-
"@types/yargs":
|
|
78
|
-
"@types/js-yaml":
|
|
79
|
-
"@types/object-path":
|
|
80
|
-
"@types/ws":
|
|
81
|
-
"@types/resolve":
|
|
82
|
-
"@types/wav":
|
|
83
|
-
"@types/luxon":
|
|
84
|
-
"@types/wrap-text":
|
|
84
|
+
"@types/node": "24.3.0",
|
|
85
|
+
"@types/yargs": "17.0.33",
|
|
86
|
+
"@types/js-yaml": "4.0.9",
|
|
87
|
+
"@types/object-path": "0.11.4",
|
|
88
|
+
"@types/ws": "8.18.1",
|
|
89
|
+
"@types/resolve": "1.20.6",
|
|
90
|
+
"@types/wav": "1.0.4",
|
|
91
|
+
"@types/luxon": "3.7.1",
|
|
92
|
+
"@types/wrap-text": "1.0.2",
|
|
85
93
|
|
|
86
|
-
"patch-package":
|
|
87
|
-
"stmux":
|
|
88
|
-
"nodemon":
|
|
89
|
-
"shx":
|
|
90
|
-
"@yao-pkg/pkg":
|
|
91
|
-
"typescript":
|
|
92
|
-
"delay-cli":
|
|
93
|
-
"cross-env":
|
|
94
|
+
"patch-package": "8.0.0",
|
|
95
|
+
"stmux": "1.8.11",
|
|
96
|
+
"nodemon": "3.1.10",
|
|
97
|
+
"shx": "0.4.0",
|
|
98
|
+
"@yao-pkg/pkg": "6.6.0",
|
|
99
|
+
"typescript": "5.9.2",
|
|
100
|
+
"delay-cli": "2.0.0",
|
|
101
|
+
"cross-env": "10.0.0"
|
|
94
102
|
},
|
|
95
103
|
"overrides": {
|
|
96
|
-
"@huggingface/transformers":
|
|
104
|
+
"@huggingface/transformers": { "onnxruntime-node": "1.23.0-dev.20250703-7fc6235861" }
|
|
97
105
|
},
|
|
98
|
-
"upd":
|
|
106
|
+
"upd": [ "!@biomejs/biome" ],
|
|
99
107
|
"engines": {
|
|
100
|
-
"node":
|
|
108
|
+
"node": ">=22.0.0"
|
|
101
109
|
},
|
|
102
|
-
"bin":
|
|
103
|
-
"types":
|
|
104
|
-
"module":
|
|
105
|
-
"main":
|
|
110
|
+
"bin": { "speechflow": "dst/speechflow.js" },
|
|
111
|
+
"types": "./dst/speechflow-node.d.ts",
|
|
112
|
+
"module": "./dst/speechflow-node.js",
|
|
113
|
+
"main": "./dst/speechflow-node.js",
|
|
106
114
|
"exports": {
|
|
107
115
|
".": {
|
|
108
|
-
"import":
|
|
109
|
-
"require":
|
|
116
|
+
"import": { "types": "./dst/speechflow-node.d.ts", "default": "./dst/speechflow-node.js" },
|
|
117
|
+
"require": { "types": "./dst/speechflow-node.d.ts", "default": "./dst/speechflow-node.js" }
|
|
110
118
|
}
|
|
111
119
|
},
|
|
112
120
|
"scripts": {
|
|
113
|
-
"postinstall":
|
|
114
|
-
"start":
|
|
121
|
+
"postinstall": "npm start patch-apply",
|
|
122
|
+
"start": "stx -v4 -c etc/stx.conf"
|
|
115
123
|
}
|
|
116
124
|
}
|
|
@@ -9,3 +9,27 @@ declare module "node:stream" {
|
|
|
9
9
|
export function compose (...streams: Stream[]): Duplex
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/* type definitions for AudioWorkletProcessor */
|
|
13
|
+
declare interface AudioWorkletProcessor {
|
|
14
|
+
readonly port: MessagePort
|
|
15
|
+
process(
|
|
16
|
+
inputs: Float32Array[][],
|
|
17
|
+
outputs: Float32Array[][],
|
|
18
|
+
parameters: Record<string, Float32Array>
|
|
19
|
+
): boolean
|
|
20
|
+
}
|
|
21
|
+
declare const AudioWorkletProcessor: {
|
|
22
|
+
prototype: AudioWorkletProcessor
|
|
23
|
+
new(): AudioWorkletProcessor
|
|
24
|
+
}
|
|
25
|
+
declare interface AudioParamDescriptor {
|
|
26
|
+
name: string
|
|
27
|
+
defaultValue?: number
|
|
28
|
+
minValue?: number
|
|
29
|
+
maxValue?: number
|
|
30
|
+
automationRate?: "a-rate" | "k-rate"
|
|
31
|
+
}
|
|
32
|
+
declare function registerProcessor(
|
|
33
|
+
name: string,
|
|
34
|
+
processorCtor: new (...args: any[]) => AudioWorkletProcessor
|
|
35
|
+
): void
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** SpeechFlow - Speech Processing Flow Graph
|
|
3
|
+
** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
|
+
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as utils from "./speechflow-utils"
|
|
8
|
+
|
|
9
|
+
/* downward compressor with soft knee */
|
|
10
|
+
class CompressorProcessor extends AudioWorkletProcessor {
|
|
11
|
+
/* internal state */
|
|
12
|
+
private env: number[] = []
|
|
13
|
+
private sampleRate: number
|
|
14
|
+
public reduction = 0
|
|
15
|
+
|
|
16
|
+
/* eslint no-undef: off */
|
|
17
|
+
static get parameterDescriptors(): AudioParamDescriptor[] {
|
|
18
|
+
return [
|
|
19
|
+
{ name: "threshold", defaultValue: -23, minValue: -100, maxValue: 0, automationRate: "k-rate" }, // dBFS
|
|
20
|
+
{ name: "ratio", defaultValue: 4.0, minValue: 1.0, maxValue: 20, automationRate: "k-rate" }, // compression ratio
|
|
21
|
+
{ name: "attack", defaultValue: 0.010, minValue: 0.0, maxValue: 1, automationRate: "k-rate" }, // seconds
|
|
22
|
+
{ name: "release", defaultValue: 0.050, minValue: 0.0, maxValue: 1, automationRate: "k-rate" }, // seconds
|
|
23
|
+
{ name: "knee", defaultValue: 6.0, minValue: 0.0, maxValue: 40, automationRate: "k-rate" }, // dB
|
|
24
|
+
{ name: "makeup", defaultValue: 0.0, minValue: -24, maxValue: 24, automationRate: "k-rate" } // dB
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* class constructor for custom option processing */
|
|
29
|
+
constructor (options: any) {
|
|
30
|
+
super()
|
|
31
|
+
const { sampleRate } = options.processorOptions
|
|
32
|
+
this.sampleRate = sampleRate as number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* determine gain difference */
|
|
36
|
+
private gainDBFor (levelDB: number, thresholdDB: number, ratio: number, kneeDB: number): number {
|
|
37
|
+
/* short-circuit for unreasonable ratio */
|
|
38
|
+
if (ratio <= 1.0)
|
|
39
|
+
return 0
|
|
40
|
+
|
|
41
|
+
/* determine thresholds */
|
|
42
|
+
const halfKnee = kneeDB * 0.5
|
|
43
|
+
const belowThr = levelDB < thresholdDB
|
|
44
|
+
const aboveKnee = levelDB >= (thresholdDB + halfKnee)
|
|
45
|
+
|
|
46
|
+
/* short-circuit for no compression (below threshold) */
|
|
47
|
+
if (belowThr)
|
|
48
|
+
return 0
|
|
49
|
+
|
|
50
|
+
/* apply soft-knee */
|
|
51
|
+
if (kneeDB > 0 && !aboveKnee) {
|
|
52
|
+
const x = (levelDB - thresholdDB) / kneeDB
|
|
53
|
+
const idealGainDB = (thresholdDB + (levelDB - thresholdDB) / ratio) - levelDB
|
|
54
|
+
return idealGainDB * x * x
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* determine target level */
|
|
58
|
+
const targetOut = thresholdDB + (levelDB - thresholdDB) / ratio
|
|
59
|
+
|
|
60
|
+
/* return gain difference */
|
|
61
|
+
return targetOut - levelDB
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* update envelope (smoothed amplitude contour) for single channel */
|
|
65
|
+
private updateEnvelopeForChannel (
|
|
66
|
+
chan: number,
|
|
67
|
+
samples: Float32Array,
|
|
68
|
+
attack: number,
|
|
69
|
+
release: number
|
|
70
|
+
): void {
|
|
71
|
+
/* fetch old envelope value */
|
|
72
|
+
if (this.env[chan] === undefined)
|
|
73
|
+
this.env[chan] = 1e-12
|
|
74
|
+
let env = this.env[chan]
|
|
75
|
+
|
|
76
|
+
/* calculate attack/release alpha values */
|
|
77
|
+
const alphaA = Math.exp(-1 / (attack * this.sampleRate))
|
|
78
|
+
const alphaR = Math.exp(-1 / (release * this.sampleRate))
|
|
79
|
+
|
|
80
|
+
/* iterate over all samples and calculate RMS */
|
|
81
|
+
for (const s of samples) {
|
|
82
|
+
const x = Math.abs(s)
|
|
83
|
+
const det = x * x
|
|
84
|
+
if (det > env)
|
|
85
|
+
env = alphaA * env + (1 - alphaA) * det
|
|
86
|
+
else
|
|
87
|
+
env = alphaR * env + (1 - alphaR) * det
|
|
88
|
+
}
|
|
89
|
+
this.env[chan] = Math.sqrt(Math.max(env, 1e-12))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* process a single sample frame */
|
|
93
|
+
process(
|
|
94
|
+
inputs: Float32Array[][],
|
|
95
|
+
outputs: Float32Array[][],
|
|
96
|
+
parameters: Record<string, Float32Array>
|
|
97
|
+
): boolean {
|
|
98
|
+
/* sanity check */
|
|
99
|
+
const input = inputs[0]
|
|
100
|
+
const output = outputs[0]
|
|
101
|
+
if (!input || input.length === 0 || !output)
|
|
102
|
+
return true
|
|
103
|
+
|
|
104
|
+
/* determine number of channels */
|
|
105
|
+
const nCh = input.length
|
|
106
|
+
|
|
107
|
+
/* initially just copy input to output (pass-through) */
|
|
108
|
+
for (let c = 0; c < output.length; c++) {
|
|
109
|
+
if (!output[c] || !input[c])
|
|
110
|
+
continue
|
|
111
|
+
output[c].set(input[c])
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* fetch parameters */
|
|
115
|
+
const thresholdDB = parameters["threshold"][0]
|
|
116
|
+
const ratio = parameters["ratio"][0]
|
|
117
|
+
const kneeDB = parameters["knee"][0]
|
|
118
|
+
const attackS = Math.max(parameters["attack"][0], 1 / this.sampleRate)
|
|
119
|
+
const releaseS = Math.max(parameters["release"][0], 1 / this.sampleRate)
|
|
120
|
+
const makeupDB = parameters["makeup"][0]
|
|
121
|
+
|
|
122
|
+
/* update envelope per channel */
|
|
123
|
+
for (let ch = 0; ch < nCh; ch++)
|
|
124
|
+
this.updateEnvelopeForChannel(ch, input[ch], attackS, releaseS)
|
|
125
|
+
|
|
126
|
+
/* determine linear value from decibel makeup value */
|
|
127
|
+
const makeUpLin = utils.dB2lin(makeupDB)
|
|
128
|
+
|
|
129
|
+
/* iterate over all channels */
|
|
130
|
+
this.reduction = 0
|
|
131
|
+
for (let ch = 0; ch < nCh; ch++) {
|
|
132
|
+
const levelDB = utils.lin2dB(this.env[ch])
|
|
133
|
+
const gainDB = this.gainDBFor(levelDB, thresholdDB, ratio, kneeDB)
|
|
134
|
+
const gainLin = utils.dB2lin(gainDB) * makeUpLin
|
|
135
|
+
|
|
136
|
+
/* on first channel, calculate reduction */
|
|
137
|
+
if (ch === 0)
|
|
138
|
+
this.reduction = Math.min(0, gainDB)
|
|
139
|
+
|
|
140
|
+
/* apply gain change to channel */
|
|
141
|
+
const inp = input[ch]
|
|
142
|
+
const out = output[ch]
|
|
143
|
+
for (let i = 0; i < inp.length; i++)
|
|
144
|
+
out[i] = inp[i] * gainLin
|
|
145
|
+
}
|
|
146
|
+
return true
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* register the new audio nodes */
|
|
151
|
+
registerProcessor("compressor", CompressorProcessor)
|