speechflow 2.1.0 → 2.1.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +14 -11
  3. package/package.json +6 -6
  4. package/speechflow-cli/dst/speechflow-node-a2a-vad.js +1 -1
  5. package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
  6. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +11 -7
  7. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  8. package/speechflow-cli/dst/speechflow-node-t2t-sentence.d.ts +3 -3
  9. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +117 -100
  10. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
  11. package/speechflow-cli/dst/{speechflow-node-a2t-assemblyai.d.ts → speechflow-node-t2t-simulator.d.ts} +1 -6
  12. package/speechflow-cli/dst/speechflow-node-t2t-simulator.js +128 -0
  13. package/speechflow-cli/dst/speechflow-node-t2t-simulator.js.map +1 -0
  14. package/speechflow-cli/dst/speechflow-node-xio-webrtc.js +2 -2
  15. package/speechflow-cli/dst/speechflow-node-xio-webrtc.js.map +1 -1
  16. package/speechflow-cli/dst/speechflow-util-queue.d.ts +9 -3
  17. package/speechflow-cli/dst/speechflow-util-queue.js +39 -17
  18. package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -1
  19. package/speechflow-cli/dst/speechflow-util-stream.d.ts +1 -1
  20. package/speechflow-cli/dst/speechflow-util-stream.js +15 -15
  21. package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -1
  22. package/speechflow-cli/etc/oxlint.jsonc +5 -3
  23. package/speechflow-cli/package.json +26 -23
  24. package/speechflow-cli/src/speechflow-node-a2a-vad.ts +1 -1
  25. package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +17 -14
  26. package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +128 -112
  27. package/speechflow-cli/src/speechflow-node-xio-webrtc.ts +4 -4
  28. package/speechflow-cli/src/speechflow-util-queue.ts +44 -19
  29. package/speechflow-cli/src/speechflow-util-stream.ts +15 -15
  30. package/speechflow-ui-db/dst/app-font-fa-brands-400.woff2 +0 -0
  31. package/speechflow-ui-db/dst/app-font-fa-regular-400.woff2 +0 -0
  32. package/speechflow-ui-db/dst/app-font-fa-solid-900.woff2 +0 -0
  33. package/speechflow-ui-db/dst/app-font-fa-v4compatibility.woff2 +0 -0
  34. package/speechflow-ui-db/dst/index.css +1 -1
  35. package/speechflow-ui-db/dst/index.js +47 -46
  36. package/speechflow-ui-db/package.json +16 -14
  37. package/speechflow-ui-db/src/app.vue +2 -2
  38. package/speechflow-ui-st/dst/app-font-fa-brands-400.woff2 +0 -0
  39. package/speechflow-ui-st/dst/app-font-fa-regular-400.woff2 +0 -0
  40. package/speechflow-ui-st/dst/app-font-fa-solid-900.woff2 +0 -0
  41. package/speechflow-ui-st/dst/app-font-fa-v4compatibility.woff2 +0 -0
  42. package/speechflow-ui-st/dst/index.css +1 -1
  43. package/speechflow-ui-st/dst/index.js +65 -64
  44. package/speechflow-ui-st/etc/oxlint.jsonc +2 -1
  45. package/speechflow-ui-st/package.json +17 -15
  46. package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.js +0 -275
  47. package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.js.map +0 -1
  48. /package/speechflow-cli/package.d/{sherpa-onnx+1.12.23.patch → sherpa-onnx+1.12.25.patch} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"speechflow-util-stream.js","sourceRoot":"","sources":["../src/speechflow-util-stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"speechflow-util-stream.js","sourceRoot":"","sources":["../src/speechflow-util-stream.ts"],"names":[],"mappings":"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"}
@@ -135,10 +135,12 @@
135
135
  "no-inline-comments": "off",
136
136
  "max-statements": "off",
137
137
  "no-duplicate-imports": "off",
138
+ "no-nodejs-modules": "off",
139
+ "parameter-properties": "off",
140
+ "no-shadow": "off",
141
+ "no-relative-parent-imports": "off",
138
142
 
139
- "complexity": [ "error", { "max": 35 } ],
140
- "complexity/max-cyclomatic": [ "error", { "max": 30 } ],
141
- "complexity/max-cognitive": [ "error", { "max": 50 } ]
143
+ "complexity": [ "error", { "max": 35 } ]
142
144
  }
