speechflow 1.6.7 → 1.7.1

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 (152) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +77 -52
  3. package/etc/secretlint.json +7 -0
  4. package/etc/speechflow.yaml +13 -4
  5. package/etc/stx.conf +3 -2
  6. package/package.json +8 -6
  7. package/speechflow-cli/dst/speechflow-main-api.js +9 -8
  8. package/speechflow-cli/dst/speechflow-main-api.js.map +1 -1
  9. package/speechflow-cli/dst/speechflow-main-graph.js +13 -14
  10. package/speechflow-cli/dst/speechflow-main-graph.js.map +1 -1
  11. package/speechflow-cli/dst/speechflow-main-status.js +38 -8
  12. package/speechflow-cli/dst/speechflow-main-status.js.map +1 -1
  13. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +3 -0
  14. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -1
  15. package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +4 -2
  16. package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -1
  17. package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +1 -1
  18. package/speechflow-cli/dst/speechflow-node-a2a-expander.js +4 -2
  19. package/speechflow-cli/dst/speechflow-node-a2a-expander.js.map +1 -1
  20. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js +2 -2
  21. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js.map +1 -1
  22. package/speechflow-cli/dst/speechflow-node-a2a-filler.js +46 -17
  23. package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -1
  24. package/speechflow-cli/dst/speechflow-node-a2a-gain.js +0 -5
  25. package/speechflow-cli/dst/speechflow-node-a2a-gain.js.map +1 -1
  26. package/speechflow-cli/dst/speechflow-node-a2a-gender.js +3 -4
  27. package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
  28. package/speechflow-cli/dst/speechflow-node-a2a-mute.js +0 -5
  29. package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
  30. package/speechflow-cli/dst/speechflow-node-a2a-pitch.js +1 -2
  31. package/speechflow-cli/dst/speechflow-node-a2a-pitch.js.map +1 -1
  32. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +0 -5
  33. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -1
  34. package/speechflow-cli/dst/speechflow-node-a2a-speex.js +0 -5
  35. package/speechflow-cli/dst/speechflow-node-a2a-speex.js.map +1 -1
  36. package/speechflow-cli/dst/speechflow-node-a2a-wav.js +8 -2
  37. package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -1
  38. package/speechflow-cli/dst/speechflow-node-a2t-amazon.d.ts +0 -1
  39. package/speechflow-cli/dst/speechflow-node-a2t-amazon.js +17 -19
  40. package/speechflow-cli/dst/speechflow-node-a2t-amazon.js.map +1 -1
  41. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.d.ts +0 -1
  42. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +30 -25
  43. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  44. package/speechflow-cli/dst/speechflow-node-a2t-openai.js +79 -48
  45. package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
  46. package/speechflow-cli/dst/speechflow-node-t2a-amazon.js +6 -11
  47. package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -1
  48. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +45 -44
  49. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
  50. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.d.ts +2 -0
  51. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +19 -7
  52. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
  53. package/speechflow-cli/dst/speechflow-node-t2t-amazon.js +1 -2
  54. package/speechflow-cli/dst/speechflow-node-t2t-amazon.js.map +1 -1
  55. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +0 -1
  56. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
  57. package/speechflow-cli/dst/speechflow-node-t2t-format.js +0 -1
  58. package/speechflow-cli/dst/speechflow-node-t2t-format.js.map +1 -1
  59. package/speechflow-cli/dst/speechflow-node-t2t-google.js +0 -1
  60. package/speechflow-cli/dst/speechflow-node-t2t-google.js.map +1 -1
  61. package/speechflow-cli/dst/speechflow-node-t2t-modify.js +0 -1
  62. package/speechflow-cli/dst/speechflow-node-t2t-modify.js.map +1 -1
  63. package/speechflow-cli/dst/speechflow-node-t2t-ollama.js +0 -1
  64. package/speechflow-cli/dst/speechflow-node-t2t-ollama.js.map +1 -1
  65. package/speechflow-cli/dst/speechflow-node-t2t-openai.js +0 -1
  66. package/speechflow-cli/dst/speechflow-node-t2t-openai.js.map +1 -1
  67. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +173 -29
  68. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
  69. package/speechflow-cli/dst/speechflow-node-x2x-filter.d.ts +1 -0
  70. package/speechflow-cli/dst/speechflow-node-x2x-filter.js +10 -1
  71. package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
  72. package/speechflow-cli/dst/speechflow-node-x2x-trace.js +0 -5
  73. package/speechflow-cli/dst/speechflow-node-x2x-trace.js.map +1 -1
  74. package/speechflow-cli/dst/speechflow-node-xio-device.js +5 -5
  75. package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
  76. package/speechflow-cli/dst/speechflow-node-xio-file.js +4 -4
  77. package/speechflow-cli/dst/speechflow-node-xio-file.js.map +1 -1
  78. package/speechflow-cli/dst/speechflow-node-xio-mqtt.js +9 -3
  79. package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -1
  80. package/speechflow-cli/dst/speechflow-node-xio-websocket.js +16 -5
  81. package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
  82. package/speechflow-cli/dst/speechflow-util-audio.js +3 -3
  83. package/speechflow-cli/dst/speechflow-util-audio.js.map +1 -1
  84. package/speechflow-cli/dst/speechflow-util-error.d.ts +0 -1
  85. package/speechflow-cli/dst/speechflow-util-error.js +0 -7
  86. package/speechflow-cli/dst/speechflow-util-error.js.map +1 -1
  87. package/speechflow-cli/dst/speechflow-util-misc.d.ts +2 -0
  88. package/speechflow-cli/dst/speechflow-util-misc.js +26 -0
  89. package/speechflow-cli/dst/speechflow-util-misc.js.map +1 -0
  90. package/speechflow-cli/dst/speechflow-util-queue.d.ts +9 -2
  91. package/speechflow-cli/dst/speechflow-util-queue.js +36 -15
  92. package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -1
  93. package/speechflow-cli/dst/speechflow-util-stream.d.ts +2 -2
  94. package/speechflow-cli/dst/speechflow-util-stream.js +17 -19
  95. package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -1
  96. package/speechflow-cli/dst/speechflow-util.d.ts +1 -0
  97. package/speechflow-cli/dst/speechflow-util.js +1 -0
  98. package/speechflow-cli/dst/speechflow-util.js.map +1 -1
  99. package/speechflow-cli/etc/oxlint.jsonc +6 -1
  100. package/speechflow-cli/etc/stx.conf +1 -0
  101. package/speechflow-cli/package.json +28 -27
  102. package/speechflow-cli/src/speechflow-main-api.ts +9 -11
  103. package/speechflow-cli/src/speechflow-main-graph.ts +15 -16
  104. package/speechflow-cli/src/speechflow-main-status.ts +6 -10
  105. package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +4 -0
  106. package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +4 -2
  107. package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +1 -1
  108. package/speechflow-cli/src/speechflow-node-a2a-expander.ts +4 -2
  109. package/speechflow-cli/src/speechflow-node-a2a-ffmpeg.ts +4 -2
  110. package/speechflow-cli/src/speechflow-node-a2a-filler.ts +57 -20
  111. package/speechflow-cli/src/speechflow-node-a2a-gain.ts +0 -5
  112. package/speechflow-cli/src/speechflow-node-a2a-gender.ts +3 -4
  113. package/speechflow-cli/src/speechflow-node-a2a-mute.ts +0 -5
  114. package/speechflow-cli/src/speechflow-node-a2a-pitch.ts +1 -2
  115. package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +0 -5
  116. package/speechflow-cli/src/speechflow-node-a2a-speex.ts +0 -5
  117. package/speechflow-cli/src/speechflow-node-a2a-wav.ts +9 -3
  118. package/speechflow-cli/src/speechflow-node-a2t-amazon.ts +27 -27
  119. package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +37 -28
  120. package/speechflow-cli/src/speechflow-node-a2t-openai.ts +92 -56
  121. package/speechflow-cli/src/speechflow-node-t2a-amazon.ts +7 -11
  122. package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +47 -43
  123. package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +22 -7
  124. package/speechflow-cli/src/speechflow-node-t2t-amazon.ts +1 -2
  125. package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +0 -1
  126. package/speechflow-cli/src/speechflow-node-t2t-format.ts +0 -1
  127. package/speechflow-cli/src/speechflow-node-t2t-google.ts +0 -1
  128. package/speechflow-cli/src/speechflow-node-t2t-modify.ts +0 -1
  129. package/speechflow-cli/src/speechflow-node-t2t-ollama.ts +0 -1
  130. package/speechflow-cli/src/speechflow-node-t2t-openai.ts +0 -1
  131. package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +205 -33
  132. package/speechflow-cli/src/speechflow-node-x2x-filter.ts +16 -4
  133. package/speechflow-cli/src/speechflow-node-x2x-trace.ts +3 -8
  134. package/speechflow-cli/src/speechflow-node-xio-device.ts +6 -9
  135. package/speechflow-cli/src/speechflow-node-xio-file.ts +4 -4
  136. package/speechflow-cli/src/speechflow-node-xio-mqtt.ts +10 -4
  137. package/speechflow-cli/src/speechflow-node-xio-websocket.ts +16 -5
  138. package/speechflow-cli/src/speechflow-util-audio-wt.ts +4 -4
  139. package/speechflow-cli/src/speechflow-util-audio.ts +7 -7
  140. package/speechflow-cli/src/speechflow-util-error.ts +0 -7
  141. package/speechflow-cli/src/speechflow-util-misc.ts +23 -0
  142. package/speechflow-cli/src/speechflow-util-queue.ts +40 -20
  143. package/speechflow-cli/src/speechflow-util-stream.ts +29 -24
  144. package/speechflow-cli/src/speechflow-util.ts +1 -0
  145. package/speechflow-ui-db/dst/index.css +1 -5
  146. package/speechflow-ui-db/dst/index.js +14 -58
  147. package/speechflow-ui-db/etc/stx.conf +5 -16
  148. package/speechflow-ui-db/package.json +16 -15
  149. package/speechflow-ui-st/dst/index.css +1 -5
  150. package/speechflow-ui-st/dst/index.js +31 -160
  151. package/speechflow-ui-st/etc/stx.conf +5 -16
  152. package/speechflow-ui-st/package.json +17 -16
