speechflow 2.0.2 → 2.0.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/CHANGELOG.md +17 -0
- package/README.md +9 -9
- package/etc/claude.md +1 -1
- package/package.json +6 -6
- package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main-graph.js +4 -4
- package/speechflow-cli/dst/speechflow-main-graph.js.map +1 -1
- package/speechflow-cli/dst/speechflow-main.js +1 -1
- package/speechflow-cli/dst/speechflow-main.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +6 -6
- package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js +2 -2
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.js +19 -11
- package/speechflow-cli/dst/speechflow-node-a2t-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-google.js +8 -8
- package/speechflow-cli/dst/speechflow-node-a2t-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js +7 -6
- package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js +2 -4
- package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +12 -12
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-google.js +3 -3
- package/speechflow-cli/dst/speechflow-node-t2a-google.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-amazon.js +10 -9
- package/speechflow-cli/dst/speechflow-node-t2t-amazon.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +3 -3
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-format.js +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-format.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-google.js +1 -1
- 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-modify.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-opus.js +6 -6
- package/speechflow-cli/dst/speechflow-node-t2t-opus.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-spellcheck.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +2 -2
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-summary.js +2 -2
- package/speechflow-cli/dst/speechflow-node-t2t-summary.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-t2t-translate.js +50 -25
- package/speechflow-cli/dst/speechflow-node-t2t-translate.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-exec.js +2 -2
- package/speechflow-cli/dst/speechflow-node-xio-exec.js.map +1 -1
- package/speechflow-cli/dst/speechflow-node-xio-file.js +2 -2
- package/speechflow-cli/dst/speechflow-node-xio-file.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 +1 -1
- package/speechflow-cli/dst/speechflow-util-audio.d.ts +1 -0
- package/speechflow-cli/dst/speechflow-util-audio.js +10 -3
- package/speechflow-cli/dst/speechflow-util-audio.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -1
- package/speechflow-cli/dst/speechflow-util-stream.js +4 -5
- package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -1
- package/speechflow-cli/etc/eslint.mjs +1 -3
- package/speechflow-cli/etc/oxlint.jsonc +9 -1
- package/speechflow-cli/etc/stx.conf +1 -2
- package/speechflow-cli/package.json +17 -19
- package/speechflow-cli/src/lib.d.ts +5 -1
- package/speechflow-cli/src/speechflow-main-api.ts +4 -4
- package/speechflow-cli/src/speechflow-main-cli.ts +1 -1
- package/speechflow-cli/src/speechflow-main-graph.ts +16 -16
- package/speechflow-cli/src/speechflow-main-nodes.ts +1 -1
- package/speechflow-cli/src/speechflow-main-status.ts +2 -2
- package/speechflow-cli/src/speechflow-main.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +3 -3
- package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +6 -6
- package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2a-filler.ts +4 -4
- package/speechflow-cli/src/speechflow-node-a2a-gender.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-mute.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2a-pitch.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise-wt.ts +2 -2
- package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +1 -1
- package/speechflow-cli/src/speechflow-node-a2t-amazon.ts +23 -14
- package/speechflow-cli/src/speechflow-node-a2t-google.ts +8 -8
- package/speechflow-cli/src/speechflow-node-a2t-openai.ts +9 -8
- package/speechflow-cli/src/speechflow-node-t2a-amazon.ts +2 -4
- package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +12 -12
- package/speechflow-cli/src/speechflow-node-t2a-google.ts +5 -5
- package/speechflow-cli/src/speechflow-node-t2a-supertonic.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-amazon.ts +12 -11
- package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +3 -3
- package/speechflow-cli/src/speechflow-node-t2t-format.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-google.ts +2 -2
- package/speechflow-cli/src/speechflow-node-t2t-modify.ts +2 -2
- package/speechflow-cli/src/speechflow-node-t2t-opus.ts +7 -7
- package/speechflow-cli/src/speechflow-node-t2t-punctuation.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-spellcheck.ts +1 -1
- package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +2 -2
- package/speechflow-cli/src/speechflow-node-t2t-summary.ts +3 -3
- package/speechflow-cli/src/speechflow-node-t2t-translate.ts +54 -29
- package/speechflow-cli/src/speechflow-node-x2x-filter.ts +4 -4
- package/speechflow-cli/src/speechflow-node-xio-exec.ts +2 -2
- package/speechflow-cli/src/speechflow-node-xio-file.ts +2 -2
- package/speechflow-cli/src/speechflow-node-xio-vban.ts +4 -2
- package/speechflow-cli/src/speechflow-node-xio-webrtc.ts +1 -1
- package/speechflow-cli/src/speechflow-util-audio.ts +11 -3
- package/speechflow-cli/src/speechflow-util-stream.ts +4 -5
- package/speechflow-ui-db/dst/index.js +14 -14
- package/speechflow-ui-db/etc/oxlint.jsonc +137 -0
- package/speechflow-ui-db/etc/stx.conf +4 -3
- package/speechflow-ui-db/package.json +12 -9
- package/speechflow-ui-st/dst/index.js +32 -32
- package/speechflow-ui-st/etc/oxlint.jsonc +137 -0
- package/speechflow-ui-st/etc/stx.conf +4 -3
- package/speechflow-ui-st/package.json +12 -9
- package/speechflow-cli/dst/test.d.ts +0 -1
- package/speechflow-cli/dst/test.js +0 -18
- package/speechflow-cli/dst/test.js.map +0 -1
- package/speechflow-cli/etc/biome.jsonc +0 -46
- package/speechflow-ui-db/src/lib.d.ts +0 -9
- package/speechflow-ui-st/src/lib.d.ts +0 -9
|
@@ -13,7 +13,7 @@ import * as util from "./speechflow-util"
|
|
|
13
13
|
import { LLM, type LLMCompleteMessage } from "./speechflow-util-llm"
|
|
14
14
|
|
|
15
15
|
/* internal utility types */
|
|
16
|
-
type ConfigEntry = { systemPrompt: string, chat: LLMCompleteMessage[] }
|
|
16
|
+
type ConfigEntry = { systemPrompt: { [ type: string ]: string }, chat: LLMCompleteMessage[] }
|
|
17
17
|
type Config = { [ key: string ]: ConfigEntry }
|
|
18
18
|
|
|
19
19
|
/* SpeechFlow node for LLM-based text-to-text translation */
|
|
@@ -28,19 +28,30 @@ export default class SpeechFlowNodeT2TTranslate extends SpeechFlowNode {
|
|
|
28
28
|
private setup: Config = {
|
|
29
29
|
/* English (EN) to German (DE) translation */
|
|
30
30
|
"en-de": {
|
|
31
|
-
systemPrompt:
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
31
|
+
systemPrompt: {
|
|
32
|
+
"any":
|
|
33
|
+
"You are a translator.\n" +
|
|
34
|
+
"Output only the requested text.\n" +
|
|
35
|
+
"Do not use markdown.\n" +
|
|
36
|
+
"Do not chat.\n" +
|
|
37
|
+
"Do not show any explanations.\n" +
|
|
38
|
+
"Do not show any introduction.\n" +
|
|
39
|
+
"Do not show any preamble.\n" +
|
|
40
|
+
"Do not show any prolog.\n" +
|
|
41
|
+
"Do not show any epilog.\n" +
|
|
42
|
+
"Get to the point.\n" +
|
|
43
|
+
"Preserve the original meaning, tone, and nuance.\n" +
|
|
44
|
+
"Directly translate text from English (EN) to fluent and natural German (DE) language.\n",
|
|
45
|
+
"translategemma":
|
|
46
|
+
/* ATTENTION: do not change this prompt, as TranslateGemma requires this fixed format! */
|
|
47
|
+
"You are a professional English (en) to German (de) translator. " +
|
|
48
|
+
"Your goal is to accurately convey the meaning and nuances of the original " +
|
|
49
|
+
"English text while adhering to German grammar, vocabulary, and cultural sensitivities. " +
|
|
50
|
+
"Produce only the German translation, without any additional explanations or commentary. " +
|
|
51
|
+
"Please translate the following English text into German:\n" +
|
|
52
|
+
"\n" +
|
|
53
|
+
"\n"
|
|
54
|
+
},
|
|
44
55
|
chat: [
|
|
45
56
|
{ role: "user", content: "I love my wife." },
|
|
46
57
|
{ role: "assistant", content: "Ich liebe meine Frau." },
|
|
@@ -53,19 +64,30 @@ export default class SpeechFlowNodeT2TTranslate extends SpeechFlowNode {
|
|
|
53
64
|
|
|
54
65
|
/* German (DE) to English (EN) translation */
|
|
55
66
|
"de-en": {
|
|
56
|
-
systemPrompt:
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
systemPrompt: {
|
|
68
|
+
"any":
|
|
69
|
+
"You are a translator.\n" +
|
|
70
|
+
"Output only the requested text.\n" +
|
|
71
|
+
"Do not use markdown.\n" +
|
|
72
|
+
"Do not chat.\n" +
|
|
73
|
+
"Do not show any explanations.\n" +
|
|
74
|
+
"Do not show any introduction.\n" +
|
|
75
|
+
"Do not show any preamble.\n" +
|
|
76
|
+
"Do not show any prolog.\n" +
|
|
77
|
+
"Do not show any epilog.\n" +
|
|
78
|
+
"Get to the point.\n" +
|
|
79
|
+
"Preserve the original meaning, tone, and nuance.\n" +
|
|
80
|
+
"Directly translate text from German (DE) to fluent and natural English (EN) language.\n",
|
|
81
|
+
"translategemma":
|
|
82
|
+
/* ATTENTION: do not change this prompt, as TranslateGemma requires this fixed format! */
|
|
83
|
+
"You are a professional German (de) to English (en) translator. " +
|
|
84
|
+
"Your goal is to accurately convey the meaning and nuances of the original " +
|
|
85
|
+
"German text while adhering to English grammar, vocabulary, and cultural sensitivities. " +
|
|
86
|
+
"Produce only the English translation, without any additional explanations or commentary. " +
|
|
87
|
+
"Please translate the following German text into English:\n" +
|
|
88
|
+
"\n" +
|
|
89
|
+
"\n"
|
|
90
|
+
},
|
|
69
91
|
chat: [
|
|
70
92
|
{ role: "user", content: "Ich liebe meine Frau." },
|
|
71
93
|
{ role: "assistant", content: "I love my wife." },
|
|
@@ -120,14 +142,17 @@ export default class SpeechFlowNodeT2TTranslate extends SpeechFlowNode {
|
|
|
120
142
|
await this.llm.open()
|
|
121
143
|
|
|
122
144
|
/* provide text-to-text translation */
|
|
123
|
-
const llm = this.llm
|
|
145
|
+
const llm = this.llm
|
|
124
146
|
const translate = async (text: string) => {
|
|
125
147
|
const key = `${this.params.src}-${this.params.dst}`
|
|
126
148
|
const cfg = this.setup[key]
|
|
127
149
|
if (!cfg)
|
|
128
150
|
throw new Error(`unsupported language pair: ${key}`)
|
|
151
|
+
let systemPrompt = cfg.systemPrompt["any"]
|
|
152
|
+
if (this.params.model.match(/^translategemma/))
|
|
153
|
+
systemPrompt = cfg.systemPrompt["translategemma"]
|
|
129
154
|
return llm.complete({
|
|
130
|
-
system:
|
|
155
|
+
system: systemPrompt,
|
|
131
156
|
messages: cfg.chat,
|
|
132
157
|
prompt: text
|
|
133
158
|
})
|
|
@@ -83,10 +83,10 @@ export default class SpeechFlowNodeX2XFilter extends SpeechFlowNode {
|
|
|
83
83
|
const num2 = coerceNum(val2)
|
|
84
84
|
return (
|
|
85
85
|
op === "<" ? (num1 < num2) :
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
op === "<=" ? (num1 <= num2) :
|
|
87
|
+
op === ">=" ? (num1 >= num2) :
|
|
88
|
+
op === ">" ? (num1 > num2) :
|
|
89
|
+
false
|
|
90
90
|
)
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -151,8 +151,8 @@ export default class SpeechFlowNodeXIOExec extends SpeechFlowNode {
|
|
|
151
151
|
/* terminate subprocess */
|
|
152
152
|
if (this.subprocess !== null) {
|
|
153
153
|
/* gracefully end stdin if in write or read/write mode */
|
|
154
|
-
if ((this.params.mode === "w" || this.params.mode === "rw") && this.subprocess.stdin
|
|
155
|
-
!this.subprocess.stdin.destroyed && !this.subprocess.stdin.writableEnded) {
|
|
154
|
+
if ((this.params.mode === "w" || this.params.mode === "rw") && this.subprocess.stdin
|
|
155
|
+
&& !this.subprocess.stdin.destroyed && !this.subprocess.stdin.writableEnded) {
|
|
156
156
|
await Promise.race([
|
|
157
157
|
new Promise<void>((resolve, reject) => {
|
|
158
158
|
this.subprocess!.stdin!.end((err?: Error) => {
|
|
@@ -197,8 +197,8 @@ export default class SpeechFlowNodeXIOFile extends SpeechFlowNode {
|
|
|
197
197
|
else {
|
|
198
198
|
/* for stdio streams, just end without destroying */
|
|
199
199
|
const stream = this.stream
|
|
200
|
-
if ((stream instanceof Stream.Writable || stream instanceof Stream.Duplex)
|
|
201
|
-
(!stream.writableEnded && !stream.destroyed)) {
|
|
200
|
+
if ((stream instanceof Stream.Writable || stream instanceof Stream.Duplex)
|
|
201
|
+
&& (!stream.writableEnded && !stream.destroyed)) {
|
|
202
202
|
await Promise.race([
|
|
203
203
|
new Promise<void>((resolve, reject) => {
|
|
204
204
|
stream.end((err?: Error) => {
|
|
@@ -9,8 +9,10 @@ import Stream from "node:stream"
|
|
|
9
9
|
|
|
10
10
|
/* external dependencies */
|
|
11
11
|
import { DateTime } from "luxon"
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import {
|
|
13
|
+
VBANServer, VBANAudioPacket,
|
|
14
|
+
EBitsResolutions, ECodecs
|
|
15
|
+
} from "vban"
|
|
14
16
|
|
|
15
17
|
/* internal dependencies */
|
|
16
18
|
import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
|
|
@@ -306,7 +306,7 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
|
|
|
306
306
|
pc.ontrack = (event: { track: MediaStreamTrack }) => {
|
|
307
307
|
const track = event.track
|
|
308
308
|
if (track.kind === "audio") {
|
|
309
|
-
this.log("info",
|
|
309
|
+
this.log("info", "WebRTC audio track received from publisher")
|
|
310
310
|
|
|
311
311
|
/* subscribe to incoming RTP packets */
|
|
312
312
|
track.onReceiveRtp.subscribe((rtpPacket: RtpPacket) => {
|
|
@@ -168,10 +168,12 @@ export function updateEnvelopeForChannel (
|
|
|
168
168
|
return Math.sqrt(Math.max(currentEnv, 1e-12))
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
/* helper
|
|
171
|
+
/* helper function for linear to decibel conversion */
|
|
172
172
|
export function lin2dB (x: number): number {
|
|
173
173
|
return 20 * Math.log10(Math.max(x, 1e-12))
|
|
174
174
|
}
|
|
175
|
+
|
|
176
|
+
/* helper function for decibel to linear conversion */
|
|
175
177
|
export function dB2lin (db: number): number {
|
|
176
178
|
return Math.pow(10, db / 20)
|
|
177
179
|
}
|
|
@@ -187,6 +189,7 @@ export class WebAudio {
|
|
|
187
189
|
reject: (error: Error) => void
|
|
188
190
|
timeout: ReturnType<typeof setTimeout>
|
|
189
191
|
}>()
|
|
192
|
+
private captureListener: ((event: MessageEvent) => void) | null = null
|
|
190
193
|
|
|
191
194
|
/* construct object */
|
|
192
195
|
constructor (
|
|
@@ -222,7 +225,7 @@ export class WebAudio {
|
|
|
222
225
|
numberOfInputs: 1,
|
|
223
226
|
numberOfOutputs: 0
|
|
224
227
|
})
|
|
225
|
-
this.
|
|
228
|
+
this.captureListener = (event) => {
|
|
226
229
|
const { type, chunkId, data } = event.data ?? {}
|
|
227
230
|
if (type === "capture-complete") {
|
|
228
231
|
const promise = this.pendingPromises.get(chunkId)
|
|
@@ -235,7 +238,8 @@ export class WebAudio {
|
|
|
235
238
|
promise.resolve(int16Data)
|
|
236
239
|
}
|
|
237
240
|
}
|
|
238
|
-
}
|
|
241
|
+
}
|
|
242
|
+
this.captureNode.port.addEventListener("message", this.captureListener)
|
|
239
243
|
|
|
240
244
|
/* start ports */
|
|
241
245
|
this.sourceNode.port.start()
|
|
@@ -302,6 +306,10 @@ export class WebAudio {
|
|
|
302
306
|
this.sourceNode = null
|
|
303
307
|
}
|
|
304
308
|
if (this.captureNode !== null) {
|
|
309
|
+
if (this.captureListener !== null) {
|
|
310
|
+
this.captureNode.port.removeEventListener("message", this.captureListener)
|
|
311
|
+
this.captureListener = null
|
|
312
|
+
}
|
|
305
313
|
this.captureNode.disconnect()
|
|
306
314
|
this.captureNode = null
|
|
307
315
|
}
|
|
@@ -208,11 +208,10 @@ export async function destroyStream (
|
|
|
208
208
|
stream: Stream.Readable | Stream.Writable | Stream.Duplex | Stream.Transform
|
|
209
209
|
) {
|
|
210
210
|
/* signal the end for a writable stream */
|
|
211
|
-
if ((stream instanceof Stream.Duplex
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
(!stream.writableEnded &&
|
|
215
|
-
!stream.destroyed ) )
|
|
211
|
+
if (( stream instanceof Stream.Duplex
|
|
212
|
+
|| stream instanceof Stream.Transform
|
|
213
|
+
|| stream instanceof Stream.Writable )
|
|
214
|
+
&& (!stream.writableEnded && !stream.destroyed))
|
|
216
215
|
await Promise.race([
|
|
217
216
|
new Promise<void>((resolve) => {
|
|
218
217
|
stream.end(() => { resolve() })
|