143
145
  }
144
146
 
@@ -24,23 +24,23 @@
24
24
  "shell-parser": "1.0.0",
25
25
  "@deepgram/sdk": "4.11.3",
26
26
  "deepl-node": "1.24.0",
27
- "@elevenlabs/elevenlabs-js": "2.33.0",
27
+ "@elevenlabs/elevenlabs-js": "2.36.0",
28
28
  "get-stream": "9.0.1",
29
29
  "@dotenvx/dotenvx": "1.52.0",
30
30
  "speex-resampler": "3.0.1",
31
31
  "@sapphi-red/speex-preprocess-wasm": "0.4.0",
32
32
  "@shiguredo/rnnoise-wasm": "2025.1.5",
33
- "sherpa-onnx": "1.12.23",
34
- "axios": "1.13.3",
35
- "@aws-sdk/client-transcribe-streaming": "3.975.0",
36
- "@aws-sdk/client-translate": "3.975.0",
37
- "@aws-sdk/client-polly": "3.975.0",
33
+ "sherpa-onnx": "1.12.25",
34
+ "axios": "1.13.5",
35
+ "@aws-sdk/client-transcribe-streaming": "3.992.0",
36
+ "@aws-sdk/client-translate": "3.992.0",
37
+ "@aws-sdk/client-polly": "3.992.0",
38
38
  "@google-cloud/translate": "9.3.0",
39
39
  "@google-cloud/speech": "7.2.1",
40
40
  "@google-cloud/text-to-speech": "6.4.0",
41
- "node-web-audio-api": "1.0.7",
41
+ "node-web-audio-api": "1.0.8",
42
42
  "object-path": "0.11.8",
43
- "glob": "13.0.0",
43
+ "glob": "13.0.5",
44
44
  "ws": "8.19.0",
45
45
  "bufferutil": "4.1.0",
46
46
  "utf-8-validate": "6.0.6",
@@ -51,15 +51,15 @@
51
51
  "hapi-plugin-websocket": "2.4.11",
52
52
  "@opensumi/reconnecting-websocket": "4.4.0",
53
53
  "ollama": "0.6.3",
54
- "openai": "6.16.0",
55
- "@anthropic-ai/sdk": "0.71.2",
56
- "@google/genai": "1.38.0",
54
+ "openai": "6.22.0",
55
+ "@anthropic-ai/sdk": "0.75.0",
56
+ "@google/genai": "1.41.0",
57
57
  "@rse/ffmpeg": "1.4.2",
58
58
  "ffmpeg-stream": "1.0.1",
59
59
  "installed-packages": "1.0.13",
60
60
  "syspath": "1.0.8",
61
61
  "wav": "1.0.2",
62
- "mqtt": "5.14.1",
62
+ "mqtt": "5.15.0",
63
63
  "vban": "1.5.6",
64
64
  "cbor2": "2.2.1",
65
65
  "arktype": "2.1.29",
@@ -67,7 +67,7 @@
67
67
  "wavefile": "11.0.0",
68
68
  "audio-inspect": "0.0.4",
69
69
  "@huggingface/transformers": "3.8.1",
70
- "@huggingface/hub": "2.8.0",
70
+ "@huggingface/hub": "2.10.1",
71
71
  "kokoro-js": "1.2.1",
72
72
  "@ericedouard/vad-node-realtime": "0.2.0",
73
73
  "osc-js": "2.4.1",