@@ -91,7 +91,7 @@ export function convertBufToI16 (buf: Buffer, littleEndian = true) {
91
91
  return arr
92
92
  }
93
93
 
94
- /* helper function: convert In16Array in PCM/I16 to Buffer */
94
+ /* helper function: convert Int16Array in PCM/I16 to Buffer */
95
95
  export function convertI16ToBuf (arr: Int16Array, littleEndian = true) {
96
96
  if (arr.length === 0)
97
97
  return Buffer.alloc(0)
@@ -133,7 +133,7 @@ export async function processInt16ArrayInSegments (
133
133
  }
134
134
 
135
135
  /* update envelope (smoothed amplitude contour) for single channel */
136
- export function updateEnvelopeForChannel(
136
+ export function updateEnvelopeForChannel (
137
137
  env: number[],
138
138
  sampleRate: number,
139
139
  chan: number,
@@ -182,7 +182,7 @@ export class WebAudio {
182
182
  }>()
183
183
 
184
184
  /* construct object */
185
- constructor(
185
+ constructor (
186
186
  public sampleRate: number,
187
187
  public channels: number
188
188
  ) {
@@ -215,7 +215,7 @@ export class WebAudio {
215
215
  numberOfInputs: 1,
216
216
  numberOfOutputs: 0
217
217
  })
218
- this.captureNode!.port.addEventListener("message", (event) => {
218
+ this.captureNode.port.addEventListener("message", (event) => {
219
219
  const { type, chunkId, data } = event.data ?? {}
220
220
  if (type === "capture-complete") {
221
221
  const promise = this.pendingPromises.get(chunkId)
@@ -232,7 +232,7 @@ export class WebAudio {
232
232
 
233
233
  /* start ports */
234
234
  this.sourceNode.port.start()
235
- this.captureNode!.port.start()
235
+ this.captureNode.port.start()
236
236
  }
237
237
 
238
238
  /* process single audio chunk */
@@ -242,7 +242,7 @@ export class WebAudio {
242
242
  const timeout = setTimeout(() => {
243
243
  this.pendingPromises.delete(chunkId)
244
244
  reject(new Error("processing timeout"))
245
- }, (int16Array.length / this.audioContext.sampleRate) * 1000 + 250)
245
+ }, (int16Array.length / this.channels / this.audioContext.sampleRate) * 1000 + 250)
246
246
  if (this.captureNode !== null)
247
247
  this.pendingPromises.set(chunkId, { resolve, reject, timeout })
248
248
  try {
@@ -252,7 +252,7 @@ export class WebAudio {
252
252
 
253
253
  /* start capture first */
254
254
  if (this.captureNode !== null) {
255
- this.captureNode?.port.postMessage({
255
+ this.captureNode.port.postMessage({
256
256
  type: "start-capture",
257
257
  chunkId,
258
258
  expectedSamples: int16Array.length
@@ -4,13 +4,6 @@
4
4
  ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
5
5
  */
6
6
 
7
- /* helper function for promise-based timeout */
8
- export function timeoutPromise<T = void> (duration: number = 10 * 1000, info = "timeout") {
9
- return new Promise<T>((resolve, reject) => {
10
- setTimeout(() => { reject(new Error(info)) }, duration)
11
- })
12
- }
13
-
14
7
  /* helper function for retrieving an Error object */
15
8
  export function ensureError (error: unknown, prefix?: string, debug = false): Error {
16
9
  if (error instanceof Error && prefix === undefined && debug === false)
@@ -0,0 +1,23 @@
1
+ /*
2
+ ** SpeechFlow - Speech Processing Flow Graph
3
+ ** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
4
+ ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
5
+ */
6
+
7
+ /* sleep: wait a duration of time and then resolve */
8
+ export function sleep (durationMs: number) {
9
+ return new Promise<void>((resolve) => {
10
+ setTimeout(() => {
11
+ resolve()
12
+ }, durationMs)
13
+ })
14
+ }
15
+
16
+ /* timeout: wait a duration of time and then reject */
17
+ export function timeout (durationMs: number, info = "timeout") {
18
+ return new Promise<never>((_resolve, reject) => {
19
+ setTimeout(() => {
20
+ reject(new Error(info))
21
+ }, durationMs)
22
+ })
23
+ }
@@ -34,12 +34,10 @@ export class SingleQueue<T> extends EventEmitter {
34
34
  this.emit("dequeue")
35
35
  }
36
36
  read () {
37
- return new Promise<T>((resolve, reject) => {
38
- const consume = () =>
39
- this.queue.length > 0 ? this.queue.pop()! : null
37
+ return new Promise<T>((resolve) => {
40
38
  const tryToConsume = () => {
41
- const item = consume()
42
- if (item !== null)
39
+ const item = this.queue.pop()
40
+ if (item !== undefined)
43
41
  resolve(item)
44
42
  else
45
43
  this.once("dequeue", tryToConsume)
@@ -47,6 +45,11 @@ export class SingleQueue<T> extends EventEmitter {
47
45
  tryToConsume()
48
46
  })
49
47
  }
48
+ drain () {
49
+ const items = this.queue
50
+ this.queue = new Array<T>()
51
+ return items
52
+ }
50
53
  }
51
54
 
52
55
  /* helper class for double-item queue */
@@ -66,18 +69,18 @@ export class DoubleQueue<T0, T1> extends EventEmitter {
66
69
  this.notify()
67
70
  }
68
71
  read () {
69
- return new Promise<[ T0, T1 ]>((resolve, reject) => {
70
- const consume = (): [ T0, T1 ] | null => {
72
+ return new Promise<[ T0, T1 ]>((resolve) => {
73
+ const consume = (): [ T0, T1 ] | undefined => {
71
74
  if (this.queue0.length > 0 && this.queue1.length > 0) {
72
75
  const item0 = this.queue0.pop() as T0
73
76
  const item1 = this.queue1.pop() as T1
74
77
  return [ item0, item1 ]
75
78
  }
76
- return null
79
+ return undefined
77
80
  }
78
81
  const tryToConsume = () => {
79
82
  const items = consume()
80
- if (items !== null)
83
+ if (items !== undefined)
81
84
  resolve(items)
82
85
  else
83
86
  this.once("dequeue", tryToConsume)
@@ -87,7 +90,7 @@ export class DoubleQueue<T0, T1> extends EventEmitter {
87
90
  }
88
91
  }
89
92
 
90
- /* queue element */
93
+ /* queue element */
91
94
  export type QueueElement = { type: string }
92
95
 
93
96
  /* queue pointer */
@@ -225,7 +228,7 @@ export class Queue<T extends QueueElement> extends EventEmitter {
225
228
  }
226
229
  pointerDelete (name: string): void {
227
230
  if (!this.pointers.has(name))
228
- throw new Error("pointer not exists")
231
+ throw new Error("pointer does not exist")
229
232
  this.pointers.delete(name)
230
233
  }
231
234
  trim (): void {
@@ -273,12 +276,12 @@ export class TimeStore<T> extends EventEmitter {
273
276
 
274
277
  /* asynchronous queue */
275
278
  export class AsyncQueue<T> {
276
- private queue: Array<T | null> = []
277
- private resolvers: ((v: T | null) => void)[] = []
278
- write (v: T | null) {
279
- const resolve = this.resolvers.shift()
280
- if (resolve)
281
- resolve(v)
279
+ private queue: Array<T> = []
280
+ private resolvers: { resolve: (v: T) => void, reject: (err: Error) => void }[] = []
281
+ write (v: T) {
282
+ const resolver = this.resolvers.shift()
283
+ if (resolver)
284
+ resolver.resolve(v)
282
285
  else
283
286
  this.queue.push(v)
284
287
  }
@@ -286,11 +289,14 @@ export class AsyncQueue<T> {
286
289
  if (this.queue.length > 0)
287
290
  return this.queue.shift()!
288
291
  else
289
- return new Promise<T | null>((resolve) => this.resolvers.push(resolve))
292
+ return new Promise<T>((resolve, reject) => this.resolvers.push({ resolve, reject }))
293
+ }
294
+ empty () {
295
+ return this.queue.length === 0
290
296
  }
291
297
  destroy () {
292
- for (const resolve of this.resolvers)
293
- resolve(null)
298
+ for (const resolver of this.resolvers)
299
+ resolver.reject(new Error("AsyncQueue destroyed"))
294
300
  this.resolvers = []
295
301
  this.queue = []
296
302
  }
@@ -318,3 +324,17 @@ export class CachedRegExp {
318
324
  return this.cache.size
319
325
  }
320
326
  }
327
+
328
+ /* set of promises */
329
+ export class PromiseSet<T> {
330
+ private promises = new Set<Promise<T>>()
331
+ add (promise: Promise<T>) {
332
+ this.promises.add(promise)
333
+ promise.finally(() => {
334
+ this.promises.delete(promise)
335
+ }).catch(() => {})
336
+ }
337
+ async awaitAll () {
338
+ await Promise.all(this.promises)
339
+ }
340
+ }
@@ -16,38 +16,43 @@ import { SpeechFlowChunk } from "./speechflow-node"
16
16
  import * as util from "./speechflow-util"
17
17
 
18
18
  /* create a Duplex/Transform stream which has
19
- object-mode on Writable side and buffer/string-mode on Readable side */
20
- export function createTransformStreamForWritableSide () {
19
+ object-mode on Writable side and
20
+ buffer/string-mode on Readable side */
21
+ export function createTransformStreamForWritableSide (
22
+ type: "text" | "audio",
23
+ readableHighWaterMark?: number
24
+ ) {
21
25
  return new Stream.Transform({
22
- readableObjectMode: true,
23
- writableObjectMode: true,
24
- decodeStrings: false,
25
- highWaterMark: 1,
26
+ writableObjectMode: true,
27
+ readableObjectMode: false,
28
+ writableHighWaterMark: 1,
29
+ readableHighWaterMark: readableHighWaterMark ?? (type === "audio" ? 19200 /* 400ms */ : 65536 /* 64KB */),
30
+ decodeStrings: false,
26
31
  transform (chunk: SpeechFlowChunk, encoding, callback) {
27
32
  this.push(chunk.payload)
28
33
  callback()
29
34
  },
30
35
  final (callback) {
31
- this.push(null)
32
36
  callback()
33
37
  }
34
38
  })
35
39
  }
36
40
 
37
41
  /* create a Duplex/Transform stream which has
38
- object-mode on Readable side and buffer/string-mode on Writable side */
39
- export function createTransformStreamForReadableSide (type: "text" | "audio", getTimeZero: () => DateTime, highWaterMark?: number) {
42
+ buffer/string-mode on Writable side and
43
+ object-mode on Readable side */
44
+ export function createTransformStreamForReadableSide (
45
+ type: "text" | "audio",
46
+ getTimeZero: () => DateTime,
47
+ writableHighWaterMark?: number
48
+ ) {
40
49
  return new Stream.Transform({
41
- readableObjectMode: true,
42
- writableObjectMode: true,
43
- decodeStrings: false,
44
- highWaterMark: highWaterMark ?? (type === "audio" ? 19200 /* 400ms */: 65536 /* 64KB */),
50
+ writableObjectMode: false,
51
+ readableObjectMode: true,
52
+ writableHighWaterMark: writableHighWaterMark ?? (type === "audio" ? 19200 /* 400ms */ : 65536 /* 64KB */),
53
+ readableHighWaterMark: 1,
54
+ decodeStrings: false,
45
55
  transform (chunk: Buffer | string, encoding, callback) {
46
- if (chunk === null) {
47
- this.push(null)
48
- callback()
49
- return
50
- }
51
56
  const timeZero = getTimeZero()
52
57
  const start = DateTime.now().diff(timeZero)
53
58
  let end = start
@@ -61,7 +66,6 @@ export function createTransformStreamForReadableSide (type: "text" | "audio", ge
61
66
  callback()
62
67
  },
63
68
  final (callback) {
64
- this.push(null)
65
69
  callback()
66
70
  }
67
71
  })
@@ -110,8 +114,7 @@ export function streamChunkEncode (chunk: SpeechFlowChunk) {
110
114
  }
111
115
  if (chunk.meta.size > 0)
112
116
  data.meta = Array.from(chunk.meta.entries())
113
- const _data = CBOR.encode(data)
114
- return _data
117
+ return CBOR.encode(data)
115
118
  }
116
119
 
117
120
  /* decode/unserialize chunk of data */
@@ -201,7 +204,7 @@ export class StreamWrapper extends Stream.Transform {
201
204
  }
202
205
 
203
206
  /* helper function for destruction of a stream */
204
- export async function destroyStream(
207
+ export async function destroyStream (
205
208
  stream: Stream.Readable | Stream.Writable | Stream.Duplex | Stream.Transform
206
209
  ) {
207
210
  /* signal the end for a writable stream */
@@ -214,8 +217,10 @@ export async function destroyStream(
214
217
  new Promise<void>((resolve) => {
215
218
  stream.end(() => { resolve() })
216
219
  }),
217
- util.timeoutPromise(5000, "stream end timeout")
218
- ])
220
+ util.timeout(5000, "stream end timeout")
221
+ ]).catch(() => {
222
+ /* ignore timeout -- stream will be destroyed anyway */
223
+ })
219
224
 
220
225
  /* destroy the stream */
221
226
  stream.destroy()
@@ -8,3 +8,4 @@ export * from "./speechflow-util-audio"
8
8
  export * from "./speechflow-util-error"
9
9
  export * from "./speechflow-util-stream"
10
10
  export * from "./speechflow-util-queue"
11
+ export * from "./speechflow-util-misc"