speechflow 1.6.4 → 1.6.5
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 +10 -0
- package/README.md +5 -3
- package/etc/speechflow.yaml +15 -13
- package/package.json +5 -5
- package/speechflow-cli/dst/speechflow-main-api.js +3 -7
- package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-graph.js +1 -1
- package/speechflow-cli/dst/speechflow-main.js +6 -0
- package/speechflow-cli/dst/speechflow-main.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +1 -21
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +1 -21
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js +2 -2
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js +35 -29
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +50 -34
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js +2 -2
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openai.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js +0 -6
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js +0 -6
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +0 -6
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +0 -6
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +6 -6
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-device.js +3 -2
- package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-audio.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-util-audio.js +21 -0
- package/speechflow-cli/dst/speechflow-util-audio.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-error.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-util-error.js +7 -1
- package/speechflow-cli/dst/speechflow-util-error.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.js +2 -2
- package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -1
- package/speechflow-cli/etc/oxlint.jsonc +2 -1
- package/speechflow-cli/package.json +17 -17
- package/speechflow-cli/src/speechflow-main-api.ts +6 -13
- package/speechflow-cli/src/speechflow-main-graph.ts +1 -1
- package/speechflow-cli/src/speechflow-main.ts +4 -0
- package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +1 -29
- package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +1 -29
- package/speechflow-cli/src/speechflow-node-a2a-ffmpeg.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2a-gender.ts +44 -39
- package/speechflow-cli/src/speechflow-node-a2a-meter.ts +58 -38
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +1 -0
- package/speechflow-cli/src/speechflow-node-a2a-vad.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2t-openai.ts +0 -6
- package/speechflow-cli/src/speechflow-node-t2a-amazon.ts +0 -6
- package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +0 -6
- package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +0 -6
- package/speechflow-cli/src/speechflow-node-t2t-ollama.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +10 -14
- package/speechflow-cli/src/speechflow-node-xio-device.ts +3 -2
- package/speechflow-cli/src/speechflow-node-xio-websocket.ts +1 -1
- package/speechflow-cli/src/speechflow-util-audio.ts +30 -0
- package/speechflow-cli/src/speechflow-util-error.ts +9 -3
- package/speechflow-cli/src/speechflow-util-stream.ts +2 -2
- package/speechflow-ui-db/dst/index.js +20 -20
- package/speechflow-ui-db/package.json +8 -8
- package/speechflow-ui-db/src/app.vue +14 -5
- package/speechflow-ui-st/dst/index.js +455 -20
- package/speechflow-ui-st/package.json +9 -9
- package/speechflow-ui-st/src/app.vue +8 -3
- package/speechflow-cli/dst/speechflow-util-webaudio-wt.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-util-webaudio-wt.js +0 -124
- package/speechflow-cli/dst/speechflow-util-webaudio-wt.js.map +0 -1
- package/speechflow-cli/dst/speechflow-util-webaudio.d.ts +0 -13
- package/speechflow-cli/dst/speechflow-util-webaudio.js +0 -137
- package/speechflow-cli/dst/speechflow-util-webaudio.js.map +0 -1
|
@@ -15,21 +15,21 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"vue": "3.5.21",
|
|
18
|
-
"vue3-spinners": "1.3.
|
|
18
|
+
"vue3-spinners": "1.3.3",
|
|
19
19
|
"luxon": "3.7.2",
|
|
20
20
|
"@opensumi/reconnecting-websocket": "4.4.0",
|
|
21
|
-
"axios": "1.12.
|
|
21
|
+
"axios": "1.12.2",
|
|
22
22
|
"typopro-web": "4.2.7",
|
|
23
23
|
"@fortawesome/fontawesome-free": "7.0.1",
|
|
24
24
|
"patch-package": "8.0.0",
|
|
25
|
-
"@rse/stx": "1.1.
|
|
25
|
+
"@rse/stx": "1.1.2",
|
|
26
26
|
"animejs": "4.1.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"vite": "7.1.
|
|
30
|
-
"typescript-eslint": "8.
|
|
31
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
32
|
-
"@typescript-eslint/parser": "8.
|
|
29
|
+
"vite": "7.1.6",
|
|
30
|
+
"typescript-eslint": "8.44.0",
|
|
31
|
+
"@typescript-eslint/eslint-plugin": "8.44.0",
|
|
32
|
+
"@typescript-eslint/parser": "8.44.0",
|
|
33
33
|
"@vitejs/plugin-vue": "6.0.1",
|
|
34
34
|
"@rollup/plugin-yaml": "4.1.2",
|
|
35
35
|
"vite-plugin-node-polyfills": "0.24.0",
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
|
|
40
40
|
"@vue/eslint-config-typescript": "14.6.0",
|
|
41
41
|
"vue-eslint-parser": "10.2.0",
|
|
42
|
-
"eslint": "9.
|
|
43
|
-
"@eslint/js": "9.
|
|
42
|
+
"eslint": "9.36.0",
|
|
43
|
+
"@eslint/js": "9.36.0",
|
|
44
44
|
"neostandard": "0.12.2",
|
|
45
45
|
"eslint-plugin-import": "2.32.0",
|
|
46
46
|
"eslint-plugin-vue": "10.4.0",
|
|
@@ -117,8 +117,10 @@ export default defineComponent({
|
|
|
117
117
|
cleanupIntervalId: null as ReturnType<typeof setInterval> | null
|
|
118
118
|
}),
|
|
119
119
|
async mounted () {
|
|
120
|
-
/* determine API
|
|
121
|
-
const
|
|
120
|
+
/* determine API URLs */
|
|
121
|
+
const urlHTTP = new URL("/api", document.location.href)
|
|
122
|
+
const urlWS = new URL("/api", document.location.href)
|
|
123
|
+
urlWS.protocol = (urlHTTP.protocol === "https:" ? "wss:" : "ws:")
|
|
122
124
|
|
|
123
125
|
/* optically remove outdated text chunks */
|
|
124
126
|
this.cleanupIntervalId = setInterval(() => {
|
|
@@ -146,13 +148,16 @@ export default defineComponent({
|
|
|
146
148
|
}, 500)
|
|
147
149
|
|
|
148
150
|
/* connect to WebSocket API for receiving dashboard information */
|
|
149
|
-
const ws = new ReconnectingWebSocket(
|
|
151
|
+
const ws = new ReconnectingWebSocket(urlWS.toString(), [], {
|
|
150
152
|
reconnectionDelayGrowFactor: 1.3,
|
|
151
153
|
maxReconnectionDelay: 4000,
|
|
152
154
|
minReconnectionDelay: 1000,
|
|
153
155
|
connectionTimeout: 4000,
|
|
154
156
|
minUptime: 5000
|
|
155
157
|
})
|
|
158
|
+
ws.addEventListener("error", (ev) => {
|
|
159
|
+
this.log("ERROR", `WebSocket error: ${ev.message}`)
|
|
160
|
+
})
|
|
156
161
|
|
|
157
162
|
/* track connection open/close */
|
|
158
163
|
ws.addEventListener("open", (ev) => {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,124 +0,0 @@
|
|
|
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
|
-
/* audio source node */
|
|
9
|
-
class AudioSourceProcessor extends AudioWorkletProcessor {
|
|
10
|
-
/* internal state */
|
|
11
|
-
pendingData = [];
|
|
12
|
-
currentChunk = null;
|
|
13
|
-
currentOffset = 0;
|
|
14
|
-
/* node construction */
|
|
15
|
-
constructor() {
|
|
16
|
-
super();
|
|
17
|
-
/* receive input chunks */
|
|
18
|
-
this.port.addEventListener("message", (event) => {
|
|
19
|
-
const { type, chunkId } = event.data;
|
|
20
|
-
if (type === "input-chunk")
|
|
21
|
-
this.pendingData.push({ data: event.data.data.pcmData, chunkId });
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
/* process audio frame */
|
|
25
|
-
process(inputs, /* unused */ outputs, parameters /* unused */) {
|
|
26
|
-
/* determine output */
|
|
27
|
-
const output = outputs[0];
|
|
28
|
-
if (!output || output.length === 0)
|
|
29
|
-
return true;
|
|
30
|
-
const frameCount = output[0].length;
|
|
31
|
-
const channelCount = output.length;
|
|
32
|
-
/* get current chunk if we don't have one */
|
|
33
|
-
if (this.currentChunk === null && this.pendingData.length > 0) {
|
|
34
|
-
this.currentChunk = this.pendingData.shift();
|
|
35
|
-
this.currentOffset = 0;
|
|
36
|
-
/* signal chunk start */
|
|
37
|
-
const message = {
|
|
38
|
-
type: "chunk-started",
|
|
39
|
-
chunkId: this.currentChunk.chunkId
|
|
40
|
-
};
|
|
41
|
-
this.port.postMessage(message);
|
|
42
|
-
}
|
|
43
|
-
/* process input */
|
|
44
|
-
if (this.currentChunk) {
|
|
45
|
-
/* output current chunk */
|
|
46
|
-
const samplesPerChannel = this.currentChunk.data.length / channelCount;
|
|
47
|
-
const remainingFrames = samplesPerChannel - this.currentOffset;
|
|
48
|
-
const framesToProcess = Math.min(frameCount, remainingFrames);
|
|
49
|
-
/* copy data from current chunk (interleaved to planar) */
|
|
50
|
-
for (let frame = 0; frame < framesToProcess; frame++) {
|
|
51
|
-
for (let ch = 0; ch < channelCount; ch++) {
|
|
52
|
-
const interleavedIndex = (this.currentOffset + frame) * channelCount + ch;
|
|
53
|
-
output[ch][frame] = this.currentChunk.data[interleavedIndex] ?? 0;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/* zero-pad remaining output if needed */
|
|
57
|
-
for (let frame = framesToProcess; frame < frameCount; frame++)
|
|
58
|
-
for (let ch = 0; ch < channelCount; ch++)
|
|
59
|
-
output[ch][frame] = 0;
|
|
60
|
-
/* check if current chunk is finished */
|
|
61
|
-
this.currentOffset += framesToProcess;
|
|
62
|
-
if (this.currentOffset >= samplesPerChannel) {
|
|
63
|
-
this.currentChunk = null;
|
|
64
|
-
this.currentOffset = 0;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
/* output silence when no input */
|
|
69
|
-
for (let ch = 0; ch < channelCount; ch++)
|
|
70
|
-
output[ch].fill(0);
|
|
71
|
-
}
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
/* audio capture node */
|
|
76
|
-
class AudioCaptureProcessor extends AudioWorkletProcessor {
|
|
77
|
-
/* internal state */
|
|
78
|
-
activeCaptures = new Map();
|
|
79
|
-
/* node construction */
|
|
80
|
-
constructor() {
|
|
81
|
-
super();
|
|
82
|
-
/* receive start of capturing command */
|
|
83
|
-
this.port.addEventListener("message", (event) => {
|
|
84
|
-
const { type, chunkId } = event.data;
|
|
85
|
-
if (type === "start-capture") {
|
|
86
|
-
this.activeCaptures.set(chunkId, {
|
|
87
|
-
data: [],
|
|
88
|
-
expectedSamples: event.data.expectedSamples
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
/* process audio frame */
|
|
94
|
-
process(inputs, outputs, /* unused */ parameters /* unused */) {
|
|
95
|
-
/* determine input */
|
|
96
|
-
const input = inputs[0];
|
|
97
|
-
if (!input || input.length === 0 || this.activeCaptures.size === 0)
|
|
98
|
-
return true;
|
|
99
|
-
const frameCount = input[0].length;
|
|
100
|
-
const channelCount = input.length;
|
|
101
|
-
/* iterate over all active captures */
|
|
102
|
-
for (const [chunkId, capture] of this.activeCaptures) {
|
|
103
|
-
/* convert planar to interleaved */
|
|
104
|
-
for (let frame = 0; frame < frameCount; frame++)
|
|
105
|
-
for (let ch = 0; ch < channelCount; ch++)
|
|
106
|
-
capture.data.push(input[ch][frame]);
|
|
107
|
-
/* send back captured data */
|
|
108
|
-
if (capture.data.length >= capture.expectedSamples) {
|
|
109
|
-
const message = {
|
|
110
|
-
type: "capture-complete",
|
|
111
|
-
chunkId,
|
|
112
|
-
data: capture.data.slice(0, capture.expectedSamples)
|
|
113
|
-
};
|
|
114
|
-
this.port.postMessage(message);
|
|
115
|
-
this.activeCaptures.delete(chunkId);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/* register the new audio nodes */
|
|
122
|
-
registerProcessor("source", AudioSourceProcessor);
|
|
123
|
-
registerProcessor("capture", AudioCaptureProcessor);
|
|
124
|
-
//# sourceMappingURL=speechflow-util-webaudio-wt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"speechflow-util-webaudio-wt.js","sourceRoot":"","sources":["../src/speechflow-util-webaudio-wt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { AudioContext, AudioWorkletNode } from "node-web-audio-api";
|
|
2
|
-
export declare class WebAudio {
|
|
3
|
-
sampleRate: number;
|
|
4
|
-
channels: number;
|
|
5
|
-
audioContext: AudioContext;
|
|
6
|
-
sourceNode: AudioWorkletNode | null;
|
|
7
|
-
captureNode: AudioWorkletNode | null;
|
|
8
|
-
private pendingPromises;
|
|
9
|
-
constructor(sampleRate: number, channels: number);
|
|
10
|
-
setup(): Promise<void>;
|
|
11
|
-
process(int16Array: Int16Array): Promise<Int16Array>;
|
|
12
|
-
destroy(): Promise<void>;
|
|
13
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
-
};
|
|
10
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.WebAudio = void 0;
|
|
12
|
-
/* standard dependencies */
|
|
13
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
-
/* external dependencies */
|
|
15
|
-
const node_web_audio_api_1 = require("node-web-audio-api");
|
|
16
|
-
class WebAudio {
|
|
17
|
-
sampleRate;
|
|
18
|
-
channels;
|
|
19
|
-
/* internal state */
|
|
20
|
-
audioContext;
|
|
21
|
-
sourceNode = null;
|
|
22
|
-
captureNode = null;
|
|
23
|
-
pendingPromises = new Map();
|
|
24
|
-
/* construct object */
|
|
25
|
-
constructor(sampleRate, channels) {
|
|
26
|
-
this.sampleRate = sampleRate;
|
|
27
|
-
this.channels = channels;
|
|
28
|
-
/* create new audio context */
|
|
29
|
-
this.audioContext = new node_web_audio_api_1.AudioContext({
|
|
30
|
-
sampleRate,
|
|
31
|
-
latencyHint: "interactive"
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
/* setup object */
|
|
35
|
-
async setup() {
|
|
36
|
-
/* ensure audio context is not suspended */
|
|
37
|
-
if (this.audioContext.state === "suspended")
|
|
38
|
-
await this.audioContext.resume();
|
|
39
|
-
/* add audio worklet module */
|
|
40
|
-
const url = node_path_1.default.resolve(__dirname, "speechflow-util-webaudio-wt.js");
|
|
41
|
-
await this.audioContext.audioWorklet.addModule(url);
|
|
42
|
-
/* create source node */
|
|
43
|
-
this.sourceNode = new node_web_audio_api_1.AudioWorkletNode(this.audioContext, "source", {
|
|
44
|
-
numberOfInputs: 0,
|
|
45
|
-
numberOfOutputs: 1,
|
|
46
|
-
outputChannelCount: [this.channels]
|
|
47
|
-
});
|
|
48
|
-
/* create capture node */
|
|
49
|
-
this.captureNode = new node_web_audio_api_1.AudioWorkletNode(this.audioContext, "capture", {
|
|
50
|
-
numberOfInputs: 1,
|
|
51
|
-
numberOfOutputs: 0
|
|
52
|
-
});
|
|
53
|
-
this.captureNode.port.addEventListener("message", (event) => {
|
|
54
|
-
const { type, chunkId, data } = event.data ?? {};
|
|
55
|
-
if (type === "capture-complete") {
|
|
56
|
-
const promise = this.pendingPromises.get(chunkId);
|
|
57
|
-
if (promise) {
|
|
58
|
-
clearTimeout(promise.timeout);
|
|
59
|
-
this.pendingPromises.delete(chunkId);
|
|
60
|
-
const int16Data = new Int16Array(data.length);
|
|
61
|
-
for (let i = 0; i < data.length; i++)
|
|
62
|
-
int16Data[i] = Math.max(-32768, Math.min(32767, Math.round(data[i] * 32767)));
|
|
63
|
-
promise.resolve(int16Data);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
/* start ports */
|
|
68
|
-
this.sourceNode.port.start();
|
|
69
|
-
this.captureNode.port.start();
|
|
70
|
-
}
|
|
71
|
-
/* process single audio chunk */
|
|
72
|
-
async process(int16Array) {
|
|
73
|
-
const chunkId = `chunk_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
74
|
-
return new Promise((resolve, reject) => {
|
|
75
|
-
const timeout = setTimeout(() => {
|
|
76
|
-
this.pendingPromises.delete(chunkId);
|
|
77
|
-
reject(new Error("processing timeout"));
|
|
78
|
-
}, (int16Array.length / this.audioContext.sampleRate) * 1000 + 250);
|
|
79
|
-
if (this.captureNode !== null)
|
|
80
|
-
this.pendingPromises.set(chunkId, { resolve, reject, timeout });
|
|
81
|
-
try {
|
|
82
|
-
const float32Data = new Float32Array(int16Array.length);
|
|
83
|
-
for (let i = 0; i < int16Array.length; i++)
|
|
84
|
-
float32Data[i] = int16Array[i] / 32768.0;
|
|
85
|
-
/* start capture first */
|
|
86
|
-
if (this.captureNode !== null) {
|
|
87
|
-
this.captureNode?.port.postMessage({
|
|
88
|
-
type: "start-capture",
|
|
89
|
-
chunkId,
|
|
90
|
-
expectedSamples: int16Array.length
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
/* small delay to ensure capture is ready before sending data */
|
|
94
|
-
setTimeout(() => {
|
|
95
|
-
/* send input to source node */
|
|
96
|
-
this.sourceNode?.port.postMessage({
|
|
97
|
-
type: "input-chunk",
|
|
98
|
-
chunkId,
|
|
99
|
-
data: { pcmData: float32Data, channels: this.channels }
|
|
100
|
-
}, [float32Data.buffer]);
|
|
101
|
-
}, 5);
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
clearTimeout(timeout);
|
|
105
|
-
if (this.captureNode !== null)
|
|
106
|
-
this.pendingPromises.delete(chunkId);
|
|
107
|
-
reject(new Error(`failed to process chunk: ${error}`));
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
async destroy() {
|
|
112
|
-
/* reject all pending promises */
|
|
113
|
-
try {
|
|
114
|
-
this.pendingPromises.forEach(({ reject, timeout }) => {
|
|
115
|
-
clearTimeout(timeout);
|
|
116
|
-
reject(new Error("WebAudio destroyed"));
|
|
117
|
-
});
|
|
118
|
-
this.pendingPromises.clear();
|
|
119
|
-
}
|
|
120
|
-
catch (_err) {
|
|
121
|
-
/* ignored - cleanup during shutdown */
|
|
122
|
-
}
|
|
123
|
-
/* disconnect nodes */
|
|
124
|
-
if (this.sourceNode !== null) {
|
|
125
|
-
this.sourceNode.disconnect();
|
|
126
|
-
this.sourceNode = null;
|
|
127
|
-
}
|
|
128
|
-
if (this.captureNode !== null) {
|
|
129
|
-
this.captureNode.disconnect();
|
|
130
|
-
this.captureNode = null;
|
|
131
|
-
}
|
|
132
|
-
/* stop context */
|
|
133
|
-
await this.audioContext.close();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
exports.WebAudio = WebAudio;
|
|
137
|
-
//# sourceMappingURL=speechflow-util-webaudio.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"speechflow-util-webaudio.js","sourceRoot":"","sources":["../src/speechflow-util-webaudio.ts"],"names":[],"mappings":"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"}
|