speechflow 2.2.1 → 2.3.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/{etc/claude.md → AGENTS.md} +8 -3
- package/CHANGELOG.md +70 -1
- package/README.md +28 -4
- package/etc/speechflow.yaml +3 -1
- package/etc/stx.conf +1 -1
- package/package.json +6 -6
- package/speechflow-cli/dst/speechflow-main-api.d.ts +2 -1
- package/speechflow-cli/dst/speechflow-main-api.js +57 -16
- package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-cli.js +2 -2
- package/speechflow-cli/dst/speechflow-main-config.js +1 -1
- package/speechflow-cli/dst/speechflow-main-graph.js +55 -21
- package/speechflow-cli/dst/speechflow-main-graph.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-nodes.js +1 -1
- package/speechflow-cli/dst/speechflow-main-status.js +6 -3
- package/speechflow-cli/dst/speechflow-main-status.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +7 -10
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +8 -6
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +9 -5
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js +6 -5
- package/speechflow-cli/dst/speechflow-node-a2a-expander.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-filler.js +2 -4
- package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gain.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js +20 -12
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gtcrn-wt.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gtcrn.js +33 -11
- package/speechflow-cli/dst/speechflow-node-a2a-gtcrn.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-pitch.js +4 -3
- package/speechflow-cli/dst/speechflow-node-a2a-pitch.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js +2 -2
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +19 -11
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-speex.js +8 -8
- package/speechflow-cli/dst/speechflow-node-a2a-speex.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js +33 -29
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js +6 -5
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.d.ts +2 -1
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.js +34 -20
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +13 -5
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-google.js +3 -2
- package/speechflow-cli/dst/speechflow-node-a2t-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js +33 -27
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js +16 -5
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +17 -5
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-google.js +17 -5
- package/speechflow-cli/dst/speechflow-node-t2a-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-kitten.d.ts +15 -0
- package/speechflow-cli/dst/speechflow-node-t2a-kitten.js +194 -0
- package/speechflow-cli/dst/speechflow-node-t2a-kitten.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +21 -9
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-openai.js +17 -5
- package/speechflow-cli/dst/speechflow-node-t2a-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js +21 -7
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-amazon.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-format.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-google.js +4 -2
- package/speechflow-cli/dst/speechflow-node-t2t-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-modify.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-opus.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-profanity.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-spellcheck.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +34 -14
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-summary.js +3 -3
- package/speechflow-cli/dst/speechflow-node-t2t-summary.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-translate.js +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js +3 -2
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-device.js +18 -7
- package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-exec.js +23 -11
- package/speechflow-cli/dst/speechflow-node-xio-exec.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-file.js +13 -7
- package/speechflow-cli/dst/speechflow-node-xio-file.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js +25 -12
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-vban.js +32 -20
- package/speechflow-cli/dst/speechflow-node-xio-vban.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-webrtc.js +78 -62
- package/speechflow-cli/dst/speechflow-node-xio-webrtc.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-websocket.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js +63 -18
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node.js +5 -7
- package/speechflow-cli/dst/speechflow-node.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-audio-wt.js +31 -5
- package/speechflow-cli/dst/speechflow-util-audio-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-audio.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-util-audio.js +25 -14
- 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 +2 -2
- package/speechflow-cli/dst/speechflow-util-error.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-llm.js +1 -1
- package/speechflow-cli/dst/speechflow-util-misc.d.ts +3 -2
- package/speechflow-cli/dst/speechflow-util-misc.js +63 -6
- package/speechflow-cli/dst/speechflow-util-misc.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-queue.d.ts +5 -17
- package/speechflow-cli/dst/speechflow-util-queue.js +57 -78
- package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.js +35 -8
- package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util.js +1 -1
- package/speechflow-cli/dst/speechflow.d.ts +1 -1
- package/speechflow-cli/dst/speechflow.js +1 -1
- package/speechflow-cli/etc/eslint.mjs +1 -1
- package/speechflow-cli/etc/oxlint.jsonc +2 -1
- package/speechflow-cli/etc/stx.conf +8 -2
- package/speechflow-cli/package.d/@ericedouard+vad-node-realtime+0.2.0.patch +2 -1
- package/speechflow-cli/package.d/@typescript-eslint+typescript-estree+8.57.2.patch +12 -0
- package/speechflow-cli/package.d/kitten-tts-js+0.1.2.patch +24 -0
- package/speechflow-cli/package.d/speex-resampler+3.0.1.patch +56 -0
- package/speechflow-cli/package.json +40 -30
- package/speechflow-cli/src/lib.d.ts +19 -1
- package/speechflow-cli/src/speechflow-main-api.ts +64 -19
- package/speechflow-cli/src/speechflow-main-cli.ts +2 -2
- package/speechflow-cli/src/speechflow-main-config.ts +1 -1
- package/speechflow-cli/src/speechflow-main-graph.ts +56 -22
- package/speechflow-cli/src/speechflow-main-nodes.ts +1 -1
- package/speechflow-cli/src/speechflow-main-status.ts +6 -3
- package/speechflow-cli/src/speechflow-main.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +7 -11
- package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +8 -6
- package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +10 -5
- package/speechflow-cli/src/speechflow-node-a2a-expander.ts +6 -5
- package/speechflow-cli/src/speechflow-node-a2a-ffmpeg.ts +3 -2
- package/speechflow-cli/src/speechflow-node-a2a-filler.ts +2 -4
- package/speechflow-cli/src/speechflow-node-a2a-gain.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-gender.ts +20 -13
- package/speechflow-cli/src/speechflow-node-a2a-gtcrn-wt.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-gtcrn.ts +43 -16
- package/speechflow-cli/src/speechflow-node-a2a-meter.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-mute.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-pitch.ts +4 -3
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise-wt.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +24 -12
- package/speechflow-cli/src/speechflow-node-a2a-speex.ts +10 -9
- package/speechflow-cli/src/speechflow-node-a2a-vad.ts +38 -31
- package/speechflow-cli/src/speechflow-node-a2a-wav.ts +6 -5
- package/speechflow-cli/src/speechflow-node-a2t-amazon.ts +35 -22
- package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +17 -6
- package/speechflow-cli/src/speechflow-node-a2t-google.ts +5 -4
- package/speechflow-cli/src/speechflow-node-a2t-openai.ts +39 -31
- package/speechflow-cli/src/speechflow-node-t2a-amazon.ts +16 -5
- package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +17 -5
- package/speechflow-cli/src/speechflow-node-t2a-google.ts +17 -5
- package/speechflow-cli/src/speechflow-node-t2a-kitten.ts +178 -0
- package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +21 -9
- package/speechflow-cli/src/speechflow-node-t2a-openai.ts +17 -5
- package/speechflow-cli/src/speechflow-node-t2a-supertonic.ts +21 -7
- package/speechflow-cli/src/speechflow-node-t2t-amazon.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-format.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-google.ts +4 -2
- package/speechflow-cli/src/speechflow-node-t2t-modify.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-opus.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-profanity.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-punctuation.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-spellcheck.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +39 -15
- package/speechflow-cli/src/speechflow-node-t2t-summary.ts +3 -3
- package/speechflow-cli/src/speechflow-node-t2t-translate.ts +1 -1
- package/speechflow-cli/src/speechflow-node-x2x-filter.ts +4 -3
- package/speechflow-cli/src/speechflow-node-x2x-trace.ts +1 -1
- package/speechflow-cli/src/speechflow-node-xio-device.ts +21 -7
- package/speechflow-cli/src/speechflow-node-xio-exec.ts +25 -11
- package/speechflow-cli/src/speechflow-node-xio-file.ts +15 -7
- package/speechflow-cli/src/speechflow-node-xio-mqtt.ts +28 -15
- package/speechflow-cli/src/speechflow-node-xio-vban.ts +35 -22
- package/speechflow-cli/src/speechflow-node-xio-webrtc.ts +85 -69
- package/speechflow-cli/src/speechflow-node-xio-websocket.ts +67 -20
- package/speechflow-cli/src/speechflow-node.ts +7 -8
- package/speechflow-cli/src/speechflow-util-audio-wt.ts +46 -7
- package/speechflow-cli/src/speechflow-util-audio.ts +27 -15
- package/speechflow-cli/src/speechflow-util-error.ts +3 -3
- package/speechflow-cli/src/speechflow-util-llm.ts +1 -1
- package/speechflow-cli/src/speechflow-util-misc.ts +63 -6
- package/speechflow-cli/src/speechflow-util-queue.ts +60 -81
- package/speechflow-cli/src/speechflow-util-stream.ts +40 -8
- package/speechflow-cli/src/speechflow-util.ts +1 -1
- package/speechflow-cli/src/speechflow.ts +1 -1
- package/speechflow-ui-db/dst/index.html +1 -1
- package/speechflow-ui-db/dst/index.js +15 -15
- package/speechflow-ui-db/etc/eslint.mjs +1 -1
- package/speechflow-ui-db/etc/oxlint.jsonc +1 -1
- package/speechflow-ui-db/etc/stx.conf +1 -1
- package/speechflow-ui-db/etc/stylelint.js +1 -1
- package/speechflow-ui-db/etc/stylelint.yaml +1 -1
- package/speechflow-ui-db/etc/vite-client.mts +1 -1
- package/speechflow-ui-db/package.d/@typescript-eslint+typescript-estree+8.57.2.patch +12 -0
- package/speechflow-ui-db/package.json +22 -16
- package/speechflow-ui-db/src/app.styl +1 -1
- package/speechflow-ui-db/src/app.vue +1 -1
- package/speechflow-ui-db/src/index.html +1 -1
- package/speechflow-ui-db/src/index.ts +1 -1
- package/speechflow-ui-st/dst/index.html +1 -1
- package/speechflow-ui-st/dst/index.js +31 -31
- package/speechflow-ui-st/etc/eslint.mjs +1 -1
- package/speechflow-ui-st/etc/oxlint.jsonc +1 -1
- package/speechflow-ui-st/etc/stx.conf +1 -1
- package/speechflow-ui-st/etc/stylelint.js +1 -1
- package/speechflow-ui-st/etc/stylelint.yaml +1 -1
- package/speechflow-ui-st/etc/vite-client.mts +1 -1
- package/speechflow-ui-st/package.d/@typescript-eslint+typescript-estree+8.57.2.patch +12 -0
- package/speechflow-ui-st/package.json +23 -17
- package/speechflow-ui-st/src/app.styl +1 -1
- package/speechflow-ui-st/src/app.vue +1 -1
- package/speechflow-ui-st/src/index.html +1 -1
- package/speechflow-ui-st/src/index.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
** SpeechFlow - Speech Processing Flow Graph
|
|
3
|
-
** Copyright (c) 2024-
|
|
3
|
+
** Copyright (c) 2024-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
4
|
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -26,70 +26,6 @@ export function importObject<T> (name: string, arg: object | string, validator:
|
|
|
26
26
|
return result as T
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
/* helper class for single item queue */
|
|
30
|
-
export class SingleQueue<T> extends EventEmitter {
|
|
31
|
-
private queue = new Array<T>()
|
|
32
|
-
write (item: T) {
|
|
33
|
-
this.queue.unshift(item)
|
|
34
|
-
this.emit("dequeue")
|
|
35
|
-
}
|
|
36
|
-
read () {
|
|
37
|
-
return new Promise<T>((resolve) => {
|
|
38
|
-
const tryToConsume = () => {
|
|
39
|
-
const item = this.queue.pop()
|
|
40
|
-
if (item !== undefined)
|
|
41
|
-
resolve(item)
|
|
42
|
-
else
|
|
43
|
-
this.once("dequeue", tryToConsume)
|
|
44
|
-
}
|
|
45
|
-
tryToConsume()
|
|
46
|
-
})
|
|
47
|
-
}
|
|
48
|
-
drain () {
|
|
49
|
-
const items = this.queue
|
|
50
|
-
this.queue = new Array<T>()
|
|
51
|
-
return items
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/* helper class for double-item queue */
|
|
56
|
-
export class DoubleQueue<T0, T1> extends EventEmitter {
|
|
57
|
-
private queue0 = new Array<T0>()
|
|
58
|
-
private queue1 = new Array<T1>()
|
|
59
|
-
private notify () {
|
|
60
|
-
if (this.queue0.length > 0 && this.queue1.length > 0)
|
|
61
|
-
this.emit("dequeue")
|
|
62
|
-
}
|
|
63
|
-
write0 (item: T0) {
|
|
64
|
-
this.queue0.unshift(item)
|
|
65
|
-
this.notify()
|
|
66
|
-
}
|
|
67
|
-
write1 (item: T1) {
|
|
68
|
-
this.queue1.unshift(item)
|
|
69
|
-
this.notify()
|
|
70
|
-
}
|
|
71
|
-
read () {
|
|
72
|
-
return new Promise<[ T0, T1 ]>((resolve) => {
|
|
73
|
-
const consume = (): [ T0, T1 ] | undefined => {
|
|
74
|
-
if (this.queue0.length > 0 && this.queue1.length > 0) {
|
|
75
|
-
const item0 = this.queue0.pop() as T0
|
|
76
|
-
const item1 = this.queue1.pop() as T1
|
|
77
|
-
return [ item0, item1 ]
|
|
78
|
-
}
|
|
79
|
-
return undefined
|
|
80
|
-
}
|
|
81
|
-
const tryToConsume = () => {
|
|
82
|
-
const items = consume()
|
|
83
|
-
if (items !== undefined)
|
|
84
|
-
resolve(items)
|
|
85
|
-
else
|
|
86
|
-
this.once("dequeue", tryToConsume)
|
|
87
|
-
}
|
|
88
|
-
tryToConsume()
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
29
|
/* queue element */
|
|
94
30
|
export type QueueElement = { type: string }
|
|
95
31
|
|
|
@@ -126,7 +62,7 @@ export class QueuePointer<T extends QueueElement> extends EventEmitter {
|
|
|
126
62
|
position (index?: number): number {
|
|
127
63
|
if (index !== undefined) {
|
|
128
64
|
this.index = Math.max(0, Math.min(index, this.queue.elements.length))
|
|
129
|
-
this.notify("position", this.index)
|
|
65
|
+
this.notify("position", { start: this.index })
|
|
130
66
|
}
|
|
131
67
|
return this.index
|
|
132
68
|
}
|
|
@@ -139,35 +75,53 @@ export class QueuePointer<T extends QueueElement> extends EventEmitter {
|
|
|
139
75
|
if (this.index !== indexOld)
|
|
140
76
|
this.notify("position", { start: this.index })
|
|
141
77
|
}
|
|
142
|
-
walkForwardUntil (type: T["type"]) {
|
|
78
|
+
walkForwardUntil (type: T["type"]): boolean {
|
|
143
79
|
while (this.index < this.queue.elements.length
|
|
144
80
|
&& this.queue.elements[this.index].type !== type)
|
|
145
81
|
this.index++
|
|
146
82
|
this.notify("position", { start: this.index })
|
|
83
|
+
return this.index < this.queue.elements.length
|
|
84
|
+
&& this.queue.elements[this.index].type === type
|
|
147
85
|
}
|
|
148
|
-
walkBackwardUntil (type: T["type"]) {
|
|
149
|
-
|
|
150
|
-
&& this.queue.elements[this.index].type !== type)
|
|
86
|
+
walkBackwardUntil (type: T["type"]): boolean {
|
|
87
|
+
if (this.index === this.queue.elements.length && this.index > 0)
|
|
151
88
|
this.index--
|
|
89
|
+
while (this.index < this.queue.elements.length
|
|
90
|
+
&& this.queue.elements[this.index].type !== type) {
|
|
91
|
+
if (this.index === 0)
|
|
92
|
+
break
|
|
93
|
+
this.index--
|
|
94
|
+
}
|
|
152
95
|
this.notify("position", { start: this.index })
|
|
96
|
+
return this.index < this.queue.elements.length
|
|
97
|
+
&& this.queue.elements[this.index].type === type
|
|
153
98
|
}
|
|
154
99
|
|
|
155
100
|
/* search operations */
|
|
156
|
-
searchForward (type: T["type"]) {
|
|
101
|
+
searchForward (type: T["type"]): number {
|
|
157
102
|
let position = this.index
|
|
158
103
|
while (position < this.queue.elements.length
|
|
159
104
|
&& this.queue.elements[position].type !== type)
|
|
160
105
|
position++
|
|
161
|
-
|
|
162
|
-
|
|
106
|
+
const found = position < this.queue.elements.length
|
|
107
|
+
&& this.queue.elements[position].type === type
|
|
108
|
+
this.notify("search", { start: this.index, end: found ? position : this.index })
|
|
109
|
+
return found ? position : -1
|
|
163
110
|
}
|
|
164
|
-
searchBackward (type: T["type"]) {
|
|
111
|
+
searchBackward (type: T["type"]): number {
|
|
165
112
|
let position = this.index
|
|
166
|
-
|
|
167
|
-
&& this.queue.elements[position].type !== type)
|
|
113
|
+
if (position === this.queue.elements.length && position > 0)
|
|
168
114
|
position--
|
|
169
|
-
|
|
170
|
-
|
|
115
|
+
while (position < this.queue.elements.length
|
|
116
|
+
&& this.queue.elements[position].type !== type) {
|
|
117
|
+
if (position === 0)
|
|
118
|
+
break
|
|
119
|
+
position--
|
|
120
|
+
}
|
|
121
|
+
const found = position < this.queue.elements.length
|
|
122
|
+
&& this.queue.elements[position].type === type
|
|
123
|
+
this.notify("search", { start: found ? position : this.index, end: this.index })
|
|
124
|
+
return found ? position : -1
|
|
171
125
|
}
|
|
172
126
|
|
|
173
127
|
/* reading operations */
|
|
@@ -269,6 +223,7 @@ export class Queue<T extends QueueElement> extends EventEmitter {
|
|
|
269
223
|
for (const pointer of this.pointers.values())
|
|
270
224
|
pointer.position(pointer.position() - min)
|
|
271
225
|
|
|
226
|
+
/* notify (start/end refer to pre-splice indices) */
|
|
272
227
|
this.notify("write", { start: 0, end: min, op: "trim" })
|
|
273
228
|
}
|
|
274
229
|
}
|
|
@@ -301,9 +256,12 @@ export class TimeStore<T> extends EventEmitter {
|
|
|
301
256
|
|
|
302
257
|
/* asynchronous queue */
|
|
303
258
|
export class AsyncQueue<T> {
|
|
304
|
-
private queue
|
|
259
|
+
private queue = new Array<T>()
|
|
305
260
|
private resolvers: { resolve: (v: T) => void, reject: (err: Error) => void }[] = []
|
|
261
|
+
public destroyed = false
|
|
306
262
|
write (v: T) {
|
|
263
|
+
if (this.destroyed)
|
|
264
|
+
return
|
|
307
265
|
const resolver = this.resolvers.shift()
|
|
308
266
|
if (resolver)
|
|
309
267
|
resolver.resolve(v)
|
|
@@ -319,7 +277,13 @@ export class AsyncQueue<T> {
|
|
|
319
277
|
empty () {
|
|
320
278
|
return this.queue.length === 0
|
|
321
279
|
}
|
|
280
|
+
drain () {
|
|
281
|
+
const items = this.queue
|
|
282
|
+
this.queue = new Array<T>()
|
|
283
|
+
return items
|
|
284
|
+
}
|
|
322
285
|
destroy () {
|
|
286
|
+
this.destroyed = true
|
|
323
287
|
for (const resolver of this.resolvers)
|
|
324
288
|
resolver.reject(new Error("AsyncQueue destroyed"))
|
|
325
289
|
this.resolvers = []
|
|
@@ -359,7 +323,22 @@ export class PromiseSet<T> {
|
|
|
359
323
|
this.promises.delete(promise)
|
|
360
324
|
}).catch(() => {})
|
|
361
325
|
}
|
|
362
|
-
async awaitAll () {
|
|
363
|
-
|
|
326
|
+
async awaitAll (timeout = 0) {
|
|
327
|
+
const deadline = timeout > 0 ? Date.now() + timeout : 0
|
|
328
|
+
while (this.promises.size > 0) {
|
|
329
|
+
const snapshot = [ ...this.promises ]
|
|
330
|
+
const remaining = deadline > 0 ? deadline - Date.now() : 0
|
|
331
|
+
if (deadline > 0 && remaining <= 0)
|
|
332
|
+
break
|
|
333
|
+
if (deadline > 0)
|
|
334
|
+
await Promise.race([
|
|
335
|
+
Promise.all(snapshot),
|
|
336
|
+
new Promise((resolve) => { setTimeout(resolve, remaining) })
|
|
337
|
+
])
|
|
338
|
+
else
|
|
339
|
+
await Promise.all(snapshot)
|
|
340
|
+
if (deadline > 0 && Date.now() >= deadline)
|
|
341
|
+
break
|
|
342
|
+
}
|
|
364
343
|
}
|
|
365
344
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
** SpeechFlow - Speech Processing Flow Graph
|
|
3
|
-
** Copyright (c) 2024-
|
|
3
|
+
** Copyright (c) 2024-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
4
|
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -59,7 +59,10 @@ export function ensureStreamChunk (type: "audio" | "text", chunk: SpeechFlowChun
|
|
|
59
59
|
export function createTransformStreamForReadableSide (
|
|
60
60
|
type: "text" | "audio",
|
|
61
61
|
getTimeZero: () => DateTime,
|
|
62
|
-
writableHighWaterMark?: number
|
|
62
|
+
writableHighWaterMark?: number,
|
|
63
|
+
sampleRate?: number,
|
|
64
|
+
bitDepth?: number,
|
|
65
|
+
channels?: number
|
|
63
66
|
) {
|
|
64
67
|
return new Stream.Transform({
|
|
65
68
|
writableObjectMode: false,
|
|
@@ -72,7 +75,8 @@ export function createTransformStreamForReadableSide (
|
|
|
72
75
|
const start = DateTime.now().diff(timeZero)
|
|
73
76
|
let end = start
|
|
74
77
|
if (type === "audio") {
|
|
75
|
-
const duration = util.audioBufferDuration(chunk as Buffer
|
|
78
|
+
const duration = util.audioBufferDuration(chunk as Buffer,
|
|
79
|
+
sampleRate, bitDepth, channels)
|
|
76
80
|
end = start.plus(duration * 1000)
|
|
77
81
|
}
|
|
78
82
|
const payload = ensureStreamChunk(type, chunk) as Buffer | string
|
|
@@ -185,9 +189,33 @@ export class StreamWrapper extends Stream.Transform {
|
|
|
185
189
|
return
|
|
186
190
|
}
|
|
187
191
|
try {
|
|
188
|
-
if (typeof this.foreignStream.end === "function")
|
|
192
|
+
if (typeof this.foreignStream.end === "function") {
|
|
189
193
|
this.foreignStream.end()
|
|
190
|
-
|
|
194
|
+
|
|
195
|
+
/* wait for the foreign stream to finish flushing
|
|
196
|
+
before signaling completion of this Transform stream */
|
|
197
|
+
const ac = new AbortController()
|
|
198
|
+
Promise.race([
|
|
199
|
+
new Promise<void>((resolve, reject) => {
|
|
200
|
+
if (typeof this.foreignStream.once === "function") {
|
|
201
|
+
this.foreignStream.once("finish", () => { resolve() })
|
|
202
|
+
this.foreignStream.once("error", (err: Error) => { reject(err) })
|
|
203
|
+
}
|
|
204
|
+
else
|
|
205
|
+
resolve()
|
|
206
|
+
}),
|
|
207
|
+
util.timeout(5000, "foreign stream flush timeout", ac.signal)
|
|
208
|
+
]).finally(() => {
|
|
209
|
+
ac.abort()
|
|
210
|
+
}).then(() => {
|
|
211
|
+
callback()
|
|
212
|
+
}).catch(() => {
|
|
213
|
+
/* ignore timeout -- stream will be destroyed anyway */
|
|
214
|
+
callback()
|
|
215
|
+
})
|
|
216
|
+
}
|
|
217
|
+
else
|
|
218
|
+
callback()
|
|
191
219
|
}
|
|
192
220
|
catch (err: unknown) {
|
|
193
221
|
callback(util.ensureError(err))
|
|
@@ -211,15 +239,19 @@ export async function destroyStream (
|
|
|
211
239
|
if (( stream instanceof Stream.Duplex
|
|
212
240
|
|| stream instanceof Stream.Transform
|
|
213
241
|
|| stream instanceof Stream.Writable )
|
|
214
|
-
&& (!stream.writableEnded && !stream.destroyed))
|
|
242
|
+
&& (!stream.writableEnded && !stream.destroyed)) {
|
|
243
|
+
const ac = new AbortController()
|
|
215
244
|
await Promise.race([
|
|
216
245
|
new Promise<void>((resolve) => {
|
|
217
246
|
stream.end(() => { resolve() })
|
|
218
247
|
}),
|
|
219
|
-
util.timeout(5000, "stream end timeout")
|
|
220
|
-
]).
|
|
248
|
+
util.timeout(5000, "stream end timeout", ac.signal)
|
|
249
|
+
]).finally(() => {
|
|
250
|
+
ac.abort()
|
|
251
|
+
}).catch(() => {
|
|
221
252
|
/* ignore timeout -- stream will be destroyed anyway */
|
|
222
253
|
})
|
|
254
|
+
}
|
|
223
255
|
|
|
224
256
|
/* destroy the stream */
|
|
225
257
|
stream.destroy()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
** SpeechFlow - Speech Processing Flow Graph
|
|
3
|
-
** Copyright (c) 2024-
|
|
3
|
+
** Copyright (c) 2024-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
4
|
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/*!
|
|
3
3
|
** SpeechFlow - Speech Processing Flow Graph
|
|
4
|
-
** Copyright (c) 2024-
|
|
4
|
+
** Copyright (c) 2024-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
5
5
|
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<!--
|
|
3
3
|
**
|
|
4
4
|
** SpeechFlow - Speech Processing Flow Graph
|
|
5
|
-
** Copyright (c) 2024-
|
|
5
|
+
** Copyright (c) 2024-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
6
6
|
** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
|
|
7
7
|
**
|
|
8
8
|
-->
|