@@ -78,8 +78,8 @@
78
78
  "@2toad/profanity": "3.2.0",
79
79
  "cli-table3": "0.6.5",
80
80
  "mkdirp": "3.0.1",
81
- "@soundtouchjs/audio-worklet": "0.2.1",
82
- "werift": "0.22.3",
81
+ "@soundtouchjs/audio-worklet": "0.3.0",
82
+ "werift": "0.22.8",
83
83
  "@discordjs/opus": "0.10.0",
84
84
  "@rse/stx": "1.1.4"
85
85
  },
@@ -90,12 +90,12 @@
90
90
  "eslint-plugin-promise": "7.2.1",
91
91
  "eslint-plugin-import": "2.32.0",
92
92
  "eslint-plugin-node": "11.1.0",
93
- "typescript-eslint": "8.54.0",
94
- "@typescript-eslint/eslint-plugin": "8.54.0",
95
- "@typescript-eslint/parser": "8.54.0",
96
- "oxlint": "1.42.0",
97
- "oxlint-plugin-complexity": "0.3.0",
98
- "eslint-plugin-oxlint": "1.42.0",
93
+ "typescript-eslint": "8.56.0",
94
+ "@typescript-eslint/eslint-plugin": "8.56.0",
95
+ "@typescript-eslint/parser": "8.56.0",
96
+ "oxlint": "1.48.0",
97
+ "oxlint-plugin-complexity": "2.0.0",
98
+ "eslint-plugin-oxlint": "1.48.0",
99
99
 
100
100
  "@types/node": "24.10.1",
101
101
  "@types/yargs": "17.0.35",
@@ -112,14 +112,17 @@
112
112
  "stmux": "1.8.11",
113
113
  "nodemon": "3.1.11",
114
114
  "shx": "0.4.0",
115
- "@yao-pkg/pkg": "6.12.0",
115
+ "@yao-pkg/pkg": "6.14.0",
116
116
  "typescript": "5.9.3",
117
117
  "delay-cli": "3.0.0",
118
118
  "cross-env": "10.1.0"
119
119
  },
120
120
  "overrides": {
121
121
  "@huggingface/transformers": { "onnxruntime-node": "1.22.0", "onnxruntime-web": "1.22.0" },
122
- "@ericedouard/vad-node-realtime": { "onnxruntime-node": "1.22.0", "onnxruntime-web": "1.22.0" }
122
+ "@ericedouard/vad-node-realtime": { "onnxruntime-node": "1.22.0", "onnxruntime-web": "1.22.0" },
123
+ "eslint-plugin-promise": { "eslint": ">=9.0.0" },
124
+ "eslint-plugin-import": { "eslint": ">=9.0.0" },
125
+ "neostandard": { "eslint": ">=9.0.0" }
123
126
  },
