speechflow 1.4.4 → 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 +37 -0
- package/README.md +273 -7
- package/etc/claude.md +70 -0
- package/etc/speechflow.png +0 -0
- package/etc/speechflow.yaml +29 -11
- 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 -1
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +35 -53
- 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 +16 -33
- 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 +114 -27
- 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 +37 -56
- 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 +16 -33
- 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 +118 -30
- package/speechflow-ui-db/dst/index.css +1 -1
- 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 +96 -78
- 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
|
@@ -55,7 +55,7 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
55
55
|
/* internal state */
|
|
56
56
|
emitInterval = null;
|
|
57
57
|
calcInterval = null;
|
|
58
|
-
|
|
58
|
+
silenceTimer = null;
|
|
59
59
|
chunkBuffer = new Float32Array(0);
|
|
60
60
|
destroyed = false;
|
|
61
61
|
/* construct node */
|
|
@@ -92,49 +92,32 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
92
92
|
const processChunk = (chunkData) => {
|
|
93
93
|
/* update internal audio sample sliding window */
|
|
94
94
|
const newWindow = new Float32Array(sampleWindowSize);
|
|
95
|
-
|
|
96
|
-
newWindow.set(
|
|
97
|
-
newWindow.set(chunkData, keepSize);
|
|
95
|
+
newWindow.set(sampleWindow.slice(chunkData.length), 0);
|
|
96
|
+
newWindow.set(chunkData, sampleWindowSize - chunkData.length);
|
|
98
97
|
sampleWindow = newWindow;
|
|
99
|
-
/*
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
timer = null;
|
|
123
|
-
}
|
|
124
|
-
lufss = lufs.shortTerm ? lufs.shortTerm[0] : 0;
|
|
125
|
-
rms = (0, audio_inspect_1.getRMS)(audioData, { asDB: true });
|
|
126
|
-
timer = setTimeout(() => {
|
|
127
|
-
lufss = -60;
|
|
128
|
-
rms = -60;
|
|
129
|
-
}, 500);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
if (!this.destroyed)
|
|
134
|
-
this.log("warning", `meter calculation error: ${error}`);
|
|
135
|
-
}
|
|
136
|
-
}, 0);
|
|
137
|
-
this.pendingCalculations.add(calculator);
|
|
98
|
+
/* calculate the LUFS-S and RMS metric */
|
|
99
|
+
const audioData = {
|
|
100
|
+
sampleRate: this.config.audioSampleRate,
|
|
101
|
+
numberOfChannels: this.config.audioChannels,
|
|
102
|
+
channelData: [sampleWindow],
|
|
103
|
+
duration: sampleWindowDuration,
|
|
104
|
+
length: sampleWindow.length
|
|
105
|
+
};
|
|
106
|
+
const lufs = (0, audio_inspect_1.getLUFS)(audioData, {
|
|
107
|
+
channelMode: this.config.audioChannels === 1 ? "mono" : "stereo",
|
|
108
|
+
calculateShortTerm: true,
|
|
109
|
+
calculateMomentary: false,
|
|
110
|
+
calculateLoudnessRange: false,
|
|
111
|
+
calculateTruePeak: false
|
|
112
|
+
});
|
|
113
|
+
lufss = lufs.shortTerm ? lufs.shortTerm[0] : -60;
|
|
114
|
+
rms = (0, audio_inspect_1.getRMS)(audioData, { asDB: true });
|
|
115
|
+
if (this.silenceTimer !== null)
|
|
116
|
+
clearTimeout(this.silenceTimer);
|
|
117
|
+
this.silenceTimer = setTimeout(() => {
|
|
118
|
+
lufss = -60;
|
|
119
|
+
rms = -60;
|
|
120
|
+
}, 500);
|
|
138
121
|
};
|
|
139
122
|
/* setup chunking interval */
|
|
140
123
|
this.calcInterval = setInterval(() => {
|
|
@@ -143,8 +126,8 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
143
126
|
/* process one single 50ms chunk if available */
|
|
144
127
|
if (this.chunkBuffer.length >= samplesPerChunk) {
|
|
145
128
|
const chunkData = this.chunkBuffer.slice(0, samplesPerChunk);
|
|
146
|
-
processChunk(chunkData);
|
|
147
129
|
this.chunkBuffer = this.chunkBuffer.slice(samplesPerChunk);
|
|
130
|
+
processChunk(chunkData);
|
|
148
131
|
}
|
|
149
132
|
}, chunkDuration * 1000);
|
|
150
133
|
/* setup loudness emitting interval */
|
|
@@ -155,11 +138,10 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
155
138
|
this.sendResponse(["meter", "LUFS-S", lufss]);
|
|
156
139
|
this.sendResponse(["meter", "RMS", rms]);
|
|
157
140
|
if (this.params.dashboard !== "")
|
|
158
|
-
this.
|
|
141
|
+
this.sendDashboard("audio", this.params.dashboard, "final", lufss);
|
|
159
142
|
}, this.params.interval);
|
|
160
143
|
/* provide Duplex stream and internally attach to meter */
|
|
161
144
|
const self = this;
|
|
162
|
-
let timer = null;
|
|
163
145
|
this.stream = new node_stream_1.default.Transform({
|
|
164
146
|
writableObjectMode: true,
|
|
165
147
|
readableObjectMode: true,
|
|
@@ -190,7 +172,7 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
190
172
|
callback();
|
|
191
173
|
}
|
|
192
174
|
catch (error) {
|
|
193
|
-
callback(error instanceof Error ? error : new Error("
|
|
175
|
+
callback(error instanceof Error ? error : new Error("meter processing failed"));
|
|
194
176
|
}
|
|
195
177
|
}
|
|
196
178
|
},
|
|
@@ -206,12 +188,6 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
206
188
|
}
|
|
207
189
|
/* close node */
|
|
208
190
|
async close() {
|
|
209
|
-
/* indicate destruction */
|
|
210
|
-
this.destroyed = true;
|
|
211
|
-
/* clear all pending calculations */
|
|
212
|
-
for (const timeout of this.pendingCalculations)
|
|
213
|
-
clearTimeout(timeout);
|
|
214
|
-
this.pendingCalculations.clear();
|
|
215
191
|
/* stop intervals */
|
|
216
192
|
if (this.emitInterval !== null) {
|
|
217
193
|
clearInterval(this.emitInterval);
|
|
@@ -221,11 +197,17 @@ class SpeechFlowNodeMeter extends speechflow_node_1.default {
|
|
|
221
197
|
clearInterval(this.calcInterval);
|
|
222
198
|
this.calcInterval = null;
|
|
223
199
|
}
|
|
200
|
+
if (this.silenceTimer !== null) {
|
|
201
|
+
clearTimeout(this.silenceTimer);
|
|
202
|
+
this.silenceTimer = null;
|
|
203
|
+
}
|
|
224
204
|
/* close stream */
|
|
225
205
|
if (this.stream !== null) {
|
|
226
206
|
this.stream.destroy();
|
|
227
207
|
this.stream = null;
|
|
228
208
|
}
|
|
209
|
+
/* indicate destruction */
|
|
210
|
+
this.destroyed = true;
|
|
229
211
|
}
|
|
230
212
|
}
|
|
231
213
|
exports.default = SpeechFlowNodeMeter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speechflow-node-a2a-meter.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-meter.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEF,6BAA6B;AAC7B,8DAAgC;AAEhC,6BAA6B;AAC7B,iDAA0D;AAE1D,6BAA6B;AAC7B,wEAAmE;AACnE,0DAAoE;AAEpE,0CAA0C;AAC1C,MAAqB,mBAAoB,SAAQ,yBAAc;IAC3D,kCAAkC;IAC3B,MAAM,CAAC,IAAI,GAAG,OAAO,CAAA;IAE5B,sBAAsB;IACd,YAAY,GAA0C,IAAI,CAAA;IAC1D,YAAY,GAA0C,IAAI,CAAA;IAC1D,
|
|
1
|
+
{"version":3,"file":"speechflow-node-a2a-meter.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-meter.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,7 +34,8 @@ class SpeechFlowNodeMute extends speechflow_node_1.default {
|
|
|
34
34
|
throw new Error("mute: node already destroyed");
|
|
35
35
|
try {
|
|
36
36
|
if (params.length === 2 && params[0] === "mode") {
|
|
37
|
-
if (
|
|
37
|
+
if (typeof params[1] !== "string" ||
|
|
38
|
+
!params[1].match(/^(?:none|silenced|unplugged)$/))
|
|
38
39
|
throw new Error("mute: invalid mode argument in external request");
|
|
39
40
|
const muteMode = params[1];
|
|
40
41
|
this.setMuteMode(muteMode);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speechflow-node-a2a-mute.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-mute.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;;;;AAEF,6BAA6B;AAC7B,8DAAgC;AAEhC,6BAA6B;AAC7B,wEAAmE;AAQnE,4DAA4D;AAC5D,MAAqB,kBAAmB,SAAQ,yBAAc;IAC1D,kCAAkC;IAC3B,MAAM,CAAC,IAAI,GAAG,MAAM,CAAA;IAE3B,sBAAsB;IACd,QAAQ,GAAa,MAAM,CAAA;IAC3B,SAAS,GAAG,KAAK,CAAA;IAEzB,sBAAsB;IACtB,YAAa,EAAU,EAAE,GAA4B,EAAE,IAA6B,EAAE,IAAW;QAC7F,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAE1B,6CAA6C;QAC7C,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;QAElB,wCAAwC;QACxC,IAAI,CAAC,KAAK,GAAI,OAAO,CAAA;QACrB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAA;IACzB,CAAC;IAED,gCAAgC;IAChC,KAAK,CAAC,cAAc,CAAE,MAAa;QAC/B,IAAI,IAAI,CAAC,SAAS;YACd,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAA;QACnD,IAAI,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;gBAC9C,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,+BAA+B,CAAC;oBACjD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;gBACtE,MAAM,QAAQ,
|
|
1
|
+
{"version":3,"file":"speechflow-node-a2a-mute.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-mute.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
** SpeechFlow - Speech Processing Flow Graph
|
|
4
|
+
** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
5
|
+
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
/* internal dependencies */
|
|
9
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
10
|
+
/* external dependencies */
|
|
11
|
+
const rnnoise_wasm_1 = require("@shiguredo/rnnoise-wasm");
|
|
12
|
+
/* WASM state */
|
|
13
|
+
let rnnoise;
|
|
14
|
+
let denoiseState;
|
|
15
|
+
(async () => {
|
|
16
|
+
try {
|
|
17
|
+
rnnoise = await rnnoise_wasm_1.Rnnoise.load();
|
|
18
|
+
denoiseState = rnnoise.createDenoiseState();
|
|
19
|
+
node_worker_threads_1.parentPort.postMessage({ type: "ready" });
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
node_worker_threads_1.parentPort.postMessage({ type: "failed", message: `failed to initialize RNNoise: ${err}` });
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
/* receive messages */
|
|
27
|
+
node_worker_threads_1.parentPort.on("message", (msg) => {
|
|
28
|
+
if (msg.type === "process") {
|
|
29
|
+
/* process a single audio frame */
|
|
30
|
+
const { id, data } = msg;
|
|
31
|
+
/* convert regular Int16Array [-32768,32768]
|
|
32
|
+
to unusual non-normalized Float32Array [-32768,32768]
|
|
33
|
+
as required by RNNoise */
|
|
34
|
+
const f32a = new Float32Array(data.length);
|
|
35
|
+
for (let i = 0; i < data.length; i++)
|
|
36
|
+
f32a[i] = data[i];
|
|
37
|
+
/* process frame with RNNoise WASM */
|
|
38
|
+
denoiseState.processFrame(f32a);
|
|
39
|
+
/* convert back Float32Array to Int16Array */
|
|
40
|
+
const i16 = new Int16Array(data.length);
|
|
41
|
+
for (let i = 0; i < data.length; i++)
|
|
42
|
+
i16[i] = Math.round(f32a[i]);
|
|
43
|
+
node_worker_threads_1.parentPort.postMessage({ type: "process-done", id, data: i16 }, [i16.buffer]);
|
|
44
|
+
}
|
|
45
|
+
else if (msg.type === "close") {
|
|
46
|
+
/* shutdown this process */
|
|
47
|
+
try {
|
|
48
|
+
denoiseState.destroy();
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
process.exit(0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=speechflow-node-a2a-rnnoise-wt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speechflow-node-a2a-rnnoise-wt.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-rnnoise-wt.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;AAEF,6BAA6B;AAC7B,6DAAgD;AAEhD,6BAA6B;AAC7B,0DAAoE;AAEpE,kBAAkB;AAClB,IAAI,OAAgB,CAAA;AACpB,IAAI,YAA0B,CAG7B;AAAA,CAAC,KAAK,IAAI,EAAE;IACT,IAAI,CAAC;QACD,OAAO,GAAG,MAAM,sBAAO,CAAC,IAAI,EAAE,CAAA;QAC9B,YAAY,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAA;QAC3C,gCAAW,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,GAAG,EAAE,CAAC;QACT,gCAAW,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,iCAAiC,GAAG,EAAE,EAAE,CAAC,CAAA;QAC5F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACnB,CAAC;AACL,CAAC,CAAC,EAAE,CAAA;AAEJ,wBAAwB;AACxB,gCAAW,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;IAC9B,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACzB,oCAAoC;QACpC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,GAAG,CAAA;QAExB;;sCAE8B;QAC9B,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;YAChC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QAErB,uCAAuC;QACvC,YAAY,CAAC,YAAY,CAAC,IAAI,CAAC,CAAA;QAE/B,+CAA+C;QAC/C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;YAChC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;QAEhC,gCAAW,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,CAAE,GAAG,CAAC,MAAM,CAAE,CAAC,CAAA;IACpF,CAAC;SACI,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,6BAA6B;QAC7B,IAAI,CAAC;YACD,YAAY,CAAC,OAAO,EAAE,CAAA;QAC1B,CAAC;gBACO,CAAC;YACL,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACnB,CAAC;IACL,CAAC;AACL,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import SpeechFlowNode from "./speechflow-node";
|
|
2
|
+
export default class SpeechFlowNodeRNNoise extends SpeechFlowNode {
|
|
3
|
+
static name: string;
|
|
4
|
+
private destroyed;
|
|
5
|
+
private sampleSize;
|
|
6
|
+
private worker;
|
|
7
|
+
constructor(id: string, cfg: {
|
|
8
|
+
[id: string]: any;
|
|
9
|
+
}, opts: {
|
|
10
|
+
[id: string]: any;
|
|
11
|
+
}, args: any[]);
|
|
12
|
+
open(): Promise<void>;
|
|
13
|
+
close(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
** SpeechFlow - Speech Processing Flow Graph
|
|
4
|
+
** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
5
|
+
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
/* standard dependencies */
|
|
45
|
+
const node_stream_1 = __importDefault(require("node:stream"));
|
|
46
|
+
const node_worker_threads_1 = require("node:worker_threads");
|
|
47
|
+
const node_path_1 = require("node:path");
|
|
48
|
+
/* internal dependencies */
|
|
49
|
+
const speechflow_node_1 = __importDefault(require("./speechflow-node"));
|
|
50
|
+
const utils = __importStar(require("./speechflow-utils"));
|
|
51
|
+
/* SpeechFlow node for RNNoise based noise suppression in audio-to-audio passing */
|
|
52
|
+
class SpeechFlowNodeRNNoise extends speechflow_node_1.default {
|
|
53
|
+
/* declare official node name */
|
|
54
|
+
static name = "rnnoise";
|
|
55
|
+
/* internal state */
|
|
56
|
+
destroyed = false;
|
|
57
|
+
sampleSize = 480; /* = 10ms at 48KHz, as required by RNNoise! */
|
|
58
|
+
worker = null;
|
|
59
|
+
/* construct node */
|
|
60
|
+
constructor(id, cfg, opts, args) {
|
|
61
|
+
super(id, cfg, opts, args);
|
|
62
|
+
/* declare node configuration parameters */
|
|
63
|
+
this.configure({});
|
|
64
|
+
/* declare node input/output format */
|
|
65
|
+
this.input = "audio";
|
|
66
|
+
this.output = "audio";
|
|
67
|
+
}
|
|
68
|
+
/* open node */
|
|
69
|
+
async open() {
|
|
70
|
+
/* clear destruction flag */
|
|
71
|
+
this.destroyed = false;
|
|
72
|
+
/* initialize worker */
|
|
73
|
+
this.worker = new node_worker_threads_1.Worker((0, node_path_1.resolve)(__dirname, "speechflow-node-a2a-rnnoise-wt.js"));
|
|
74
|
+
this.worker.on("error", (err) => {
|
|
75
|
+
this.log("error", `RNNoise worker thread error: ${err}`);
|
|
76
|
+
});
|
|
77
|
+
this.worker.on("exit", (code) => {
|
|
78
|
+
if (code !== 0)
|
|
79
|
+
this.log("error", `RNNoise worker thread exited with error code ${code}`);
|
|
80
|
+
else
|
|
81
|
+
this.log("info", `RNNoise worker thread exited with regular code ${code}`);
|
|
82
|
+
});
|
|
83
|
+
await new Promise((resolve, reject) => {
|
|
84
|
+
const timeout = setTimeout(() => {
|
|
85
|
+
reject(new Error("RNNoise worker thread initialization timeout"));
|
|
86
|
+
}, 5000);
|
|
87
|
+
this.worker.once("message", (msg) => {
|
|
88
|
+
clearTimeout(timeout);
|
|
89
|
+
if (typeof msg === "object" && msg !== null && msg.type === "ready")
|
|
90
|
+
resolve();
|
|
91
|
+
else if (typeof msg === "object" && msg !== null && msg.type === "failed")
|
|
92
|
+
reject(new Error(msg.message ?? "RNNoise worker thread initialization failed"));
|
|
93
|
+
else
|
|
94
|
+
reject(new Error(`RNNoise worker thread sent unexpected message on startup`));
|
|
95
|
+
});
|
|
96
|
+
this.worker.once("error", (err) => {
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
reject(err);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
/* receive message from worker */
|
|
102
|
+
const pending = new Map();
|
|
103
|
+
this.worker.on("message", (msg) => {
|
|
104
|
+
if (typeof msg === "object" && msg !== null && msg.type === "process-done") {
|
|
105
|
+
const cb = pending.get(msg.id);
|
|
106
|
+
pending.delete(msg.id);
|
|
107
|
+
if (cb)
|
|
108
|
+
cb(msg.data);
|
|
109
|
+
else
|
|
110
|
+
this.log("warning", `RNNoise worker thread sent back unexpected id: ${msg.id}`);
|
|
111
|
+
}
|
|
112
|
+
else
|
|
113
|
+
this.log("warning", `RNNoise worker thread sent unexpected message: ${JSON.stringify(msg)}`);
|
|
114
|
+
});
|
|
115
|
+
/* send message to worker */
|
|
116
|
+
let seq = 0;
|
|
117
|
+
const workerProcessSegment = async (segment) => {
|
|
118
|
+
if (this.destroyed)
|
|
119
|
+
return segment;
|
|
120
|
+
const id = `${seq++}`;
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
pending.set(id, (segment) => { resolve(segment); });
|
|
123
|
+
this.worker.postMessage({ type: "process", id, data: segment }, [segment.buffer]);
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
/* establish a transform stream */
|
|
127
|
+
const self = this;
|
|
128
|
+
this.stream = new node_stream_1.default.Transform({
|
|
129
|
+
readableObjectMode: true,
|
|
130
|
+
writableObjectMode: true,
|
|
131
|
+
decodeStrings: false,
|
|
132
|
+
transform(chunk, encoding, callback) {
|
|
133
|
+
if (self.destroyed) {
|
|
134
|
+
callback(new Error("stream already destroyed"));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!Buffer.isBuffer(chunk.payload))
|
|
138
|
+
callback(new Error("invalid chunk payload type"));
|
|
139
|
+
else {
|
|
140
|
+
/* convert Buffer into Int16Array */
|
|
141
|
+
const payload = utils.convertBufToI16(chunk.payload);
|
|
142
|
+
/* process Int16Array in necessary segments */
|
|
143
|
+
utils.processInt16ArrayInSegments(payload, self.sampleSize, (segment) => workerProcessSegment(segment)).then((payload) => {
|
|
144
|
+
/* convert Int16Array into Buffer */
|
|
145
|
+
const buf = utils.convertI16ToBuf(payload);
|
|
146
|
+
/* update chunk */
|
|
147
|
+
chunk.payload = buf;
|
|
148
|
+
/* forward updated chunk */
|
|
149
|
+
this.push(chunk);
|
|
150
|
+
callback();
|
|
151
|
+
}).catch((err) => {
|
|
152
|
+
self.log("warning", `processing of chunk failed: ${err}`);
|
|
153
|
+
callback(err);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
final(callback) {
|
|
158
|
+
if (self.destroyed) {
|
|
159
|
+
callback();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
this.push(null);
|
|
163
|
+
callback();
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/* close node */
|
|
168
|
+
async close() {
|
|
169
|
+
/* indicate destruction */
|
|
170
|
+
this.destroyed = true;
|
|
171
|
+
/* shutdown worker */
|
|
172
|
+
if (this.worker !== null) {
|
|
173
|
+
this.worker.terminate();
|
|
174
|
+
this.worker = null;
|
|
175
|
+
}
|
|
176
|
+
/* close stream */
|
|
177
|
+
if (this.stream !== null) {
|
|
178
|
+
this.stream.destroy();
|
|
179
|
+
this.stream = null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.default = SpeechFlowNodeRNNoise;
|
|
184
|
+
//# sourceMappingURL=speechflow-node-a2a-rnnoise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speechflow-node-a2a-rnnoise.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-rnnoise.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import SpeechFlowNode from "./speechflow-node";
|
|
2
|
+
export default class SpeechFlowNodeSpeex extends SpeechFlowNode {
|
|
3
|
+
static name: string;
|
|
4
|
+
private destroyed;
|
|
5
|
+
private sampleSize;
|
|
6
|
+
private speexProcessor;
|
|
7
|
+
constructor(id: string, cfg: {
|
|
8
|
+
[id: string]: any;
|
|
9
|
+
}, opts: {
|
|
10
|
+
[id: string]: any;
|
|
11
|
+
}, args: any[]);
|
|
12
|
+
open(): Promise<void>;
|
|
13
|
+
close(): Promise<void>;
|
|
14
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
** SpeechFlow - Speech Processing Flow Graph
|
|
4
|
+
** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
5
|
+
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
/* standard dependencies */
|
|
45
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
46
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
47
|
+
const node_stream_1 = __importDefault(require("node:stream"));
|
|
48
|
+
/* external dependencies */
|
|
49
|
+
const speex_preprocess_wasm_1 = require("@sapphi-red/speex-preprocess-wasm");
|
|
50
|
+
/* internal dependencies */
|
|
51
|
+
const speechflow_node_1 = __importDefault(require("./speechflow-node"));
|
|
52
|
+
const utils = __importStar(require("./speechflow-utils"));
|
|
53
|
+
/* SpeechFlow node for Speex based noise suppression in audio-to-audio passing */
|
|
54
|
+
class SpeechFlowNodeSpeex extends speechflow_node_1.default {
|
|
55
|
+
/* declare official node name */
|
|
56
|
+
static name = "speex";
|
|
57
|
+
/* internal state */
|
|
58
|
+
destroyed = false;
|
|
59
|
+
sampleSize = 480; /* = 10ms at 48KHz */
|
|
60
|
+
speexProcessor = null;
|
|
61
|
+
/* construct node */
|
|
62
|
+
constructor(id, cfg, opts, args) {
|
|
63
|
+
super(id, cfg, opts, args);
|
|
64
|
+
/* declare node configuration parameters */
|
|
65
|
+
this.configure({
|
|
66
|
+
attenuate: { type: "number", val: -18, pos: 0, match: (n) => n >= -60 && n <= 0 },
|
|
67
|
+
});
|
|
68
|
+
/* declare node input/output format */
|
|
69
|
+
this.input = "audio";
|
|
70
|
+
this.output = "audio";
|
|
71
|
+
}
|
|
72
|
+
/* open node */
|
|
73
|
+
async open() {
|
|
74
|
+
/* clear destruction flag */
|
|
75
|
+
this.destroyed = false;
|
|
76
|
+
/* validate sample rate compatibility */
|
|
77
|
+
if (this.config.audioSampleRate !== 48000)
|
|
78
|
+
throw new Error(`Speex node requires 48KHz sample rate, got ${this.config.audioSampleRate}Hz`);
|
|
79
|
+
/* initialize and configure Speex pre-processor */
|
|
80
|
+
const wasmBinary = await node_fs_1.default.promises.readFile(node_path_1.default.join(__dirname, "../node_modules/@sapphi-red/speex-preprocess-wasm/dist/speex.wasm"));
|
|
81
|
+
const speexModule = await (0, speex_preprocess_wasm_1.loadSpeexModule)({
|
|
82
|
+
wasmBinary: wasmBinary.buffer
|
|
83
|
+
});
|
|
84
|
+
this.speexProcessor = new speex_preprocess_wasm_1.SpeexPreprocessor(speexModule, this.sampleSize, this.config.audioSampleRate);
|
|
85
|
+
this.speexProcessor.denoise = true;
|
|
86
|
+
this.speexProcessor.noiseSuppress = this.params.attenuate;
|
|
87
|
+
this.speexProcessor.agc = false;
|
|
88
|
+
this.speexProcessor.vad = false;
|
|
89
|
+
this.speexProcessor.echoSuppress = 0;
|
|
90
|
+
this.speexProcessor.echoSuppressActive = 0;
|
|
91
|
+
/* establish a transform stream */
|
|
92
|
+
const self = this;
|
|
93
|
+
this.stream = new node_stream_1.default.Transform({
|
|
94
|
+
readableObjectMode: true,
|
|
95
|
+
writableObjectMode: true,
|
|
96
|
+
decodeStrings: false,
|
|
97
|
+
transform(chunk, encoding, callback) {
|
|
98
|
+
if (self.destroyed) {
|
|
99
|
+
callback(new Error("stream already destroyed"));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!Buffer.isBuffer(chunk.payload))
|
|
103
|
+
callback(new Error("invalid chunk payload type"));
|
|
104
|
+
else {
|
|
105
|
+
/* convert Buffer into Int16Array */
|
|
106
|
+
const payload = utils.convertBufToI16(chunk.payload);
|
|
107
|
+
/* process Int16Array in necessary fixed-size segments */
|
|
108
|
+
utils.processInt16ArrayInSegments(payload, self.sampleSize, (segment) => {
|
|
109
|
+
if (self.destroyed)
|
|
110
|
+
throw new Error("stream already destroyed");
|
|
111
|
+
self.speexProcessor?.processInt16(segment);
|
|
112
|
+
return Promise.resolve(segment);
|
|
113
|
+
}).then((payload) => {
|
|
114
|
+
if (self.destroyed)
|
|
115
|
+
throw new Error("stream already destroyed");
|
|
116
|
+
/* convert Int16Array back into Buffer */
|
|
117
|
+
const buf = utils.convertI16ToBuf(payload);
|
|
118
|
+
/* update chunk */
|
|
119
|
+
chunk.payload = buf;
|
|
120
|
+
/* forward updated chunk */
|
|
121
|
+
this.push(chunk);
|
|
122
|
+
callback();
|
|
123
|
+
}).catch((err) => {
|
|
124
|
+
self.log("warning", `processing of chunk failed: ${err}`);
|
|
125
|
+
callback(err);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
final(callback) {
|
|
130
|
+
if (self.destroyed) {
|
|
131
|
+
callback();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.push(null);
|
|
135
|
+
callback();
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
/* close node */
|
|
140
|
+
async close() {
|
|
141
|
+
/* indicate destruction */
|
|
142
|
+
this.destroyed = true;
|
|
143
|
+
/* destroy processor */
|
|
144
|
+
if (this.speexProcessor !== null) {
|
|
145
|
+
this.speexProcessor.destroy();
|
|
146
|
+
this.speexProcessor = null;
|
|
147
|
+
}
|
|
148
|
+
/* close stream */
|
|
149
|
+
if (this.stream !== null) {
|
|
150
|
+
this.stream.destroy();
|
|
151
|
+
this.stream = null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
exports.default = SpeechFlowNodeSpeex;
|
|
156
|
+
//# sourceMappingURL=speechflow-node-a2a-speex.js.map
|