speechflow 1.6.3 → 1.6.4
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/.claude/settings.local.json +3 -0
- package/CHANGELOG.md +10 -0
- package/README.md +82 -45
- package/etc/speechflow.yaml +19 -14
- package/package.json +5 -5
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +2 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js +2 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js +4 -14
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +11 -8
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-trace.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js +22 -2
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js.map +1 -1
- package/speechflow-cli/etc/stx.conf +6 -10
- package/speechflow-cli/package.json +13 -13
- package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +2 -1
- package/speechflow-cli/src/speechflow-node-a2a-expander.ts +2 -1
- package/speechflow-cli/src/speechflow-node-a2a-meter.ts +11 -8
- package/speechflow-cli/src/speechflow-node-x2x-trace.ts +25 -2
- package/speechflow-ui-db/dst/index.js +24 -33
- package/speechflow-ui-db/package.json +12 -10
- package/speechflow-ui-db/src/app.vue +16 -2
- package/speechflow-ui-st/.claude/settings.local.json +3 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-BoldIt.eot +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-BoldIt.ttf +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-BoldIt.woff +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-RegularIt.eot +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-RegularIt.ttf +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-RegularIt.woff +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Semibold.eot +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Semibold.ttf +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Semibold.woff +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-SemiboldIt.eot +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-SemiboldIt.ttf +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-SemiboldIt.woff +0 -0
- package/speechflow-ui-st/dst/index.css +2 -2
- package/speechflow-ui-st/dst/index.js +26 -28
- package/speechflow-ui-st/package.json +11 -10
- package/speechflow-ui-st/src/app.vue +142 -48
- package/speechflow-ui-st/src/index.ts +4 -0
|
@@ -16,6 +16,8 @@ const speechflow_node_1 = __importDefault(require("./speechflow-node"));
|
|
|
16
16
|
class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
17
17
|
/* declare official node name */
|
|
18
18
|
static name = "x2x-trace";
|
|
19
|
+
/* internal state */
|
|
20
|
+
destroyed = false;
|
|
19
21
|
/* construct node */
|
|
20
22
|
constructor(id, cfg, opts, args) {
|
|
21
23
|
super(id, cfg, opts, args);
|
|
@@ -23,6 +25,7 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
23
25
|
this.configure({
|
|
24
26
|
type: { type: "string", pos: 0, val: "audio", match: /^(?:audio|text)$/ },
|
|
25
27
|
name: { type: "string", pos: 1, val: "trace" },
|
|
28
|
+
mode: { type: "string", pos: 2, val: "filter", match: /^(?:filter|sink)$/ },
|
|
26
29
|
dashboard: { type: "string", val: "" }
|
|
27
30
|
});
|
|
28
31
|
/* sanity check parameters */
|
|
@@ -30,7 +33,10 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
30
33
|
throw new Error("only trace nodes of type \"text\" can export to dashboard");
|
|
31
34
|
/* declare node input/output format */
|
|
32
35
|
this.input = this.params.type;
|
|
33
|
-
|
|
36
|
+
if (this.params.mode === "filter")
|
|
37
|
+
this.output = this.params.type;
|
|
38
|
+
else if (this.params.mode === "sink")
|
|
39
|
+
this.output = "none";
|
|
34
40
|
}
|
|
35
41
|
/* open node */
|
|
36
42
|
async open() {
|
|
@@ -41,6 +47,8 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
41
47
|
else
|
|
42
48
|
this.log(level, msg);
|
|
43
49
|
};
|
|
50
|
+
/* clear destruction flag */
|
|
51
|
+
this.destroyed = false;
|
|
44
52
|
/* helper functions for formatting */
|
|
45
53
|
const fmtTime = (t) => t.toFormat("hh:mm:ss.SSS");
|
|
46
54
|
const fmtMeta = (meta) => {
|
|
@@ -64,6 +72,10 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
64
72
|
highWaterMark: 1,
|
|
65
73
|
transform(chunk, encoding, callback) {
|
|
66
74
|
let error;
|
|
75
|
+
if (self.destroyed) {
|
|
76
|
+
callback(new Error("stream already destroyed"));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
67
79
|
if (Buffer.isBuffer(chunk.payload)) {
|
|
68
80
|
if (self.params.type === "audio")
|
|
69
81
|
log("debug", fmtChunkBase(chunk) +
|
|
@@ -84,7 +96,9 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
84
96
|
else
|
|
85
97
|
error = new Error(`${self.params.type} chunk: seen String instead of Buffer chunk type`);
|
|
86
98
|
}
|
|
87
|
-
if (
|
|
99
|
+
if (self.params.mode === "sink")
|
|
100
|
+
callback();
|
|
101
|
+
else if (error !== undefined)
|
|
88
102
|
callback(error);
|
|
89
103
|
else {
|
|
90
104
|
this.push(chunk, encoding);
|
|
@@ -92,6 +106,10 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
92
106
|
}
|
|
93
107
|
},
|
|
94
108
|
final(callback) {
|
|
109
|
+
if (self.destroyed || self.params.mode === "sink") {
|
|
110
|
+
callback();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
95
113
|
this.push(null);
|
|
96
114
|
callback();
|
|
97
115
|
}
|
|
@@ -104,6 +122,8 @@ class SpeechFlowNodeX2XTrace extends speechflow_node_1.default {
|
|
|
104
122
|
this.stream.destroy();
|
|
105
123
|
this.stream = null;
|
|
106
124
|
}
|
|
125
|
+
/* indicate destruction */
|
|
126
|
+
this.destroyed = true;
|
|
107
127
|
}
|
|
108
128
|
}
|
|
109
129
|
exports.default = SpeechFlowNodeX2XTrace;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speechflow-node-x2x-trace.js","sourceRoot":"","sources":["../src/speechflow-node-x2x-trace.ts"],"names":[],"mappings":";AAAA;;;;EAIE;;;;;AAEF,6BAA6B;AAC7B,8DAAgC;AAKhC,6BAA6B;AAC7B,wEAAmE;AAEnE,6CAA6C;AAC7C,MAAqB,sBAAuB,SAAQ,yBAAc;IAC9D,kCAAkC;IAC3B,MAAM,CAAC,IAAI,GAAG,WAAW,CAAA;IAEhC,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;YACX,IAAI,EAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,kBAAkB,EAAE;YAC9E,IAAI,EAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE;YACnD,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAU,GAAG,EAAE,EAAE,EAAE;SACjD,CAAC,CAAA;QAEF,+BAA+B;QAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,KAAK,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO;YAC5D,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;QAEhF,wCAAwC;QACxC,IAAI,CAAC,KAAK,GAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;QAC9B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"speechflow-node-x2x-trace.js","sourceRoot":"","sources":["../src/speechflow-node-x2x-trace.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,9 +17,9 @@ patch-apply
|
|
|
17
17
|
# [speechflow-cli] multiview-style development dashboard
|
|
18
18
|
dev
|
|
19
19
|
stmux -w always -m beep -e "built.in.+ms" -- \
|
|
20
|
-
[ -s
|
|
20
|
+
[ -s 50% "stx lint-watch" : \
|
|
21
21
|
-s 15% "stx build-watch" : \
|
|
22
|
-
-s
|
|
22
|
+
-s 25% "stx server-watch" ]
|
|
23
23
|
|
|
24
24
|
# [speechflow-cli] static code analysis (linting)
|
|
25
25
|
lint:
|
|
@@ -37,7 +37,7 @@ build
|
|
|
37
37
|
tsc --project etc/tsconfig.json
|
|
38
38
|
|
|
39
39
|
# [speechflow-cli] code compilation/transpiling (building) with file watching
|
|
40
|
-
build-watch
|
|
40
|
+
build-watch : build
|
|
41
41
|
nodemon --exec "stx build" --watch src --ext ts
|
|
42
42
|
|
|
43
43
|
# [speechflow-cli] build all-in-one packages
|
|
@@ -54,18 +54,14 @@ build-pkg
|
|
|
54
54
|
shx mv speechflow-macos-x64 speechflow-mac-x64 && \
|
|
55
55
|
shx mv speechflow-macos-arm64 speechflow-mac-a64
|
|
56
56
|
|
|
57
|
-
# [speechflow-cli] (internal) wait for server
|
|
58
|
-
server-delay
|
|
59
|
-
delay 2.0
|
|
60
|
-
|
|
61
57
|
# [speechflow-cli] run program
|
|
62
58
|
server
|
|
63
|
-
|
|
59
|
+
cd .. && npm start test
|
|
64
60
|
|
|
65
61
|
# [speechflow-cli] run program with file watching
|
|
66
62
|
server-watch
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
delay 4.0
|
|
64
|
+
cross-env nodemon --exec "stx server" --watch dst --ext ts --delay 1.0
|
|
69
65
|
|
|
70
66
|
# [speechflow-cli] remove all files regularly generated
|
|
71
67
|
clean
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
"@gpeng/naudiodon": "2.4.1",
|
|
23
23
|
"@deepgram/sdk": "4.11.2",
|
|
24
24
|
"deepl-node": "1.19.0",
|
|
25
|
-
"@elevenlabs/elevenlabs-js": "2.
|
|
25
|
+
"@elevenlabs/elevenlabs-js": "2.15.0",
|
|
26
26
|
"stream-transform": "3.4.0",
|
|
27
27
|
"get-stream": "9.0.1",
|
|
28
28
|
"@dotenvx/dotenvx": "1.49.0",
|
|
29
29
|
"speex-resampler": "3.0.1",
|
|
30
30
|
"@sapphi-red/speex-preprocess-wasm": "0.4.0",
|
|
31
31
|
"@shiguredo/rnnoise-wasm": "2025.1.5",
|
|
32
|
-
"@aws-sdk/client-transcribe-streaming": "3.
|
|
33
|
-
"@aws-sdk/client-translate": "3.
|
|
34
|
-
"@aws-sdk/client-polly": "3.
|
|
32
|
+
"@aws-sdk/client-transcribe-streaming": "3.888.0",
|
|
33
|
+
"@aws-sdk/client-translate": "3.888.0",
|
|
34
|
+
"@aws-sdk/client-polly": "3.888.0",
|
|
35
35
|
"@google-cloud/translate": "9.2.0",
|
|
36
36
|
"node-web-audio-api": "1.0.4",
|
|
37
37
|
"object-path": "0.11.8",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"hapi-plugin-websocket": "2.4.11",
|
|
47
47
|
"@opensumi/reconnecting-websocket": "4.4.0",
|
|
48
48
|
"ollama": "0.5.17",
|
|
49
|
-
"openai": "5.
|
|
49
|
+
"openai": "5.20.2",
|
|
50
50
|
"@rse/ffmpeg": "1.4.2",
|
|
51
51
|
"ffmpeg-stream": "1.0.1",
|
|
52
52
|
"installed-packages": "1.0.13",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"pure-uuid": "1.8.1",
|
|
59
59
|
"wavefile": "11.0.0",
|
|
60
60
|
"audio-inspect": "0.0.4",
|
|
61
|
-
"@huggingface/transformers": "3.7.
|
|
61
|
+
"@huggingface/transformers": "3.7.3",
|
|
62
62
|
"kokoro-js": "1.2.1",
|
|
63
63
|
"@ericedouard/vad-node-realtime": "0.2.0",
|
|
64
64
|
"osc-js": "2.4.1",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"node-interval-tree": "2.1.2",
|
|
67
67
|
"wrap-text": "1.0.10",
|
|
68
68
|
"cli-table3": "0.6.5",
|
|
69
|
-
"@rse/stx": "1.1.
|
|
69
|
+
"@rse/stx": "1.1.1"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"eslint": "9.35.0",
|
|
@@ -75,15 +75,15 @@
|
|
|
75
75
|
"eslint-plugin-promise": "7.2.1",
|
|
76
76
|
"eslint-plugin-import": "2.32.0",
|
|
77
77
|
"eslint-plugin-node": "11.1.0",
|
|
78
|
-
"typescript-eslint": "8.
|
|
79
|
-
"@typescript-eslint/eslint-plugin": "8.
|
|
80
|
-
"@typescript-eslint/parser": "8.
|
|
81
|
-
"oxlint": "1.
|
|
82
|
-
"eslint-plugin-oxlint": "1.
|
|
78
|
+
"typescript-eslint": "8.43.0",
|
|
79
|
+
"@typescript-eslint/eslint-plugin": "8.43.0",
|
|
80
|
+
"@typescript-eslint/parser": "8.43.0",
|
|
81
|
+
"oxlint": "1.15.0",
|
|
82
|
+
"eslint-plugin-oxlint": "1.15.0",
|
|
83
83
|
"@biomejs/biome": "2.0.6",
|
|
84
84
|
"eslint-config-biome": "2.1.3",
|
|
85
85
|
|
|
86
|
-
"@types/node": "24.3.
|
|
86
|
+
"@types/node": "24.3.3",
|
|
87
87
|
"@types/yargs": "17.0.33",
|
|
88
88
|
"@types/js-yaml": "4.0.9",
|
|
89
89
|
"@types/object-path": "0.11.4",
|
|
@@ -255,7 +255,8 @@ export default class SpeechFlowNodeA2ACompressor extends SpeechFlowNode {
|
|
|
255
255
|
this.push(chunk)
|
|
256
256
|
callback()
|
|
257
257
|
}).catch((error: unknown) => {
|
|
258
|
-
|
|
258
|
+
if (!self.destroyed)
|
|
259
|
+
callback(util.ensureError(error, "compression failed"))
|
|
259
260
|
})
|
|
260
261
|
}
|
|
261
262
|
},
|
|
@@ -176,7 +176,8 @@ export default class SpeechFlowNodeA2AExpander extends SpeechFlowNode {
|
|
|
176
176
|
this.push(chunk)
|
|
177
177
|
callback()
|
|
178
178
|
}).catch((error: unknown) => {
|
|
179
|
-
|
|
179
|
+
if (!self.destroyed)
|
|
180
|
+
callback(util.ensureError(error, "expansion failed"))
|
|
180
181
|
})
|
|
181
182
|
}
|
|
182
183
|
},
|
|
@@ -33,12 +33,16 @@ export default class SpeechFlowNodeA2AMeter extends SpeechFlowNode {
|
|
|
33
33
|
/* declare node configuration parameters */
|
|
34
34
|
this.configure({
|
|
35
35
|
interval: { type: "number", pos: 0, val: 250 },
|
|
36
|
+
mode: { type: "string", pos: 1, val: "filter", match: /^(?:filter|sink)$/ },
|
|
36
37
|
dashboard: { type: "string", val: "" }
|
|
37
38
|
})
|
|
38
39
|
|
|
39
40
|
/* declare node input/output format */
|
|
40
41
|
this.input = "audio"
|
|
41
|
-
this.
|
|
42
|
+
if (this.params.mode === "filter")
|
|
43
|
+
this.output = "audio"
|
|
44
|
+
else if (this.params.mode === "sink")
|
|
45
|
+
this.output = "none"
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
/* open node */
|
|
@@ -53,7 +57,7 @@ export default class SpeechFlowNodeA2AMeter extends SpeechFlowNode {
|
|
|
53
57
|
/* internal state */
|
|
54
58
|
const sampleWindowDuration = 3 /* LUFS-S requires 3s */
|
|
55
59
|
const sampleWindowSize = Math.floor(this.config.audioSampleRate * sampleWindowDuration)
|
|
56
|
-
|
|
60
|
+
const sampleWindow = new Float32Array(sampleWindowSize)
|
|
57
61
|
sampleWindow.fill(0, 0, sampleWindowSize)
|
|
58
62
|
let lufss = -60
|
|
59
63
|
let rms = -60
|
|
@@ -66,10 +70,8 @@ export default class SpeechFlowNodeA2AMeter extends SpeechFlowNode {
|
|
|
66
70
|
/* define chunk processing function */
|
|
67
71
|
const processChunk = (chunkData: Float32Array) => {
|
|
68
72
|
/* update internal audio sample sliding window */
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
newWindow.set(chunkData, sampleWindowSize - chunkData.length)
|
|
72
|
-
sampleWindow = newWindow
|
|
73
|
+
sampleWindow.set(sampleWindow.subarray(chunkData.length), 0)
|
|
74
|
+
sampleWindow.set(chunkData, sampleWindowSize - chunkData.length)
|
|
73
75
|
|
|
74
76
|
/* calculate the LUFS-S and RMS metric */
|
|
75
77
|
const audioData = {
|
|
@@ -151,7 +153,8 @@ export default class SpeechFlowNodeA2AMeter extends SpeechFlowNode {
|
|
|
151
153
|
self.chunkBuffer = newBuffer
|
|
152
154
|
|
|
153
155
|
/* pass-through original audio chunk */
|
|
154
|
-
|
|
156
|
+
if (self.params.mode === "filter")
|
|
157
|
+
this.push(chunk)
|
|
155
158
|
callback()
|
|
156
159
|
}
|
|
157
160
|
catch (error) {
|
|
@@ -160,7 +163,7 @@ export default class SpeechFlowNodeA2AMeter extends SpeechFlowNode {
|
|
|
160
163
|
}
|
|
161
164
|
},
|
|
162
165
|
final (callback) {
|
|
163
|
-
if (self.destroyed) {
|
|
166
|
+
if (self.destroyed || self.params.mode === "sink") {
|
|
164
167
|
callback()
|
|
165
168
|
return
|
|
166
169
|
}
|
|
@@ -18,6 +18,9 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
18
18
|
/* declare official node name */
|
|
19
19
|
public static name = "x2x-trace"
|
|
20
20
|
|
|
21
|
+
/* internal state */
|
|
22
|
+
private destroyed = false
|
|
23
|
+
|
|
21
24
|
/* construct node */
|
|
22
25
|
constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
|
|
23
26
|
super(id, cfg, opts, args)
|
|
@@ -26,6 +29,7 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
26
29
|
this.configure({
|
|
27
30
|
type: { type: "string", pos: 0, val: "audio", match: /^(?:audio|text)$/ },
|
|
28
31
|
name: { type: "string", pos: 1, val: "trace" },
|
|
32
|
+
mode: { type: "string", pos: 2, val: "filter", match: /^(?:filter|sink)$/ },
|
|
29
33
|
dashboard: { type: "string", val: "" }
|
|
30
34
|
})
|
|
31
35
|
|
|
@@ -35,7 +39,10 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
35
39
|
|
|
36
40
|
/* declare node input/output format */
|
|
37
41
|
this.input = this.params.type
|
|
38
|
-
|
|
42
|
+
if (this.params.mode === "filter")
|
|
43
|
+
this.output = this.params.type
|
|
44
|
+
else if (this.params.mode === "sink")
|
|
45
|
+
this.output = "none"
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
/* open node */
|
|
@@ -48,6 +55,9 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
48
55
|
this.log(level, msg)
|
|
49
56
|
}
|
|
50
57
|
|
|
58
|
+
/* clear destruction flag */
|
|
59
|
+
this.destroyed = false
|
|
60
|
+
|
|
51
61
|
/* helper functions for formatting */
|
|
52
62
|
const fmtTime = (t: Duration) => t.toFormat("hh:mm:ss.SSS")
|
|
53
63
|
const fmtMeta = (meta: Map<string, any>) => {
|
|
@@ -74,6 +84,10 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
74
84
|
highWaterMark: 1,
|
|
75
85
|
transform (chunk: SpeechFlowChunk, encoding, callback) {
|
|
76
86
|
let error: Error | undefined
|
|
87
|
+
if (self.destroyed) {
|
|
88
|
+
callback(new Error("stream already destroyed"))
|
|
89
|
+
return
|
|
90
|
+
}
|
|
77
91
|
if (Buffer.isBuffer(chunk.payload)) {
|
|
78
92
|
if (self.params.type === "audio")
|
|
79
93
|
log("debug", fmtChunkBase(chunk) +
|
|
@@ -94,7 +108,9 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
94
108
|
else
|
|
95
109
|
error = new Error(`${self.params.type} chunk: seen String instead of Buffer chunk type`)
|
|
96
110
|
}
|
|
97
|
-
if (
|
|
111
|
+
if (self.params.mode === "sink")
|
|
112
|
+
callback()
|
|
113
|
+
else if (error !== undefined)
|
|
98
114
|
callback(error)
|
|
99
115
|
else {
|
|
100
116
|
this.push(chunk, encoding)
|
|
@@ -102,6 +118,10 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
102
118
|
}
|
|
103
119
|
},
|
|
104
120
|
final (callback) {
|
|
121
|
+
if (self.destroyed || self.params.mode === "sink") {
|
|
122
|
+
callback()
|
|
123
|
+
return
|
|
124
|
+
}
|
|
105
125
|
this.push(null)
|
|
106
126
|
callback()
|
|
107
127
|
}
|
|
@@ -115,5 +135,8 @@ export default class SpeechFlowNodeX2XTrace extends SpeechFlowNode {
|
|
|
115
135
|
this.stream.destroy()
|
|
116
136
|
this.stream = null
|
|
117
137
|
}
|
|
138
|
+
|
|
139
|
+
/* indicate destruction */
|
|
140
|
+
this.destroyed = true
|
|
118
141
|
}
|
|
119
142
|
}
|