speechflow 2.0.0 → 2.0.2
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 +12 -0
- package/README.md +4 -4
- package/package.json +4 -4
- package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-cli.js +1 -0
- package/speechflow-cli/dst/speechflow-main-cli.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-graph.js +2 -4
- package/speechflow-cli/dst/speechflow-main-graph.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-nodes.js +1 -0
- package/speechflow-cli/dst/speechflow-main-nodes.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +7 -9
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js +8 -9
- package/speechflow-cli/dst/speechflow-node-a2a-expander.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-filler.js +2 -0
- package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-pitch.js +11 -9
- package/speechflow-cli/dst/speechflow-node-a2a-pitch.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-speex.js +4 -2
- package/speechflow-cli/dst/speechflow-node-a2a-speex.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js +19 -22
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js +7 -0
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.js +2 -11
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-google.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-node-a2t-google.js +0 -6
- package/speechflow-cli/dst/speechflow-node-a2t-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js +6 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js +27 -7
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +5 -3
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-google.js +1 -4
- package/speechflow-cli/dst/speechflow-node-t2a-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.d.ts +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +27 -6
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-openai.js +1 -4
- package/speechflow-cli/dst/speechflow-node-t2a-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.d.ts +2 -3
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js +97 -459
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-amazon.js +0 -2
- package/speechflow-cli/dst/speechflow-node-t2t-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-opus.js +18 -16
- package/speechflow-cli/dst/speechflow-node-t2t-opus.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js +2 -3
- package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-spellcheck.js +2 -3
- package/speechflow-cli/dst/speechflow-node-t2t-spellcheck.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +5 -2
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-summary.js +2 -3
- package/speechflow-cli/dst/speechflow-node-t2t-summary.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-translate.js +1 -2
- package/speechflow-cli/dst/speechflow-node-t2t-translate.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js +2 -0
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-exec.js +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-exec.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-file.js +3 -5
- package/speechflow-cli/dst/speechflow-node-xio-file.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-vban.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-webrtc.js +2 -0
- package/speechflow-cli/dst/speechflow-node-xio-webrtc.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js +9 -9
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-audio.js +4 -0
- package/speechflow-cli/dst/speechflow-util-audio.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-llm.d.ts +0 -1
- package/speechflow-cli/dst/speechflow-util-llm.js +4 -8
- package/speechflow-cli/dst/speechflow-util-llm.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-queue.js +2 -1
- package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util.js +1 -0
- package/speechflow-cli/dst/speechflow-util.js.map +1 -1
- package/speechflow-cli/dst/test.d.ts +1 -0
- package/speechflow-cli/dst/test.js +18 -0
- package/speechflow-cli/dst/test.js.map +1 -0
- package/speechflow-cli/etc/oxlint.jsonc +3 -1
- package/speechflow-cli/package.json +16 -16
- package/speechflow-cli/src/speechflow-main-api.ts +16 -16
- package/speechflow-cli/src/speechflow-main-cli.ts +1 -0
- package/speechflow-cli/src/speechflow-main-graph.ts +7 -9
- package/speechflow-cli/src/speechflow-main-nodes.ts +1 -0
- package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +1 -0
- package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +8 -10
- package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +1 -0
- package/speechflow-cli/src/speechflow-node-a2a-expander.ts +9 -10
- package/speechflow-cli/src/speechflow-node-a2a-filler.ts +2 -0
- package/speechflow-cli/src/speechflow-node-a2a-gender.ts +3 -3
- package/speechflow-cli/src/speechflow-node-a2a-meter.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2a-pitch.ts +11 -9
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise-wt.ts +1 -0
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-speex.ts +5 -3
- package/speechflow-cli/src/speechflow-node-a2a-vad.ts +20 -23
- package/speechflow-cli/src/speechflow-node-a2a-wav.ts +7 -0
- package/speechflow-cli/src/speechflow-node-a2t-amazon.ts +6 -18
- package/speechflow-cli/src/speechflow-node-a2t-google.ts +4 -11
- package/speechflow-cli/src/speechflow-node-a2t-openai.ts +12 -7
- package/speechflow-cli/src/speechflow-node-t2a-amazon.ts +32 -10
- package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +6 -4
- package/speechflow-cli/src/speechflow-node-t2a-google.ts +1 -4
- package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +33 -10
- package/speechflow-cli/src/speechflow-node-t2a-openai.ts +1 -4
- package/speechflow-cli/src/speechflow-node-t2a-supertonic.ts +106 -571
- package/speechflow-cli/src/speechflow-node-t2t-amazon.ts +1 -3
- package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +2 -2
- package/speechflow-cli/src/speechflow-node-t2t-google.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-opus.ts +19 -18
- package/speechflow-cli/src/speechflow-node-t2t-punctuation.ts +2 -3
- package/speechflow-cli/src/speechflow-node-t2t-spellcheck.ts +2 -3
- package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +5 -2
- package/speechflow-cli/src/speechflow-node-t2t-summary.ts +2 -3
- package/speechflow-cli/src/speechflow-node-t2t-translate.ts +1 -2
- package/speechflow-cli/src/speechflow-node-x2x-filter.ts +2 -0
- package/speechflow-cli/src/speechflow-node-xio-exec.ts +1 -0
- package/speechflow-cli/src/speechflow-node-xio-file.ts +3 -5
- package/speechflow-cli/src/speechflow-node-xio-mqtt.ts +2 -2
- package/speechflow-cli/src/speechflow-node-xio-vban.ts +5 -5
- package/speechflow-cli/src/speechflow-node-xio-webrtc.ts +2 -0
- package/speechflow-cli/src/speechflow-node-xio-websocket.ts +9 -9
- package/speechflow-cli/src/speechflow-util-audio.ts +5 -0
- package/speechflow-cli/src/speechflow-util-llm.ts +4 -9
- package/speechflow-cli/src/speechflow-util-queue.ts +4 -4
- package/speechflow-cli/src/speechflow-util.ts +1 -0
- package/speechflow-ui-db/dst/index.js +14 -14
- package/speechflow-ui-db/package.json +6 -6
- package/speechflow-ui-st/dst/index.js +32 -32
- package/speechflow-ui-st/package.json +6 -6
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/* standard dependencies */
|
|
8
|
-
import Stream
|
|
8
|
+
import Stream from "node:stream"
|
|
9
9
|
|
|
10
10
|
/* external dependencies */
|
|
11
11
|
import { TranslateClient, TranslateTextCommand } from "@aws-sdk/client-translate"
|
|
@@ -65,8 +65,6 @@ export default class SpeechFlowNodeT2TAmazon extends SpeechFlowNode {
|
|
|
65
65
|
secretAccessKey: this.params.secKey
|
|
66
66
|
}
|
|
67
67
|
})
|
|
68
|
-
if (this.client === null)
|
|
69
|
-
throw new Error("failed to establish Amazon Translate client")
|
|
70
68
|
|
|
71
69
|
/* provide text-to-text translation */
|
|
72
70
|
const maxRetries = 10
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
/* standard dependencies */
|
|
8
|
-
import Stream
|
|
8
|
+
import Stream from "node:stream"
|
|
9
9
|
|
|
10
10
|
/* external dependencies */
|
|
11
|
-
import * as DeepL
|
|
11
|
+
import * as DeepL from "deepl-node"
|
|
12
12
|
|
|
13
13
|
/* internal dependencies */
|
|
14
14
|
import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
|
|
@@ -68,18 +68,19 @@ export default class SpeechFlowNodeT2TOPUS extends SpeechFlowNode {
|
|
|
68
68
|
}, 1000)
|
|
69
69
|
|
|
70
70
|
/* instantiate Transformers engine and model */
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
71
|
+
try {
|
|
72
|
+
const pipeline = Transformers.pipeline("translation", model, {
|
|
73
|
+
cache_dir: path.join(this.config.cacheDir, "transformers"),
|
|
74
|
+
dtype: "q4",
|
|
75
|
+
device: "auto",
|
|
76
|
+
progress_callback: progressCallback
|
|
77
|
+
})
|
|
78
|
+
this.translator = await pipeline
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
/* clear progress interval again */
|
|
82
|
+
clearInterval(interval)
|
|
83
|
+
}
|
|
83
84
|
|
|
84
85
|
/* provide text-to-text translation */
|
|
85
86
|
const translate = async (text: string) => {
|
|
@@ -120,17 +121,17 @@ export default class SpeechFlowNodeT2TOPUS extends SpeechFlowNode {
|
|
|
120
121
|
|
|
121
122
|
/* close node */
|
|
122
123
|
async close () {
|
|
123
|
-
/* shutdown stream */
|
|
124
|
-
if (this.stream !== null) {
|
|
125
|
-
await util.destroyStream(this.stream)
|
|
126
|
-
this.stream = null
|
|
127
|
-
}
|
|
128
|
-
|
|
129
124
|
/* shutdown Transformers */
|
|
130
125
|
if (this.translator !== null) {
|
|
131
126
|
this.translator.dispose()
|
|
132
127
|
this.translator = null
|
|
133
128
|
}
|
|
129
|
+
|
|
130
|
+
/* shutdown stream */
|
|
131
|
+
if (this.stream !== null) {
|
|
132
|
+
await util.destroyStream(this.stream)
|
|
133
|
+
this.stream = null
|
|
134
|
+
}
|
|
134
135
|
}
|
|
135
136
|
}
|
|
136
137
|
|
|
@@ -74,7 +74,7 @@ export default class SpeechFlowNodeT2TPunctuation extends SpeechFlowNode {
|
|
|
74
74
|
"Gib KEINE Erklärungen.\n" +
|
|
75
75
|
"Gib KEINE Einleitung.\n" +
|
|
76
76
|
"Gib KEINE Kommentare.\n" +
|
|
77
|
-
"Gib KEINE
|
|
77
|
+
"Gib KEINE Präambel.\n" +
|
|
78
78
|
"Gib KEINEN Prolog.\n" +
|
|
79
79
|
"Gib KEINEN Epilog.\n" +
|
|
80
80
|
"Ändere NICHT die Wörter.\n" +
|
|
@@ -133,8 +133,7 @@ export default class SpeechFlowNodeT2TPunctuation extends SpeechFlowNode {
|
|
|
133
133
|
api: this.params.api,
|
|
134
134
|
model: this.params.model,
|
|
135
135
|
key: this.params.key,
|
|
136
|
-
temperature: 0.7
|
|
137
|
-
topP: 0.5
|
|
136
|
+
temperature: 0.7
|
|
138
137
|
})
|
|
139
138
|
this.llm.on("log", (level: string, message: string) => {
|
|
140
139
|
this.log(level as "info" | "warning" | "error", message)
|
|
@@ -66,7 +66,7 @@ export default class SpeechFlowNodeT2TSpellcheck extends SpeechFlowNode {
|
|
|
66
66
|
"Gib KEINE Erklärungen.\n" +
|
|
67
67
|
"Gib KEINE Einleitung.\n" +
|
|
68
68
|
"Gib KEINE Kommentare.\n" +
|
|
69
|
-
"Gib KEINE
|
|
69
|
+
"Gib KEINE Präambel.\n" +
|
|
70
70
|
"Gib KEINEN Prolog.\n" +
|
|
71
71
|
"Gib KEINEN Epilog.\n" +
|
|
72
72
|
"Ändere NICHT die Grammatik.\n" +
|
|
@@ -120,8 +120,7 @@ export default class SpeechFlowNodeT2TSpellcheck extends SpeechFlowNode {
|
|
|
120
120
|
api: this.params.api,
|
|
121
121
|
model: this.params.model,
|
|
122
122
|
key: this.params.key,
|
|
123
|
-
temperature: 0.7
|
|
124
|
-
topP: 0.5
|
|
123
|
+
temperature: 0.7
|
|
125
124
|
})
|
|
126
125
|
this.llm.on("log", (level: string, message: string) => {
|
|
127
126
|
this.log(level as "info" | "warning" | "error", message)
|
|
@@ -191,7 +191,7 @@ export default class SpeechFlowNodeT2TSubtitle extends SpeechFlowNode {
|
|
|
191
191
|
for (const block of blocks) {
|
|
192
192
|
const lines = block.trim().split(/\r?\n/)
|
|
193
193
|
if (lines.length < 2) {
|
|
194
|
-
this.log("warning", "SRT block contains
|
|
194
|
+
this.log("warning", "SRT block contains fewer than 2 lines")
|
|
195
195
|
continue
|
|
196
196
|
}
|
|
197
197
|
|
|
@@ -231,7 +231,7 @@ export default class SpeechFlowNodeT2TSubtitle extends SpeechFlowNode {
|
|
|
231
231
|
for (const block of blocks) {
|
|
232
232
|
const lines = block.trim().split(/\r?\n/)
|
|
233
233
|
if (lines.length < 1) {
|
|
234
|
-
this.log("warning", "VTT block contains
|
|
234
|
+
this.log("warning", "VTT block contains fewer than 1 line")
|
|
235
235
|
continue
|
|
236
236
|
}
|
|
237
237
|
|
|
@@ -394,15 +394,18 @@ export default class SpeechFlowNodeT2TSubtitle extends SpeechFlowNode {
|
|
|
394
394
|
h.response({}).code(204)
|
|
395
395
|
})
|
|
396
396
|
|
|
397
|
+
/* start HAPI server */
|
|
397
398
|
await this.hapi.start()
|
|
398
399
|
this.log("info", `HAPI: started REST/WebSocket network service: http://${this.params.addr}:${this.params.port}`)
|
|
399
400
|
|
|
401
|
+
/* helper to emit chunks to WebSocket peers */
|
|
400
402
|
const emit = (chunk: SpeechFlowChunk) => {
|
|
401
403
|
const data = JSON.stringify(chunk)
|
|
402
404
|
for (const info of wsPeers.values())
|
|
403
405
|
info.ws.send(data)
|
|
404
406
|
}
|
|
405
407
|
|
|
408
|
+
/* establish writable stream */
|
|
406
409
|
this.stream = new Stream.Writable({
|
|
407
410
|
objectMode: true,
|
|
408
411
|
decodeStrings: false,
|
|
@@ -60,7 +60,7 @@ export default class SpeechFlowNodeT2TSummary extends SpeechFlowNode {
|
|
|
60
60
|
"Gib KEINE Erklärungen.\n" +
|
|
61
61
|
"Gib KEINE Einleitung.\n" +
|
|
62
62
|
"Gib KEINE Kommentare.\n" +
|
|
63
|
-
"Gib KEINE
|
|
63
|
+
"Gib KEINE Präambel.\n" +
|
|
64
64
|
"Gib KEINEN Prolog.\n" +
|
|
65
65
|
"Gib KEINEN Epilog.\n" +
|
|
66
66
|
"Komme auf den Punkt.\n" +
|
|
@@ -119,8 +119,7 @@ export default class SpeechFlowNodeT2TSummary extends SpeechFlowNode {
|
|
|
119
119
|
api: this.params.api,
|
|
120
120
|
model: this.params.model,
|
|
121
121
|
key: this.params.key,
|
|
122
|
-
temperature: 0.7
|
|
123
|
-
topP: 0.5
|
|
122
|
+
temperature: 0.7
|
|
124
123
|
})
|
|
125
124
|
this.llm.on("log", (level: string, message: string) => {
|
|
126
125
|
this.log(level as "info" | "warning" | "error", message)
|
|
@@ -112,8 +112,7 @@ export default class SpeechFlowNodeT2TTranslate extends SpeechFlowNode {
|
|
|
112
112
|
api: this.params.api,
|
|
113
113
|
model: this.params.model,
|
|
114
114
|
key: this.params.key,
|
|
115
|
-
temperature: 0.7
|
|
116
|
-
topP: 0.5
|
|
115
|
+
temperature: 0.7
|
|
117
116
|
})
|
|
118
117
|
this.llm.on("log", (level: string, message: string) => {
|
|
119
118
|
this.log(level as "info" | "warning" | "error", message)
|
|
@@ -120,6 +120,8 @@ export default class SpeechFlowNodeX2XFilter extends SpeechFlowNode {
|
|
|
120
120
|
val1 = chunk.timestampStart.toMillis()
|
|
121
121
|
else if (self.params.var === "time:end")
|
|
122
122
|
val1 = chunk.timestampEnd.toMillis()
|
|
123
|
+
else
|
|
124
|
+
val1 = undefined
|
|
123
125
|
if (comparison(val1, self.params.op, val2)) {
|
|
124
126
|
self.log("info", `[${self.params.name}]: passing through ${chunk.type} chunk`)
|
|
125
127
|
this.push(chunk)
|
|
@@ -54,7 +54,7 @@ export default class SpeechFlowNodeXIOFile extends SpeechFlowNode {
|
|
|
54
54
|
/* open node */
|
|
55
55
|
async open () {
|
|
56
56
|
/* determine how many bytes we need per chunk when
|
|
57
|
-
the chunk should be of the required duration/size
|
|
57
|
+
the chunk should be of the required duration/size */
|
|
58
58
|
const highWaterMarkAudio = (
|
|
59
59
|
this.config.audioSampleRate *
|
|
60
60
|
(this.config.audioBitDepth / 8)
|
|
@@ -139,11 +139,10 @@ export default class SpeechFlowNodeXIOFile extends SpeechFlowNode {
|
|
|
139
139
|
const payload = Buffer.isBuffer(chunk.payload) ?
|
|
140
140
|
chunk.payload : Buffer.from(chunk.payload)
|
|
141
141
|
const seekPosition = chunk.meta.get("chunk:seek") as number | undefined
|
|
142
|
-
if (seekPosition !== undefined)
|
|
142
|
+
if (seekPosition !== undefined)
|
|
143
143
|
/* seek to specified position and write (overload) */
|
|
144
144
|
fs.write(self.fd!, payload, 0, payload.byteLength, seekPosition, callback)
|
|
145
|
-
|
|
146
|
-
else {
|
|
145
|
+
else
|
|
147
146
|
/* append at current position */
|
|
148
147
|
fs.write(self.fd!, payload, 0, payload.byteLength, writePosition, (err) => {
|
|
149
148
|
if (err)
|
|
@@ -153,7 +152,6 @@ export default class SpeechFlowNodeXIOFile extends SpeechFlowNode {
|
|
|
153
152
|
callback()
|
|
154
153
|
}
|
|
155
154
|
})
|
|
156
|
-
}
|
|
157
155
|
},
|
|
158
156
|
final (callback) {
|
|
159
157
|
callback()
|
|
@@ -21,8 +21,8 @@ export default class SpeechFlowNodeXIOMQTT extends SpeechFlowNode {
|
|
|
21
21
|
public static name = "xio-mqtt"
|
|
22
22
|
|
|
23
23
|
/* internal state */
|
|
24
|
-
private broker:
|
|
25
|
-
private clientId:
|
|
24
|
+
private broker: MQTT.MqttClient | null = null
|
|
25
|
+
private clientId: string = (new UUID(1)).format()
|
|
26
26
|
private chunkQueue: util.SingleQueue<SpeechFlowChunk> | null = null
|
|
27
27
|
|
|
28
28
|
/* construct node */
|
|
@@ -29,11 +29,11 @@ export default class SpeechFlowNodeXIOVBAN extends SpeechFlowNode {
|
|
|
29
29
|
public static name = "xio-vban"
|
|
30
30
|
|
|
31
31
|
/* internal state */
|
|
32
|
-
private server:
|
|
33
|
-
private chunkQueue:
|
|
34
|
-
private frameCounter
|
|
35
|
-
private targetAddress
|
|
36
|
-
private targetPort
|
|
32
|
+
private server: VBANServer | null = null
|
|
33
|
+
private chunkQueue: util.SingleQueue<SpeechFlowChunk> | null = null
|
|
34
|
+
private frameCounter = 0
|
|
35
|
+
private targetAddress = ""
|
|
36
|
+
private targetPort = 0
|
|
37
37
|
|
|
38
38
|
/* construct node */
|
|
39
39
|
constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
|
|
@@ -154,6 +154,7 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
|
|
|
154
154
|
this.pcmBuffer = this.pcmBuffer.subarray(this.pcmBuffer.length - maxBufferSize)
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
/* process full Opus frames from buffer */
|
|
157
158
|
while (this.pcmBuffer.length >= this.OPUS_FRAME_BYTES) {
|
|
158
159
|
const frame = this.pcmBuffer.subarray(0, this.OPUS_FRAME_BYTES)
|
|
159
160
|
this.pcmBuffer = this.pcmBuffer.subarray(this.OPUS_FRAME_BYTES)
|
|
@@ -418,6 +419,7 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
|
|
|
418
419
|
const isPublisher = hasSendonly || hasSendrecv
|
|
419
420
|
const isViewer = hasRecvonly
|
|
420
421
|
|
|
422
|
+
/* handle protocol based on mode */
|
|
421
423
|
if (self.params.mode === "r" && isPublisher)
|
|
422
424
|
/* in read mode, accept WHIP publishers */
|
|
423
425
|
await self.handleWHIP(res, body)
|
|
@@ -15,7 +15,7 @@ import ReconnWebSocket, { ErrorEvent } from "@opensumi/reconnecting-websocket"
|
|
|
15
15
|
import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
|
|
16
16
|
import * as util from "./speechflow-util"
|
|
17
17
|
|
|
18
|
-
/* SpeechFlow node for
|
|
18
|
+
/* SpeechFlow node for WebSocket networking */
|
|
19
19
|
export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
20
20
|
/* declare official node name */
|
|
21
21
|
public static name = "xio-websocket"
|
|
@@ -38,9 +38,9 @@ export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
|
38
38
|
|
|
39
39
|
/* sanity check parameters */
|
|
40
40
|
if (this.params.listen !== "" && this.params.connect !== "")
|
|
41
|
-
throw new Error("
|
|
41
|
+
throw new Error("WebSocket node cannot listen and connect at the same time")
|
|
42
42
|
else if (this.params.listen === "" && this.params.connect === "")
|
|
43
|
-
throw new Error("
|
|
43
|
+
throw new Error("WebSocket node requires either listen or connect mode")
|
|
44
44
|
|
|
45
45
|
/* declare node input/output format */
|
|
46
46
|
if (this.params.mode === "rw") {
|
|
@@ -121,7 +121,7 @@ export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
|
121
121
|
else if (chunk.type !== self.params.type)
|
|
122
122
|
callback(new Error(`written chunk is not of ${self.params.type} type`))
|
|
123
123
|
else if (websockets.size === 0)
|
|
124
|
-
callback(new Error("still no
|
|
124
|
+
callback(new Error("still no WebSocket connections available"))
|
|
125
125
|
else {
|
|
126
126
|
const data = util.streamChunkEncode(chunk)
|
|
127
127
|
const results: Promise<void>[] = []
|
|
@@ -168,10 +168,10 @@ export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
|
168
168
|
connectionTimeout: 4000,
|
|
169
169
|
minUptime: 5000
|
|
170
170
|
})
|
|
171
|
-
this.client.addEventListener("open", (
|
|
171
|
+
this.client.addEventListener("open", (_ev) => {
|
|
172
172
|
this.log("info", `connection opened to URL ${this.params.connect}`)
|
|
173
173
|
})
|
|
174
|
-
this.client.addEventListener("close", (
|
|
174
|
+
this.client.addEventListener("close", (_ev) => {
|
|
175
175
|
this.log("info", `connection closed to URL ${this.params.connect}`)
|
|
176
176
|
})
|
|
177
177
|
this.client.addEventListener("error", (ev: ErrorEvent) => {
|
|
@@ -208,7 +208,7 @@ export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
|
208
208
|
else if (chunk.type !== self.params.type)
|
|
209
209
|
callback(new Error(`written chunk is not of ${self.params.type} type`))
|
|
210
210
|
else if (!self.client!.OPEN)
|
|
211
|
-
callback(new Error("still no
|
|
211
|
+
callback(new Error("still no WebSocket connection available"))
|
|
212
212
|
else {
|
|
213
213
|
const data = util.streamChunkEncode(chunk)
|
|
214
214
|
self.client!.send(data)
|
|
@@ -234,7 +234,7 @@ export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
|
234
234
|
|
|
235
235
|
/* close node */
|
|
236
236
|
async close () {
|
|
237
|
-
/* close
|
|
237
|
+
/* close WebSocket server */
|
|
238
238
|
if (this.server !== null) {
|
|
239
239
|
await new Promise<void>((resolve, reject) => {
|
|
240
240
|
this.server!.close((error) => {
|
|
@@ -245,7 +245,7 @@ export default class SpeechFlowNodeXIOWebSocket extends SpeechFlowNode {
|
|
|
245
245
|
this.server = null
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
/* close
|
|
248
|
+
/* close WebSocket client */
|
|
249
249
|
if (this.client !== null) {
|
|
250
250
|
this.client.close()
|
|
251
251
|
this.client = null
|
|
@@ -162,6 +162,9 @@ export function updateEnvelopeForChannel (
|
|
|
162
162
|
else
|
|
163
163
|
currentEnv = alphaR * currentEnv + (1 - alphaR) * det
|
|
164
164
|
}
|
|
165
|
+
|
|
166
|
+
/* store updated envelope value back */
|
|
167
|
+
env[chan] = currentEnv
|
|
165
168
|
return Math.sqrt(Math.max(currentEnv, 1e-12))
|
|
166
169
|
}
|
|
167
170
|
|
|
@@ -173,6 +176,7 @@ export function dB2lin (db: number): number {
|
|
|
173
176
|
return Math.pow(10, db / 20)
|
|
174
177
|
}
|
|
175
178
|
|
|
179
|
+
/* Web Audio API wrapper class */
|
|
176
180
|
export class WebAudio {
|
|
177
181
|
/* internal state */
|
|
178
182
|
public audioContext: AudioContext
|
|
@@ -281,6 +285,7 @@ export class WebAudio {
|
|
|
281
285
|
})
|
|
282
286
|
}
|
|
283
287
|
|
|
288
|
+
/* destroy object */
|
|
284
289
|
public async destroy (): Promise<void> {
|
|
285
290
|
/* reject all pending promises */
|
|
286
291
|
shield(() => {
|
|
@@ -27,7 +27,6 @@ export type LLMConfig = {
|
|
|
27
27
|
timeout?: number
|
|
28
28
|
temperature?: number
|
|
29
29
|
maxTokens?: number
|
|
30
|
-
topP?: number
|
|
31
30
|
cacheDir?: string
|
|
32
31
|
}
|
|
33
32
|
export type LLMCompleteOptions = {
|
|
@@ -61,7 +60,6 @@ export class LLM extends EventEmitter {
|
|
|
61
60
|
timeout: 30 * 1000,
|
|
62
61
|
temperature: 0.7,
|
|
63
62
|
maxTokens: 1024,
|
|
64
|
-
topP: 0.5,
|
|
65
63
|
cacheDir: "",
|
|
66
64
|
...config
|
|
67
65
|
} as Required<LLMConfig>
|
|
@@ -102,7 +100,9 @@ export class LLM extends EventEmitter {
|
|
|
102
100
|
/* instantiate Anthropic API */
|
|
103
101
|
this.anthropic = new Anthropic({
|
|
104
102
|
...(this.config.api !== "" ? { baseURL: this.config.api } : {}),
|
|
105
|
-
|
|
103
|
+
...(this.config.key.match(/^sk-ant-oat/) ?
|
|
104
|
+
{ authToken: this.config.key } :
|
|
105
|
+
{ apiKey: this.config.key } ),
|
|
106
106
|
timeout: this.config.timeout
|
|
107
107
|
})
|
|
108
108
|
}
|
|
@@ -229,7 +229,6 @@ export class LLM extends EventEmitter {
|
|
|
229
229
|
model: this.config.model,
|
|
230
230
|
max_tokens: this.config.maxTokens,
|
|
231
231
|
temperature: this.config.temperature,
|
|
232
|
-
top_p: this.config.topP,
|
|
233
232
|
messages: messages as OpenAI.ChatCompletionMessageParam[]
|
|
234
233
|
}).catch((err) => {
|
|
235
234
|
throw new Error(`failed to perform OpenAI chat completion: ${err}`, { cause: err })
|
|
@@ -252,7 +251,6 @@ export class LLM extends EventEmitter {
|
|
|
252
251
|
model: this.config.model,
|
|
253
252
|
max_tokens: this.config.maxTokens,
|
|
254
253
|
temperature: this.config.temperature,
|
|
255
|
-
top_p: this.config.topP,
|
|
256
254
|
system: systemMessage?.content,
|
|
257
255
|
messages: chatMessages as Anthropic.MessageParam[]
|
|
258
256
|
}).catch((err) => {
|
|
@@ -283,7 +281,6 @@ export class LLM extends EventEmitter {
|
|
|
283
281
|
config: {
|
|
284
282
|
maxOutputTokens: this.config.maxTokens,
|
|
285
283
|
temperature: this.config.temperature,
|
|
286
|
-
topP: this.config.topP,
|
|
287
284
|
...(systemInstruction ? { systemInstruction } : {})
|
|
288
285
|
}
|
|
289
286
|
}).catch((err) => {
|
|
@@ -305,8 +302,7 @@ export class LLM extends EventEmitter {
|
|
|
305
302
|
keep_alive: "10m",
|
|
306
303
|
options: {
|
|
307
304
|
num_predict: this.config.maxTokens,
|
|
308
|
-
temperature: this.config.temperature
|
|
309
|
-
top_p: this.config.topP
|
|
305
|
+
temperature: this.config.temperature
|
|
310
306
|
}
|
|
311
307
|
}).catch((err) => {
|
|
312
308
|
throw new Error(`failed to perform Ollama chat completion: ${err}`, { cause: err })
|
|
@@ -324,7 +320,6 @@ export class LLM extends EventEmitter {
|
|
|
324
320
|
const result = await this.transformer(messages, {
|
|
325
321
|
max_new_tokens: this.config.maxTokens,
|
|
326
322
|
temperature: this.config.temperature,
|
|
327
|
-
top_p: this.config.topP,
|
|
328
323
|
do_sample: true
|
|
329
324
|
}).catch((err) => {
|
|
330
325
|
throw new Error(`failed to perform HuggingFace Transformers text generation: ${err}`, { cause: err })
|
|
@@ -6,17 +6,17 @@
|
|
|
6
6
|
|
|
7
7
|
/* standard dependencies */
|
|
8
8
|
import { EventEmitter } from "node:events"
|
|
9
|
-
import { type, type Type } from "arktype"
|
|
10
9
|
|
|
11
10
|
/* external dependencies */
|
|
12
|
-
import {
|
|
11
|
+
import { type, type Type } from "arktype"
|
|
12
|
+
import { Duration } from "luxon"
|
|
13
13
|
import * as IntervalTree from "node-interval-tree"
|
|
14
14
|
|
|
15
15
|
/* internal dependencies */
|
|
16
16
|
import * as util from "./speechflow-util"
|
|
17
17
|
|
|
18
18
|
/* import an object with parsing and strict error handling */
|
|
19
|
-
export function importObject<T>(name: string, arg: object | string, validator: Type<T, {}>): T {
|
|
19
|
+
export function importObject<T> (name: string, arg: object | string, validator: Type<T, {}>): T {
|
|
20
20
|
const obj: object = typeof arg === "string" ?
|
|
21
21
|
util.run(`${name}: parsing JSON`, () => JSON.parse(arg)) :
|
|
22
22
|
arg
|
|
@@ -289,7 +289,7 @@ export class AsyncQueue<T> {
|
|
|
289
289
|
if (this.queue.length > 0)
|
|
290
290
|
return this.queue.shift()!
|
|
291
291
|
else
|
|
292
|
-
return new Promise<T>((resolve, reject) => this.resolvers.push({ resolve, reject }))
|
|
292
|
+
return new Promise<T>((resolve, reject) => { this.resolvers.push({ resolve, reject }) })
|
|
293
293
|
}
|
|
294
294
|
empty () {
|
|
295
295
|
return this.queue.length === 0
|