124
127
  "upd": [
125
128
  "!onnxruntime-node",
@@ -86,6 +86,7 @@ export default class SpeechFlowNodeA2AVAD extends SpeechFlowNode {
86
86
  }
87
87
 
88
88
  /* helper function for tail timer handling */
89
+ let tail = false
89
90
  const startTailTimer = () => {
90
91
  tail = true
91
92
  clearTailTimer()
@@ -98,7 +99,6 @@ export default class SpeechFlowNodeA2AVAD extends SpeechFlowNode {
98
99
  }
99
100
 
100
101
  /* establish Voice Activity Detection (VAD) facility */
101
- let tail = false
102
102
  try {
103
103
  this.vad = await RealTimeVAD.new({
104
104
  model: "v5",
@@ -32,13 +32,14 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
32
32
 
33
33
  /* declare node configuration parameters */
34
34
  this.configure({
35
- key: { type: "string", val: process.env.SPEECHFLOW_DEEPGRAM_KEY },
36
- keyAdm: { type: "string", val: process.env.SPEECHFLOW_DEEPGRAM_KEY_ADM },
37
- model: { type: "string", val: "nova-2", pos: 0 },
38
- version: { type: "string", val: "latest", pos: 1 },
39
- language: { type: "string", val: "multi", pos: 2 },
40
- interim: { type: "boolean", val: false, pos: 3 },
41
- keywords: { type: "string", val: "", pos: 4 }
35
+ key: { type: "string", val: process.env.SPEECHFLOW_DEEPGRAM_KEY },
36
+ keyAdm: { type: "string", val: process.env.SPEECHFLOW_DEEPGRAM_KEY_ADM },
37
+ model: { type: "string", val: "nova-2", pos: 0 },
38
+ version: { type: "string", val: "latest", pos: 1 },
39
+ language: { type: "string", val: "multi", pos: 2 },
40
+ interim: { type: "boolean", val: false, pos: 3 },
41
+ endpointing: { type: "number", val: 0, pos: 4 },
42
+ keywords: { type: "string", val: "", pos: 5 }
42
43
  })
43
44
 
44
45
  /* sanity check parameters */
@@ -88,6 +89,8 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
88
89
  const metastore = new util.TimeStore<Map<string, any>>()
89
90
 
90
91
  /* configure Deepgram connection options */
92
+ const interim = this.params.interim as boolean
93
+ const endpointing = this.params.endpointing as number
91
94
  const options: Deepgram.LiveSchema = {
92
95
  mip_opt_out: true,
93
96
  model: this.params.model,
@@ -96,8 +99,8 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
96
99
  sample_rate: this.config.audioSampleRate,
97
100
  encoding: "linear16",
98
101
  multichannel: false,
99
- endpointing: false,
100
- interim_results: this.params.interim,
102
+ endpointing: endpointing > 0 ? endpointing : false,
103
+ interim_results: interim,
101
104
  smart_format: false,
102
105
  punctuate: true,
103
106
  filler_words: true,
@@ -140,13 +143,14 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
140
143
  const text = (data.channel?.alternatives[0]?.transcript ?? "") as string
141
144
  const words = (data.channel?.alternatives[0]?.words ?? []) as
142
145
  { word: string, punctuated_word?: string, start: number, end: number }[]
143
- const isFinal = (data.is_final ?? false) as boolean
146
+ const isFinal = (data.is_final as boolean) ?? false
147
+ const speechFinal = (data.speech_final as boolean) ?? false
148
+ const kind = ((interim && isFinal) || (endpointing > 0 && speechFinal)) ? "final" : "intermediate"
144
149
  if (text === "")
145
150
  this.log("info", `empty/dummy text received (start: ${data.start}s, duration: ${data.duration.toFixed(2)}s)`)
146
151
  else {
147
152
  this.log("info", `text received (start: ${data.start}s, ` +
148
- `duration: ${data.duration.toFixed(2)}s, ` +
149
- `kind: ${isFinal ? "final" : "intermediate"}): ` +
153
+ `duration: ${data.duration.toFixed(2)}s, kind: ${kind}): ` +
150
154
  `"${text}"`)
151
155
  const start = Duration.fromMillis(data.start * 1000).plus(this.timeZeroOffset)
152
156
  const end = start.plus({ seconds: data.duration })
@@ -161,8 +165,7 @@ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
161
165
  const end = Duration.fromMillis(word.end * 1000).plus(this.timeZeroOffset)
162
166
  return { word: word.punctuated_word ?? word.word, start, end }
163
167
  }))
164
- const chunk = new SpeechFlowChunk(start, end,
165
- isFinal ? "final" : "intermediate", "text", text, meta)
168
+ const chunk = new SpeechFlowChunk(start, end, kind, "text", text, meta)
166
169
  this.queue.write(chunk)
167
170
  }
168
171
  })
@@ -18,8 +18,7 @@ import * as util from "./speechflow-util"
18
18
  type TextQueueElement = {
19
19
  type: "text-frame",
20
20
  chunk: SpeechFlowChunk,
21
- preview?: "pending" | "sent",
22
- complete?: boolean
21
+ complete: boolean
23
22
  } | {
24
23
  type: "text-eof"
25
24
  }
@@ -31,12 +30,11 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
31
30
 
32
31
  /* internal state */
33
32
  private queue = new util.Queue<TextQueueElement>()
34
- private queueRecv = this.queue.pointerUse("recv")
35
- private queueSplit = this.queue.pointerUse("split")
36
33
  private queueSend = this.queue.pointerUse("send")
37
- private closing = false
34
+ private queueSplit = this.queue.pointerUse("split")
35
+ private queueRecv = this.queue.pointerUse("recv")
36
+ private closing = false
38
37
  private workingOffTimer: ReturnType<typeof setTimeout> | null = null
39
- private previewTimer: ReturnType<typeof setTimeout> | null = null
40
38
 
41
39
  /* construct node */
42
40
  constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
@@ -44,7 +42,8 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
44
42
 
45
43
  /* declare node configuration parameters */
46
44
  this.configure({
47
- timeout: { type: "number", pos: 0, val: 3 * 1000 }
45
+ timeout: { type: "number", pos: 0, val: 3 * 1000 },
46
+ interim: { type: "boolean", pos: 1, val: false }
48
47
  })
49
48
 
50
49
  /* declare node input/output format */
@@ -52,6 +51,14 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
52
51
  this.output = "text"
53
52
  }
54
53
 
54
+ /* concatenate two payloads with proper whitespacing */
55
+ private concatPayload (s1: string, s2: string) {
56
+ if (!(s1.match(/\s+$/) || s2.match(/^\s+/)))
57
+ return `${s1} ${s2}`
58
+ else
59
+ return `${s1}${s2}`
60
+ }
61
+
55
62
  /* open node */
56
63
  async open () {
57
64
  /* clear destruction flag */
@@ -83,84 +90,101 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
83
90
  break
84
91
  }
85
92
 
86
- /* perform sentence splitting on input chunk */
87
- const chunk = element.chunk
88
- const payload = chunk.payload as string
89
- const m = payload.match(/^((?:.|\r?\n)+?[.;?!])\s*((?:.|\r?\n)*)$/)
90
- if (m !== null) {
91
- /* contains a sentence */
92
- const [ , sentence, rest ] = m
93
- if (rest !== "") {
94
- /* contains more than a sentence */
95
- const chunk2 = chunk.clone()
96
- const duration = Duration.fromMillis(
97
- chunk.timestampEnd.minus(chunk.timestampStart).toMillis() *
98
- (sentence.length / payload.length))
99
- chunk2.timestampStart = chunk.timestampStart.plus(duration)
100
- chunk.timestampEnd = chunk2.timestampStart
101
- chunk.payload = sentence
102
- chunk2.payload = rest
103
- element.complete = true
104
- this.queueSplit.touch()
105
- this.queueSplit.walk(+1)
106
- this.queueSplit.insert({ type: "text-frame", chunk: chunk2 })
107
- }
108
- else {
109
- /* contains just the sentence */
110
- element.complete = true
111
- this.queueSplit.touch()
112
- this.queueSplit.walk(+1)
113
- }
93
+ /* skip elements already completed */
94
+ if (element.type === "text-frame" && element.chunk.kind === "final" && element.complete === true) {
95
+ this.queueSplit.walk(+1)
96
+ continue
114
97
  }
115
- else {
116
- /* contains less than a sentence */
117
- const position = this.queueSplit.position()
118
- if (position < this.queueSplit.maxPosition() - 1) {
119
- /* merge into following chunk */
120
- const element2 = this.queueSplit.peek(position + 1)
121
- if (element2 === undefined)
122
- break
123
- if (element2.type === "text-eof") {
124
- /* no more chunks: output as final
125
- (perhaps incomplete sentence at end of stream) */
98
+
99
+ /* perform sentence splitting on input chunk */
100
+ if (element.chunk.kind === "final") {
101
+ const chunk = element.chunk
102
+ const payload = chunk.payload as string
103
+ const m = payload.match(/^((?:.|\r?\n)+?[.;?!])(?:\s+((?:.|\r?\n)+)|\s*)$/)
104
+ if (m !== null) {
105
+ /* contains a sentence */
106
+ const [ , sentence, rest ] = m
107
+ if (rest !== undefined && rest !== "") {
108
+ /* contains more than a sentence */
109
+ const chunk2 = chunk.clone()
110
+ const duration = Duration.fromMillis(
111
+ chunk.timestampEnd.minus(chunk.timestampStart).toMillis() *
112
+ (sentence.length / payload.length))
113
+ chunk2.timestampStart = chunk.timestampStart.plus(duration)
114
+ chunk.timestampEnd = chunk2.timestampStart
115
+ chunk.payload = sentence
116
+ chunk2.payload = rest
126
117
  element.complete = true
118
+ this.queue.silent(true)
127
119
  this.queueSplit.touch()
120
+ this.queue.silent(false)
128
121
  this.queueSplit.walk(+1)
129
- break
122
+ this.queueSplit.insert({ type: "text-frame", chunk: chunk2, complete: false })
123
+ }
124
+ else {
125
+ /* contains just the sentence */
126
+ element.complete = true
127
+ this.queue.silent(true)
128
+ this.queueSplit.silent(true)
129
+ const position = this.queueSplit.position()
130
+ this.queueSplit.walk(+1)
131
+ this.queue.silent(false)
132
+ this.queueSplit.silent(false)
133
+ this.queueSplit.touch(position)
130
134
  }
131
-
132
- /* merge into following chunk */
133
- element2.chunk.timestampStart = element.chunk.timestampStart
134
- element2.chunk.payload =
135
- (element.chunk.payload as string) + " " +
136
- (element2.chunk.payload as string)
137
-
138
- /* reset preview state (merged content needs new preview) */
139
- element2.preview = undefined
140
- this.queueSplit.delete()
141
- this.queueSplit.touch()
142
135
  }
143
136
  else {
144
- /* no following chunk yet: mark for intermediate preview output */
145
- if (element.preview !== "sent") {
146
- element.preview = "pending"
147
- this.queueSplit.touch()
137
+ /* contains less than a sentence */
138
+ const position = this.queueSplit.position()
139
+ if (position < this.queueSplit.maxPosition() - 1) {
140
+ /* merge into following chunk */
141
+ const element2 = this.queueSplit.peek(position + 1)
142
+ if (element2 === undefined)
143
+ break
144
+ if (element2.type === "text-eof") {
145
+ /* no more chunks: output as final
146
+ (perhaps incomplete sentence at end of stream) */
147
+ element.complete = true
148
+ this.queueSplit.walk(+1)
149
+ this.queueSplit.touch(this.queueSplit.position() - 1)
150
+ break
151
+ }
152
+ if (element2.chunk.kind === "final") {
153
+ /* merge into following chunk */
154
+ element2.chunk.timestampStart = element.chunk.timestampStart
155
+ element2.chunk.payload = this.concatPayload(element.chunk.payload as string,
156
+ element2.chunk.payload as string)
157
+
158
+ /* remove current element and touch now current element */
159
+ this.queue.silent(true)
160
+ this.queueSplit.delete()
161
+ this.queue.silent(false)
162
+ this.queueSplit.touch()
163
+ }
164
+ else
165
+ break
166
+ }
167
+ else {
168
+ /* no following chunk yet */
169
+ break
148
170
  }
149
- break
150
171
  }
151
172
  }
173
+ else
174
+ break
152
175
  }
153
176
 
154
177
  /* re-initiate working off round (if still not destroyed) */
155
- workingOff = false
156
178
  if (!this.closing) {
157
179
  this.workingOffTimer = setTimeout(workOffQueue, 100)
158
180
  this.queue.once("write", workOffQueue)
159
181
  }
182
+ workingOff = false
160
183
  }
161
184
  this.queue.once("write", workOffQueue)
162
185
 
163
186
  /* provide Duplex stream and internally attach to classifier */
187
+ let previewed = false
164
188
  const self = this
165
189
  this.stream = new Stream.Duplex({
166
190
  writableObjectMode: true,
@@ -169,37 +193,38 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
169
193
  highWaterMark: 1,
170
194
 
171
195
  /* receive text chunk (writable side of stream) */
172
- write (chunk: SpeechFlowChunk, encoding, callback) {
196
+ write (chunk: SpeechFlowChunk, encoding: BufferEncoding, callback: (error?: Error | null) => void) {
173
197
  if (self.closing)
174
198
  callback(new Error("stream already destroyed"))
175
199
  else if (Buffer.isBuffer(chunk.payload))
176
200
  callback(new Error("expected text input as string chunks"))
177
201
  else if (chunk.payload.length === 0)
178
202
  callback()
179
- else if (chunk.kind === "intermediate") {
180
- /* intermediate chunks: pass through immediately (bypass queue) */
181
- self.log("info", `received text (${chunk.kind}): ${JSON.stringify(chunk.payload)}`)
182
- self.log("info", `send text (intermediate pass-through): ${JSON.stringify(chunk.payload)}`)
183
- this.push(chunk)
184
- callback()
185
- }
186
203
  else {
187
204
  /* final chunks: queue for sentence splitting */
188
205
  self.log("info", `received text (${chunk.kind}): ${JSON.stringify(chunk.payload)}`)
189
-
190
- /* cancel any pending preview timeout */
191
- if (self.previewTimer !== null) {
192
- clearTimeout(self.previewTimer)
193
- self.previewTimer = null
206
+ const recvPos = self.queueRecv.position()
207
+ if (recvPos > 0) {
208
+ const element = self.queueRecv.peek(recvPos - 1)
209
+ if (element) {
210
+ if (element.type === "text-eof") {
211
+ callback(new Error("received text input after end-of-stream"))
212
+ return
213
+ }
214
+ if (element.chunk.kind === "intermediate") {
215
+ self.queueRecv.walk(-1)
216
+ self.queueRecv.delete()
217
+ }
218
+ }
194
219
  }
195
-
196
- self.queueRecv.append({ type: "text-frame", chunk })
220
+ previewed = false
221
+ self.queueRecv.append({ type: "text-frame", chunk, complete: false })
197
222
  callback()
198
223
  }
199
224
  },
200
225
 
201
226
  /* receive no more text chunks (writable side of stream) */
202
- final (callback) {
227
+ final (callback: (error?: Error | null) => void) {
203
228
  if (self.closing) {
204
229
  callback()
205
230
  return
@@ -227,6 +252,7 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
227
252
  && element.type === "text-frame"
228
253
  && element.complete === true) {
229
254
  /* send all consecutive complete chunks */
255
+ let eofSeen = false
230
256
  while (true) {
231
257
  const nextElement = self.queueSend.peek()
232
258
  if (nextElement === undefined)
@@ -234,49 +260,43 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
234
260
  else if (nextElement.type === "text-eof") {
235
261
  this.push(null)
236
262
  self.queueSend.walk(+1)
263
+ eofSeen = true
237
264
  break
238
265
  }
239
266
  else if (nextElement.type === "text-frame"
240
267
  && nextElement.complete !== true)
241
268
  break
242
- self.log("info", `send text (${nextElement.chunk.kind}): ${JSON.stringify(nextElement.chunk.payload)}`)
269
+ self.log("info", `send text 1 (${nextElement.chunk.kind}): ${JSON.stringify(nextElement.chunk.payload)} pos=${self.queueSend.position()}`)
243
270
  this.push(nextElement.chunk)
244
271
  self.queueSend.walk(+1)
245
272
  self.queue.trim()
246
273
  }
274
+
275
+ /* wait for more data (unless end-of-stream was reached) */
276
+ if (!eofSeen && !self.closing)
277
+ self.queue.once("write", flushPendingChunks)
247
278
  }
248
279
  else if (element !== undefined
249
280
  && element.type === "text-frame"
250
- && element.preview === "pending") {
251
- /* send intermediate preview (without advancing pointer) */
281
+ && element.complete === false
282
+ && !previewed
283
+ && self.params.interim === true) {
284
+ /* merge together all still queued elements and
285
+ send this out as an intermediate chunk as preview */
252
286
  const previewChunk = element.chunk.clone()
253
287
  previewChunk.kind = "intermediate"
254
- self.log("info", `send text (intermediate preview): ${JSON.stringify(previewChunk.payload)}`)
255
- this.push(previewChunk)
256
- element.preview = "sent"
257
- self.queueSend.touch()
258
-
259
- /* start preview timeout (if configured) */
260
- const timeout = self.params.timeout as number
261
- if (timeout > 0 && self.previewTimer === null) {
262
- self.previewTimer = setTimeout(() => {
263
- self.previewTimer = null
264
- if (self.closing)
265
- return
266
-
267
- /* promote preview to final chunk */
268
- const el = self.queueSend.peek()
269
- if (el !== undefined
270
- && el.type === "text-frame"
271
- && el.preview === "sent"
272
- && el.complete !== true) {
273
- self.log("info", `timeout: promoting intermediate to final: ${JSON.stringify(el.chunk.payload)}`)
274
- el.complete = true
275
- self.queueSend.touch()
276
- self.queue.emit("write")
277
- }
278
- }, timeout)
288
+ for (let pos = self.queueSend.position() + 1; pos < self.queueSend.maxPosition(); pos++) {
289
+ const element2 = self.queueSend.peek(pos)
290
+ if (!element2)
291
+ continue
292
+ if (element2.type === "text-eof")
293
+ break
294
+ previewChunk.payload = self.concatPayload(
295
+ previewChunk.payload as string, element2.chunk.payload as string)
279
296
  }
297
+ this.push(previewChunk)
298
+ self.log("info", `send text 2 (intermediate): ${JSON.stringify(previewChunk.payload)}`)
299
+ previewed = true
280
300
 
281
301
  /* wait for more data */
282
302
  if (!self.closing)
@@ -300,10 +320,6 @@ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
300
320
  clearTimeout(this.workingOffTimer)
301
321
  this.workingOffTimer = null
302
322
  }
303
- if (this.previewTimer !== null) {
304
- clearTimeout(this.previewTimer)
305
- this.previewTimer = null
306
- }
307
323
 
308
324
  /* remove any pending event listeners */
309
325
  this.queue.removeAllListeners("write")
@@ -94,6 +94,10 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
94
94
  const chunks: Buffer[] = []
95
95
  const maxBodySize = 1024 * 1024 /* 1 MB limit for SDP */
96
96
  let totalSize = 0
97
+ const onError = (err: Error) =>
98
+ reject(err)
99
+ const onEnd = () =>
100
+ resolve(Buffer.concat(chunks).toString("utf8"))
97
101
  const onData = (chunk: Buffer) => {
98
102
  totalSize += chunk.length
99
103
  if (totalSize > maxBodySize) {
@@ -106,10 +110,6 @@ export default class SpeechFlowNodeXIOWebRTC extends SpeechFlowNode {
106
110
  }
107
111
  chunks.push(chunk)
108
112
  }
109
- const onEnd = () =>
110
- resolve(Buffer.concat(chunks).toString("utf8"))
111
- const onError = (err: Error) =>
112
- reject(err)
113
113
  req.on("data", onData)
114
114
  req.on("end", onEnd)
115
115
  req.on("error", onError)