speechflow 1.5.1 → 1.6.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 (232) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +192 -171
  3. package/etc/claude.md +83 -46
  4. package/etc/speechflow.yaml +84 -84
  5. package/package.json +3 -3
  6. package/speechflow-cli/dst/speechflow-main-api.d.ts +12 -0
  7. package/speechflow-cli/dst/speechflow-main-api.js +319 -0
  8. package/speechflow-cli/dst/speechflow-main-api.js.map +1 -0
  9. package/speechflow-cli/dst/speechflow-main-cli.d.ts +28 -0
  10. package/speechflow-cli/dst/speechflow-main-cli.js +271 -0
  11. package/speechflow-cli/dst/speechflow-main-cli.js.map +1 -0
  12. package/speechflow-cli/dst/speechflow-main-config.d.ts +9 -0
  13. package/speechflow-cli/dst/speechflow-main-config.js +27 -0
  14. package/speechflow-cli/dst/speechflow-main-config.js.map +1 -0
  15. package/speechflow-cli/dst/speechflow-main-graph.d.ts +34 -0
  16. package/speechflow-cli/dst/speechflow-main-graph.js +367 -0
  17. package/speechflow-cli/dst/speechflow-main-graph.js.map +1 -0
  18. package/speechflow-cli/dst/speechflow-main-nodes.d.ts +10 -0
  19. package/speechflow-cli/dst/speechflow-main-nodes.js +60 -0
  20. package/speechflow-cli/dst/speechflow-main-nodes.js.map +1 -0
  21. package/speechflow-cli/dst/speechflow-main-status.d.ts +11 -0
  22. package/speechflow-cli/dst/speechflow-main-status.js +60 -0
  23. package/speechflow-cli/dst/speechflow-main-status.js.map +1 -0
  24. package/speechflow-cli/dst/speechflow-main.d.ts +7 -0
  25. package/speechflow-cli/dst/speechflow-main.js +127 -0
  26. package/speechflow-cli/dst/speechflow-main.js.map +1 -0
  27. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +4 -4
  28. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -1
  29. package/speechflow-cli/dst/speechflow-node-a2a-compressor.d.ts +1 -1
  30. package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +8 -9
  31. package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -1
  32. package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +5 -5
  33. package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js.map +1 -1
  34. package/speechflow-cli/dst/speechflow-node-a2a-expander.d.ts +1 -1
  35. package/speechflow-cli/dst/speechflow-node-a2a-expander.js +8 -9
  36. package/speechflow-cli/dst/speechflow-node-a2a-expander.js.map +1 -1
  37. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.d.ts +1 -1
  38. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js +8 -8
  39. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js.map +1 -1
  40. package/speechflow-cli/dst/speechflow-node-a2a-filler.d.ts +1 -1
  41. package/speechflow-cli/dst/speechflow-node-a2a-filler.js +6 -6
  42. package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -1
  43. package/speechflow-cli/dst/speechflow-node-a2a-gain.d.ts +1 -1
  44. package/speechflow-cli/dst/speechflow-node-a2a-gain.js +5 -5
  45. package/speechflow-cli/dst/speechflow-node-a2a-gain.js.map +1 -1
  46. package/speechflow-cli/dst/speechflow-node-a2a-gender.d.ts +1 -1
  47. package/speechflow-cli/dst/speechflow-node-a2a-gender.js +7 -7
  48. package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
  49. package/speechflow-cli/dst/speechflow-node-a2a-meter.d.ts +1 -1
  50. package/speechflow-cli/dst/speechflow-node-a2a-meter.js +5 -5
  51. package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -1
  52. package/speechflow-cli/dst/speechflow-node-a2a-mute.d.ts +1 -1
  53. package/speechflow-cli/dst/speechflow-node-a2a-mute.js +3 -3
  54. package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
  55. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.d.ts +1 -1
  56. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +7 -7
  57. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -1
  58. package/speechflow-cli/dst/speechflow-node-a2a-speex.d.ts +1 -1
  59. package/speechflow-cli/dst/speechflow-node-a2a-speex.js +7 -7
  60. package/speechflow-cli/dst/speechflow-node-a2a-speex.js.map +1 -1
  61. package/speechflow-cli/dst/speechflow-node-a2a-vad.d.ts +1 -1
  62. package/speechflow-cli/dst/speechflow-node-a2a-vad.js +7 -7
  63. package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
  64. package/speechflow-cli/dst/speechflow-node-a2a-wav.d.ts +1 -1
  65. package/speechflow-cli/dst/speechflow-node-a2a-wav.js +3 -3
  66. package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -1
  67. package/speechflow-cli/dst/{speechflow-node-a2t-awstranscribe.d.ts → speechflow-node-a2t-amazon.d.ts} +1 -1
  68. package/speechflow-cli/dst/{speechflow-node-a2t-awstranscribe.js → speechflow-node-a2t-amazon.js} +11 -11
  69. package/speechflow-cli/dst/speechflow-node-a2t-amazon.js.map +1 -0
  70. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.d.ts +1 -1
  71. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +7 -7
  72. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  73. package/speechflow-cli/dst/{speechflow-node-a2t-openaitranscribe.d.ts → speechflow-node-a2t-openai.d.ts} +1 -1
  74. package/speechflow-cli/dst/{speechflow-node-a2t-openaitranscribe.js → speechflow-node-a2t-openai.js} +11 -11
  75. package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -0
  76. package/speechflow-cli/dst/{speechflow-node-t2a-awspolly.d.ts → speechflow-node-t2a-amazon.d.ts} +1 -1
  77. package/speechflow-cli/dst/{speechflow-node-t2a-awspolly.js → speechflow-node-t2a-amazon.js} +9 -9
  78. package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -0
  79. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.d.ts +1 -1
  80. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +5 -5
  81. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
  82. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.d.ts +1 -1
  83. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +7 -7
  84. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
  85. package/speechflow-cli/dst/{speechflow-node-t2t-awstranslate.d.ts → speechflow-node-t2t-amazon.d.ts} +1 -1
  86. package/speechflow-cli/dst/{speechflow-node-t2t-awstranslate.js → speechflow-node-t2t-amazon.js} +7 -7
  87. package/speechflow-cli/dst/speechflow-node-t2t-amazon.js.map +1 -0
  88. package/speechflow-cli/dst/speechflow-node-t2t-deepl.d.ts +1 -1
  89. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +5 -5
  90. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
  91. package/speechflow-cli/dst/speechflow-node-t2t-format.d.ts +1 -1
  92. package/speechflow-cli/dst/speechflow-node-t2t-format.js +3 -3
  93. package/speechflow-cli/dst/speechflow-node-t2t-format.js.map +1 -1
  94. package/speechflow-cli/dst/speechflow-node-t2t-google.d.ts +1 -1
  95. package/speechflow-cli/dst/speechflow-node-t2t-google.js +8 -8
  96. package/speechflow-cli/dst/speechflow-node-t2t-google.js.map +1 -1
  97. package/speechflow-cli/dst/{speechflow-node-a2a-dynamics.d.ts → speechflow-node-t2t-modify.d.ts} +1 -5
  98. package/speechflow-cli/dst/speechflow-node-t2t-modify.js +111 -0
  99. package/speechflow-cli/dst/speechflow-node-t2t-modify.js.map +1 -0
  100. package/speechflow-cli/dst/speechflow-node-t2t-ollama.d.ts +1 -1
  101. package/speechflow-cli/dst/speechflow-node-t2t-ollama.js +5 -5
  102. package/speechflow-cli/dst/speechflow-node-t2t-ollama.js.map +1 -1
  103. package/speechflow-cli/dst/speechflow-node-t2t-openai.d.ts +1 -1
  104. package/speechflow-cli/dst/speechflow-node-t2t-openai.js +5 -5
  105. package/speechflow-cli/dst/speechflow-node-t2t-openai.js.map +1 -1
  106. package/speechflow-cli/dst/speechflow-node-t2t-sentence.d.ts +1 -1
  107. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +5 -5
  108. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
  109. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.d.ts +1 -1
  110. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +5 -5
  111. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
  112. package/speechflow-cli/dst/speechflow-node-t2t-transformers.d.ts +1 -1
  113. package/speechflow-cli/dst/speechflow-node-t2t-transformers.js +5 -5
  114. package/speechflow-cli/dst/speechflow-node-t2t-transformers.js.map +1 -1
  115. package/speechflow-cli/dst/speechflow-node-x2x-filter.d.ts +1 -1
  116. package/speechflow-cli/dst/speechflow-node-x2x-filter.js +5 -5
  117. package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
  118. package/speechflow-cli/dst/speechflow-node-x2x-trace.d.ts +1 -1
  119. package/speechflow-cli/dst/speechflow-node-x2x-trace.js +3 -3
  120. package/speechflow-cli/dst/speechflow-node-x2x-trace.js.map +1 -1
  121. package/speechflow-cli/dst/speechflow-node-xio-device.d.ts +1 -1
  122. package/speechflow-cli/dst/speechflow-node-xio-device.js +8 -8
  123. package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
  124. package/speechflow-cli/dst/speechflow-node-xio-file.d.ts +1 -1
  125. package/speechflow-cli/dst/speechflow-node-xio-file.js +50 -29
  126. package/speechflow-cli/dst/speechflow-node-xio-file.js.map +1 -1
  127. package/speechflow-cli/dst/speechflow-node-xio-mqtt.d.ts +1 -1
  128. package/speechflow-cli/dst/speechflow-node-xio-mqtt.js +7 -7
  129. package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -1
  130. package/speechflow-cli/dst/speechflow-node-xio-websocket.d.ts +1 -1
  131. package/speechflow-cli/dst/speechflow-node-xio-websocket.js +10 -10
  132. package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
  133. package/speechflow-cli/dst/{speechflow-utils-audio-wt.js → speechflow-util-audio-wt.js} +1 -1
  134. package/speechflow-cli/dst/speechflow-util-audio-wt.js.map +1 -0
  135. package/speechflow-cli/dst/speechflow-util-audio.d.ts +22 -0
  136. package/speechflow-cli/dst/speechflow-util-audio.js +251 -0
  137. package/speechflow-cli/dst/speechflow-util-audio.js.map +1 -0
  138. package/speechflow-cli/dst/speechflow-util-error.d.ts +14 -0
  139. package/speechflow-cli/dst/speechflow-util-error.js +131 -0
  140. package/speechflow-cli/dst/speechflow-util-error.js.map +1 -0
  141. package/speechflow-cli/dst/speechflow-util-queue.d.ts +68 -0
  142. package/speechflow-cli/dst/speechflow-util-queue.js +338 -0
  143. package/speechflow-cli/dst/speechflow-util-queue.js.map +1 -0
  144. package/speechflow-cli/dst/speechflow-util-stream.d.ts +18 -0
  145. package/speechflow-cli/dst/speechflow-util-stream.js +219 -0
  146. package/speechflow-cli/dst/speechflow-util-stream.js.map +1 -0
  147. package/speechflow-cli/dst/speechflow-util-webaudio-wt.js +124 -0
  148. package/speechflow-cli/dst/speechflow-util-webaudio-wt.js.map +1 -0
  149. package/speechflow-cli/dst/{speechflow-utils-audio.js → speechflow-util-webaudio.js} +2 -2
  150. package/speechflow-cli/dst/speechflow-util-webaudio.js.map +1 -0
  151. package/speechflow-cli/dst/speechflow-util.d.ts +4 -0
  152. package/speechflow-cli/dst/speechflow-util.js +26 -0
  153. package/speechflow-cli/dst/speechflow-util.js.map +1 -0
  154. package/speechflow-cli/dst/speechflow.js +3 -906
  155. package/speechflow-cli/dst/speechflow.js.map +1 -1
  156. package/speechflow-cli/etc/oxlint.jsonc +4 -1
  157. package/speechflow-cli/package.json +12 -11
  158. package/speechflow-cli/src/speechflow-main-api.ts +315 -0
  159. package/speechflow-cli/src/speechflow-main-cli.ts +259 -0
  160. package/speechflow-cli/src/speechflow-main-config.ts +17 -0
  161. package/speechflow-cli/src/speechflow-main-graph.ts +372 -0
  162. package/speechflow-cli/src/speechflow-main-nodes.ts +61 -0
  163. package/speechflow-cli/src/speechflow-main-status.ts +70 -0
  164. package/speechflow-cli/src/speechflow-main.ts +106 -0
  165. package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +4 -4
  166. package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +7 -8
  167. package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +5 -5
  168. package/speechflow-cli/src/speechflow-node-a2a-expander.ts +7 -8
  169. package/speechflow-cli/src/speechflow-node-a2a-ffmpeg.ts +7 -7
  170. package/speechflow-cli/src/speechflow-node-a2a-filler.ts +6 -6
  171. package/speechflow-cli/src/speechflow-node-a2a-gain.ts +4 -4
  172. package/speechflow-cli/src/speechflow-node-a2a-gender.ts +6 -6
  173. package/speechflow-cli/src/speechflow-node-a2a-meter.ts +4 -4
  174. package/speechflow-cli/src/speechflow-node-a2a-mute.ts +2 -2
  175. package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +6 -6
  176. package/speechflow-cli/src/speechflow-node-a2a-speex.ts +6 -6
  177. package/speechflow-cli/src/speechflow-node-a2a-vad.ts +6 -6
  178. package/speechflow-cli/src/speechflow-node-a2a-wav.ts +2 -2
  179. package/speechflow-cli/src/{speechflow-node-a2t-awstranscribe.ts → speechflow-node-a2t-amazon.ts} +10 -10
  180. package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +7 -7
  181. package/speechflow-cli/src/{speechflow-node-a2t-openaitranscribe.ts → speechflow-node-a2t-openai.ts} +10 -10
  182. package/speechflow-cli/src/{speechflow-node-t2a-awspolly.ts → speechflow-node-t2a-amazon.ts} +7 -7
  183. package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +4 -4
  184. package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +6 -6
  185. package/speechflow-cli/src/{speechflow-node-t2t-awstranslate.ts → speechflow-node-t2t-amazon.ts} +5 -5
  186. package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +4 -4
  187. package/speechflow-cli/src/speechflow-node-t2t-format.ts +2 -2
  188. package/speechflow-cli/src/speechflow-node-t2t-google.ts +7 -7
  189. package/speechflow-cli/src/speechflow-node-t2t-modify.ts +84 -0
  190. package/speechflow-cli/src/speechflow-node-t2t-ollama.ts +4 -4
  191. package/speechflow-cli/src/speechflow-node-t2t-openai.ts +4 -4
  192. package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +4 -4
  193. package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +9 -9
  194. package/speechflow-cli/src/speechflow-node-t2t-transformers.ts +4 -4
  195. package/speechflow-cli/src/speechflow-node-x2x-filter.ts +4 -4
  196. package/speechflow-cli/src/speechflow-node-x2x-trace.ts +2 -2
  197. package/speechflow-cli/src/speechflow-node-xio-device.ts +7 -7
  198. package/speechflow-cli/src/speechflow-node-xio-file.ts +49 -28
  199. package/speechflow-cli/src/speechflow-node-xio-mqtt.ts +7 -7
  200. package/speechflow-cli/src/speechflow-node-xio-websocket.ts +9 -9
  201. package/speechflow-cli/src/{speechflow-utils-audio.ts → speechflow-util-audio.ts} +131 -1
  202. package/speechflow-cli/src/speechflow-util-error.ts +184 -0
  203. package/speechflow-cli/src/speechflow-util-queue.ts +320 -0
  204. package/speechflow-cli/src/speechflow-util-stream.ts +197 -0
  205. package/speechflow-cli/src/speechflow-util.ts +10 -0
  206. package/speechflow-cli/src/speechflow.ts +3 -947
  207. package/speechflow-ui-db/package.json +3 -3
  208. package/speechflow-ui-st/dst/app-font-fa-brands-400.woff2 +0 -0
  209. package/speechflow-ui-st/dst/app-font-fa-regular-400.woff2 +0 -0
  210. package/speechflow-ui-st/dst/app-font-fa-solid-900.woff2 +0 -0
  211. package/speechflow-ui-st/dst/app-font-fa-v4compatibility.woff2 +0 -0
  212. package/speechflow-ui-st/dst/index.css +2 -2
  213. package/speechflow-ui-st/dst/index.js +32 -33
  214. package/speechflow-ui-st/package.json +4 -4
  215. package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.js +0 -208
  216. package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.js.map +0 -1
  217. package/speechflow-cli/dst/speechflow-node-a2a-dynamics.js +0 -312
  218. package/speechflow-cli/dst/speechflow-node-a2a-dynamics.js.map +0 -1
  219. package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.js.map +0 -1
  220. package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.js.map +0 -1
  221. package/speechflow-cli/dst/speechflow-node-t2a-awspolly.js.map +0 -1
  222. package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.js.map +0 -1
  223. package/speechflow-cli/dst/speechflow-utils-audio-wt.js.map +0 -1
  224. package/speechflow-cli/dst/speechflow-utils-audio.js.map +0 -1
  225. package/speechflow-cli/dst/speechflow-utils.d.ts +0 -108
  226. package/speechflow-cli/dst/speechflow-utils.js +0 -740
  227. package/speechflow-cli/dst/speechflow-utils.js.map +0 -1
  228. package/speechflow-cli/src/speechflow-utils.ts +0 -804
  229. /package/speechflow-cli/dst/{speechflow-node-a2a-dynamics-wt.d.ts → speechflow-util-audio-wt.d.ts} +0 -0
  230. /package/speechflow-cli/dst/{speechflow-utils-audio-wt.d.ts → speechflow-util-webaudio-wt.d.ts} +0 -0
  231. /package/speechflow-cli/dst/{speechflow-utils-audio.d.ts → speechflow-util-webaudio.d.ts} +0 -0
  232. /package/speechflow-cli/src/{speechflow-utils-audio-wt.ts → speechflow-util-audio-wt.ts} +0 -0
@@ -14,12 +14,12 @@ import { loadSpeexModule, SpeexPreprocessor } from "@sapphi-red/speex-preprocess
14
14
 
15
15
  /* internal dependencies */
16
16
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
17
- import * as utils from "./speechflow-utils"
17
+ import * as util from "./speechflow-util"
18
18
 
19
19
  /* SpeechFlow node for Speex based noise suppression in audio-to-audio passing */
20
- export default class SpeechFlowNodeSpeex extends SpeechFlowNode {
20
+ export default class SpeechFlowNodeA2ASpeex extends SpeechFlowNode {
21
21
  /* declare official node name */
22
- public static name = "speex"
22
+ public static name = "a2a-speex"
23
23
 
24
24
  /* internal state */
25
25
  private destroyed = false
@@ -79,10 +79,10 @@ export default class SpeechFlowNodeSpeex extends SpeechFlowNode {
79
79
  callback(new Error("invalid chunk payload type"))
80
80
  else {
81
81
  /* convert Buffer into Int16Array */
82
- const payload = utils.convertBufToI16(chunk.payload)
82
+ const payload = util.convertBufToI16(chunk.payload)
83
83
 
84
84
  /* process Int16Array in necessary fixed-size segments */
85
- utils.processInt16ArrayInSegments(payload, self.sampleSize, (segment) => {
85
+ util.processInt16ArrayInSegments(payload, self.sampleSize, (segment) => {
86
86
  if (self.destroyed)
87
87
  throw new Error("stream already destroyed")
88
88
  self.speexProcessor?.processInt16(segment)
@@ -92,7 +92,7 @@ export default class SpeechFlowNodeSpeex extends SpeechFlowNode {
92
92
  throw new Error("stream already destroyed")
93
93
 
94
94
  /* convert Int16Array back into Buffer */
95
- const buf = utils.convertI16ToBuf(payload)
95
+ const buf = util.convertI16ToBuf(payload)
96
96
 
97
97
  /* update chunk */
98
98
  chunk.payload = buf
@@ -12,7 +12,7 @@ import { RealTimeVAD } from "@ericedouard/vad-node-realtime"
12
12
 
13
13
  /* internal dependencies */
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
- import * as utils from "./speechflow-utils"
15
+ import * as util from "./speechflow-util"
16
16
 
17
17
  /* audio stream queue element */
18
18
  type AudioQueueElementSegment = {
@@ -30,13 +30,13 @@ type AudioQueueElement = {
30
30
  }
31
31
 
32
32
  /* SpeechFlow node for VAD speech-to-speech processing */
33
- export default class SpeechFlowNodeVAD extends SpeechFlowNode {
33
+ export default class SpeechFlowNodeA2AVAD extends SpeechFlowNode {
34
34
  /* declare official node name */
35
- public static name = "vad"
35
+ public static name = "a2a-vad"
36
36
 
37
37
  /* internal state */
38
38
  private vad: RealTimeVAD | null = null
39
- private queue = new utils.Queue<AudioQueueElement>()
39
+ private queue = new util.Queue<AudioQueueElement>()
40
40
  private queueRecv = this.queue.pointerUse("recv")
41
41
  private queueVAD = this.queue.pointerUse("vad")
42
42
  private queueSend = this.queue.pointerUse("send")
@@ -109,7 +109,7 @@ export default class SpeechFlowNodeVAD extends SpeechFlowNode {
109
109
  onSpeechEnd: (audio) => {
110
110
  if (this.destroyed)
111
111
  return
112
- const duration = utils.audioArrayDuration(audio, vadSampleRateTarget)
112
+ const duration = util.audioArrayDuration(audio, vadSampleRateTarget)
113
113
  this.log("info", `VAD: speech end (duration: ${duration.toFixed(2)}s)`)
114
114
  if (this.params.mode === "unplugged") {
115
115
  tail = true
@@ -189,7 +189,7 @@ export default class SpeechFlowNodeVAD extends SpeechFlowNode {
189
189
  else {
190
190
  try {
191
191
  /* convert audio samples from PCM/I16 to PCM/F32 */
192
- const data = utils.convertBufToF32(chunk.payload,
192
+ const data = util.convertBufToF32(chunk.payload,
193
193
  self.config.audioLittleEndian)
194
194
 
195
195
  /* segment audio samples as individual VAD-sized frames */
@@ -83,9 +83,9 @@ const readWavHeader = (buffer: Buffer) => {
83
83
  }
84
84
 
85
85
  /* SpeechFlow node for WAV format conversion */
86
- export default class SpeechFlowNodeWAV extends SpeechFlowNode {
86
+ export default class SpeechFlowNodeA2AWAV extends SpeechFlowNode {
87
87
  /* declare official node name */
88
- public static name = "wav"
88
+ public static name = "a2a-wav"
89
89
 
90
90
  /* construct node */
91
91
  constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
@@ -19,7 +19,7 @@ import { DateTime, Duration } from "luxon"
19
19
 
20
20
  /* internal dependencies */
21
21
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
22
- import * as utils from "./speechflow-utils"
22
+ import * as util from "./speechflow-util"
23
23
 
24
24
  /* helper class for an asynchronous queue */
25
25
  class AsyncQueue<T> {
@@ -62,10 +62,10 @@ class AsyncQueue<T> {
62
62
  }
63
63
  }
64
64
 
65
- /* SpeechFlow node for AWS Transcribe speech-to-text conversion */
66
- export default class SpeechFlowNodeAWSTranscribe extends SpeechFlowNode {
65
+ /* SpeechFlow node for Amazon Transcribe speech-to-text conversion */
66
+ export default class SpeechFlowNodeA2TAmazon extends SpeechFlowNode {
67
67
  /* declare official node name */
68
- public static name = "awstranscribe"
68
+ public static name = "a2t-amazon"
69
69
 
70
70
  /* internal state */
71
71
  private client: TranscribeStreamingClient | null = null
@@ -73,7 +73,7 @@ export default class SpeechFlowNodeAWSTranscribe extends SpeechFlowNode {
73
73
  private destroyed = false
74
74
  private initTimeout: ReturnType<typeof setTimeout> | null = null
75
75
  private connectionTimeout: ReturnType<typeof setTimeout> | null = null
76
- private queue: utils.SingleQueue<SpeechFlowChunk | null> | null = null
76
+ private queue: util.SingleQueue<SpeechFlowChunk | null> | null = null
77
77
 
78
78
  /* construct node */
79
79
  constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
@@ -114,10 +114,10 @@ export default class SpeechFlowNodeAWSTranscribe extends SpeechFlowNode {
114
114
  this.destroyed = false
115
115
 
116
116
  /* create queue for results */
117
- this.queue = new utils.SingleQueue<SpeechFlowChunk | null>()
117
+ this.queue = new util.SingleQueue<SpeechFlowChunk | null>()
118
118
 
119
119
  /* create a store for the meta information */
120
- const metastore = new utils.TimeStore<Map<string, any>>()
120
+ const metastore = new util.TimeStore<Map<string, any>>()
121
121
 
122
122
  /* connect to Amazon Transcribe API */
123
123
  this.client = new TranscribeStreamingClient({
@@ -225,7 +225,7 @@ export default class SpeechFlowNodeAWSTranscribe extends SpeechFlowNode {
225
225
  metastore.store(chunk.timestampStart, chunk.timestampEnd, chunk.meta)
226
226
  audioQueue.push(new Uint8Array(chunk.payload)) /* intentionally discard all time information */
227
227
  ensureAudioStreamActive().catch((error: unknown) => {
228
- self.log("error", `failed to start audio stream: ${utils.ensureError(error).message}`)
228
+ self.log("error", `failed to start audio stream: ${util.ensureError(error).message}`)
229
229
  })
230
230
  }
231
231
  callback()
@@ -251,7 +251,7 @@ export default class SpeechFlowNodeAWSTranscribe extends SpeechFlowNode {
251
251
  }
252
252
  }).catch((error: unknown) => {
253
253
  if (!self.destroyed)
254
- self.log("error", `queue read error: ${utils.ensureError(error).message}`)
254
+ self.log("error", `queue read error: ${util.ensureError(error).message}`)
255
255
  })
256
256
  },
257
257
  final (callback) {
@@ -259,7 +259,7 @@ export default class SpeechFlowNodeAWSTranscribe extends SpeechFlowNode {
259
259
  callback()
260
260
  return
261
261
  }
262
- utils.run(
262
+ util.run(
263
263
  () => self.client!.destroy(),
264
264
  (error: Error) => self.log("warning", `error closing Amazon Transcribe connection: ${error}`)
265
265
  )
@@ -13,19 +13,19 @@ import { DateTime, Duration } from "luxon"
13
13
 
14
14
  /* internal dependencies */
15
15
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
16
- import * as utils from "./speechflow-utils"
16
+ import * as util from "./speechflow-util"
17
17
 
18
18
  /* SpeechFlow node for Deepgram speech-to-text conversion */
19
- export default class SpeechFlowNodeDeepgram extends SpeechFlowNode {
19
+ export default class SpeechFlowNodeA2TDeepgram extends SpeechFlowNode {
20
20
  /* declare official node name */
21
- public static name = "deepgram"
21
+ public static name = "a2t-deepgram"
22
22
 
23
23
  /* internal state */
24
24
  private dg: Deepgram.LiveClient | null = null
25
25
  private destroyed = false
26
26
  private initTimeout: ReturnType<typeof setTimeout> | null = null
27
27
  private connectionTimeout: ReturnType<typeof setTimeout> | null = null
28
- private queue: utils.SingleQueue<SpeechFlowChunk | null> | null = null
28
+ private queue: util.SingleQueue<SpeechFlowChunk | null> | null = null
29
29
 
30
30
  /* construct node */
31
31
  constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
@@ -78,10 +78,10 @@ export default class SpeechFlowNodeDeepgram extends SpeechFlowNode {
78
78
  this.destroyed = false
79
79
 
80
80
  /* create queue for results */
81
- this.queue = new utils.SingleQueue<SpeechFlowChunk | null>()
81
+ this.queue = new util.SingleQueue<SpeechFlowChunk | null>()
82
82
 
83
83
  /* create a store for the meta information */
84
- const metastore = new utils.TimeStore<Map<string, any>>()
84
+ const metastore = new util.TimeStore<Map<string, any>>()
85
85
 
86
86
  /* connect to Deepgram API */
87
87
  const deepgram = Deepgram.createClient(this.params.key)
@@ -234,7 +234,7 @@ export default class SpeechFlowNodeDeepgram extends SpeechFlowNode {
234
234
  }
235
235
  }).catch((error: unknown) => {
236
236
  if (!self.destroyed)
237
- self.log("error", `queue read error: ${utils.ensureError(error).message}`)
237
+ self.log("error", `queue read error: ${util.ensureError(error).message}`)
238
238
  })
239
239
  },
240
240
  final (callback) {
@@ -15,18 +15,18 @@ import ws from "ws"
15
15
 
16
16
  /* internal dependencies */
17
17
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
18
- import * as utils from "./speechflow-utils"
18
+ import * as util from "./speechflow-util"
19
19
 
20
- /* SpeechFlow node for OpenAI Transcribe speech-to-text conversion */
21
- export default class SpeechFlowNodeOpenAITranscribe extends SpeechFlowNode {
20
+ /* SpeechFlow node for OpenAI speech-to-text conversion */
21
+ export default class SpeechFlowNodeA2TOpenAI extends SpeechFlowNode {
22
22
  /* declare official node name */
23
- public static name = "openaitranscribe"
23
+ public static name = "a2t-openai"
24
24
 
25
25
  /* internal state */
26
26
  private static speexInitialized = false
27
27
  private openai: OpenAI | null = null
28
28
  private ws: ws.WebSocket | null = null
29
- private queue: utils.SingleQueue<SpeechFlowChunk | null> | null = null
29
+ private queue: util.SingleQueue<SpeechFlowChunk | null> | null = null
30
30
  private resampler: SpeexResampler | null = null
31
31
  private destroyed = false
32
32
  private connectionTimeout: ReturnType<typeof setTimeout> | null = null
@@ -64,17 +64,17 @@ export default class SpeechFlowNodeOpenAITranscribe extends SpeechFlowNode {
64
64
  this.destroyed = false
65
65
 
66
66
  /* create queue for results */
67
- this.queue = new utils.SingleQueue<SpeechFlowChunk | null>()
67
+ this.queue = new util.SingleQueue<SpeechFlowChunk | null>()
68
68
 
69
69
  /* create a store for the meta information */
70
- const metastore = new utils.TimeStore<Map<string, any>>()
70
+ const metastore = new util.TimeStore<Map<string, any>>()
71
71
 
72
72
  /* establish resampler from our standard audio sample rate (48Khz)
73
73
  to OpenAI's maximum 24Khz input sample rate */
74
- if (!SpeechFlowNodeOpenAITranscribe.speexInitialized) {
74
+ if (!SpeechFlowNodeA2TOpenAI.speexInitialized) {
75
75
  /* at least once initialize resampler */
76
76
  await SpeexResampler.initPromise
77
- SpeechFlowNodeOpenAITranscribe.speexInitialized = true
77
+ SpeechFlowNodeA2TOpenAI.speexInitialized = true
78
78
  }
79
79
  this.resampler = new SpeexResampler(1, this.config.audioSampleRate, 24000, 7)
80
80
 
@@ -281,7 +281,7 @@ export default class SpeechFlowNodeOpenAITranscribe extends SpeechFlowNode {
281
281
  }
282
282
  }).catch((error: unknown) => {
283
283
  if (!self.destroyed)
284
- self.log("error", `queue read error: ${utils.ensureError(error).message}`)
284
+ self.log("error", `queue read error: ${util.ensureError(error).message}`)
285
285
  })
286
286
  },
287
287
  final (callback) {
@@ -17,12 +17,12 @@ import {
17
17
 
18
18
  /* internal dependencies */
19
19
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
20
- import * as utils from "./speechflow-utils"
20
+ import * as util from "./speechflow-util"
21
21
 
22
- /* SpeechFlow node for AWS Polly text-to-speech conversion */
23
- export default class SpeechFlowNodeAWSPolly extends SpeechFlowNode {
22
+ /* SpeechFlow node for Amazon Polly text-to-speech conversion */
23
+ export default class SpeechFlowNodeT2AAmazon extends SpeechFlowNode {
24
24
  /* declare official node name */
25
- public static name = "awspolly"
25
+ public static name = "t2a-amazon"
26
26
 
27
27
  /* internal state */
28
28
  private client: PollyClient | null = null
@@ -114,10 +114,10 @@ export default class SpeechFlowNodeAWSPolly extends SpeechFlowNode {
114
114
 
115
115
  /* establish resampler from AWS Polly's maximum 16Khz output
116
116
  (for PCM output) to our standard audio sample rate (48KHz) */
117
- if (!SpeechFlowNodeAWSPolly.speexInitialized) {
117
+ if (!SpeechFlowNodeT2AAmazon.speexInitialized) {
118
118
  /* at least once initialize resampler */
119
119
  await SpeexResampler.initPromise
120
- SpeechFlowNodeAWSPolly.speexInitialized = true
120
+ SpeechFlowNodeT2AAmazon.speexInitialized = true
121
121
  }
122
122
  this.resampler = new SpeexResampler(1, 16000, this.config.audioSampleRate, 7)
123
123
 
@@ -146,7 +146,7 @@ export default class SpeechFlowNodeAWSPolly extends SpeechFlowNode {
146
146
  this.push(chunkNew)
147
147
  callback()
148
148
  }).catch((error: unknown) => {
149
- callback(utils.ensureError(error, "failed to send to AWS Polly"))
149
+ callback(util.ensureError(error, "failed to send to AWS Polly"))
150
150
  })
151
151
  }
152
152
  else
@@ -16,9 +16,9 @@ import SpeexResampler from "speex-resampler"
16
16
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
17
17
 
18
18
  /* SpeechFlow node for Elevenlabs text-to-speech conversion */
19
- export default class SpeechFlowNodeElevenlabs extends SpeechFlowNode {
19
+ export default class SpeechFlowNodeT2AElevenlabs extends SpeechFlowNode {
20
20
  /* declare official node name */
21
- public static name = "elevenlabs"
21
+ public static name = "t2a-elevenlabs"
22
22
 
23
23
  /* internal state */
24
24
  private elevenlabs: ElevenLabs.ElevenLabsClient | null = null
@@ -131,10 +131,10 @@ export default class SpeechFlowNodeElevenlabs extends SpeechFlowNode {
131
131
 
132
132
  /* establish resampler from ElevenLabs's maximum 24Khz
133
133
  output to our standard audio sample rate (48KHz) */
134
- if (!SpeechFlowNodeElevenlabs.speexInitialized) {
134
+ if (!SpeechFlowNodeT2AElevenlabs.speexInitialized) {
135
135
  /* at least once initialize resampler */
136
136
  await SpeexResampler.initPromise
137
- SpeechFlowNodeElevenlabs.speexInitialized = true
137
+ SpeechFlowNodeT2AElevenlabs.speexInitialized = true
138
138
  }
139
139
  this.resampler = new SpeexResampler(1, maxSampleRate, this.config.audioSampleRate, 7)
140
140
 
@@ -13,12 +13,12 @@ import SpeexResampler from "speex-resampler"
13
13
 
14
14
  /* internal dependencies */
15
15
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
16
- import * as utils from "./speechflow-utils"
16
+ import * as util from "./speechflow-util"
17
17
 
18
18
  /* SpeechFlow node for Kokoro text-to-speech conversion */
19
- export default class SpeechFlowNodeKokoro extends SpeechFlowNode {
19
+ export default class SpeechFlowNodeT2AKokoro extends SpeechFlowNode {
20
20
  /* declare official node name */
21
- public static name = "kokoro"
21
+ public static name = "t2a-kokoro"
22
22
 
23
23
  /* internal state */
24
24
  private kokoro: KokoroTTS | null = null
@@ -82,9 +82,9 @@ export default class SpeechFlowNodeKokoro extends SpeechFlowNode {
82
82
 
83
83
  /* establish resampler from Kokoro's maximum 24Khz
84
84
  output to our standard audio sample rate (48KHz) */
85
- if (!SpeechFlowNodeKokoro.speexInitialized) {
85
+ if (!SpeechFlowNodeT2AKokoro.speexInitialized) {
86
86
  /* at least once initialize resampler */
87
- SpeechFlowNodeKokoro.speexInitialized = true
87
+ SpeechFlowNodeT2AKokoro.speexInitialized = true
88
88
  await SpeexResampler.initPromise
89
89
  }
90
90
  this.resampler = new SpeexResampler(1, 24000, this.config.audioSampleRate, 7)
@@ -143,7 +143,7 @@ export default class SpeechFlowNodeKokoro extends SpeechFlowNode {
143
143
  this.push(chunk)
144
144
  callback()
145
145
  }).catch((error: unknown) => {
146
- callback(utils.ensureError(error))
146
+ callback(util.ensureError(error))
147
147
  })
148
148
  }
149
149
  },
@@ -12,12 +12,12 @@ import { TranslateClient, TranslateTextCommand } from "@aws-sdk/client-translate
12
12
 
13
13
  /* internal dependencies */
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
- import * as utils from "./speechflow-utils"
15
+ import * as util from "./speechflow-util"
16
16
 
17
- /* SpeechFlow node for AWS Translate text-to-text translations */
18
- export default class SpeechFlowNodeAWSTranslate extends SpeechFlowNode {
17
+ /* SpeechFlow node for Amazon Translate text-to-text translations */
18
+ export default class SpeechFlowNodeT2TAmazon extends SpeechFlowNode {
19
19
  /* declare official node name */
20
- public static name = "awstranslate"
20
+ public static name = "t2t-amazon"
21
21
 
22
22
  /* internal state */
23
23
  private client: TranslateClient | null = null
@@ -124,7 +124,7 @@ export default class SpeechFlowNodeAWSTranslate extends SpeechFlowNode {
124
124
  this.push(chunkNew)
125
125
  callback()
126
126
  }).catch((error: unknown) => {
127
- callback(utils.ensureError(error))
127
+ callback(util.ensureError(error))
128
128
  })
129
129
  }
130
130
  },
@@ -12,12 +12,12 @@ import * as DeepL from "deepl-node"
12
12
 
13
13
  /* internal dependencies */
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
- import * as utils from "./speechflow-utils"
15
+ import * as util from "./speechflow-util"
16
16
 
17
17
  /* SpeechFlow node for DeepL text-to-text translations */
18
- export default class SpeechFlowNodeDeepL extends SpeechFlowNode {
18
+ export default class SpeechFlowNodeT2TDeepL extends SpeechFlowNode {
19
19
  /* declare official node name */
20
- public static name = "deepl"
20
+ public static name = "t2t-deepl"
21
21
 
22
22
  /* internal state */
23
23
  private deepl: DeepL.Translator | null = null
@@ -95,7 +95,7 @@ export default class SpeechFlowNodeDeepL extends SpeechFlowNode {
95
95
  this.push(chunkNew)
96
96
  callback()
97
97
  }).catch((error: unknown) => {
98
- callback(utils.ensureError(error))
98
+ callback(util.ensureError(error))
99
99
  })
100
100
  }
101
101
  },
@@ -14,9 +14,9 @@ import wrapText from "wrap-text"
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
15
 
16
16
  /* SpeechFlow node for text-to-text formatting */
17
- export default class SpeechFlowNodeFormat extends SpeechFlowNode {
17
+ export default class SpeechFlowNodeT2TFormat extends SpeechFlowNode {
18
18
  /* declare official node name */
19
- public static name = "format"
19
+ public static name = "t2t-format"
20
20
 
21
21
  /* construct node */
22
22
  constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
@@ -13,12 +13,12 @@ import * as arktype from "arktype"
13
13
 
14
14
  /* internal dependencies */
15
15
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
16
- import * as utils from "./speechflow-utils"
16
+ import * as util from "./speechflow-util"
17
17
 
18
18
  /* SpeechFlow node for Google Translate text-to-text translations */
19
- export default class SpeechFlowNodeGoogle extends SpeechFlowNode {
19
+ export default class SpeechFlowNodeT2TGoogle extends SpeechFlowNode {
20
20
  /* declare official node name */
21
- public static name = "google"
21
+ public static name = "t2t-google"
22
22
 
23
23
  /* internal state */
24
24
  private client: TranslationServiceClient | null = null
@@ -55,9 +55,9 @@ export default class SpeechFlowNodeGoogle extends SpeechFlowNode {
55
55
  /* open node */
56
56
  async open () {
57
57
  /* instantiate Google Translate client */
58
- const data = utils.run("Google Cloud API credentials key", () =>
58
+ const data = util.run("Google Cloud API credentials key", () =>
59
59
  JSON.parse(this.params.key))
60
- const credentials = utils.importObject("Google Cloud API credentials key",
60
+ const credentials = util.importObject("Google Cloud API credentials key",
61
61
  data,
62
62
  arktype.type({
63
63
  project_id: "string",
@@ -74,7 +74,7 @@ export default class SpeechFlowNodeGoogle extends SpeechFlowNode {
74
74
  })
75
75
 
76
76
  /* provide text-to-text translation */
77
- const translate = utils.runner("Google Translate API", async (text: string) => {
77
+ const translate = util.runner("Google Translate API", async (text: string) => {
78
78
  const [ response ] = await this.client!.translateText({
79
79
  parent: `projects/${credentials.project_id}/locations/global`,
80
80
  contents: [ text ],
@@ -105,7 +105,7 @@ export default class SpeechFlowNodeGoogle extends SpeechFlowNode {
105
105
  this.push(chunkNew)
106
106
  callback()
107
107
  }).catch((error: unknown) => {
108
- callback(utils.ensureError(error))
108
+ callback(util.ensureError(error))
109
109
  })
110
110
  }
111
111
  },
@@ -0,0 +1,84 @@
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
+ /* standard dependencies */
8
+ import Stream from "node:stream"
9
+
10
+ /* internal dependencies */
11
+ import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
12
+ import * as util from "./speechflow-util"
13
+
14
+ /* SpeechFlow node for text-to-text modification via regex */
15
+ export default class SpeechFlowNodeT2TModify extends SpeechFlowNode {
16
+ /* declare official node name */
17
+ public static name = "t2t-modify"
18
+
19
+ /* construct node */
20
+ constructor (id: string, cfg: { [ id: string ]: any }, opts: { [ id: string ]: any }, args: any[]) {
21
+ super(id, cfg, opts, args)
22
+
23
+ /* declare node configuration parameters */
24
+ this.configure({
25
+ match: { type: "string", val: "" },
26
+ replace: { type: "string", val: "" }
27
+ })
28
+
29
+ /* declare node input/output format */
30
+ this.input = "text"
31
+ this.output = "text"
32
+ }
33
+
34
+ /* open node */
35
+ async open () {
36
+ /* validate parameters */
37
+ if (this.params.match === "")
38
+ throw new Error("match parameter cannot be empty")
39
+
40
+ /* compile regex pattern */
41
+ const regex = util.run("compiling regex pattern",
42
+ () => new RegExp(this.params.match, "g"))
43
+
44
+ /* apply regex-based modification */
45
+ const modify = (text: string): string =>
46
+ text.replace(regex, this.params.replace)
47
+
48
+ /* establish a duplex stream and connect it to text modification */
49
+ this.stream = new Stream.Transform({
50
+ readableObjectMode: true,
51
+ writableObjectMode: true,
52
+ decodeStrings: false,
53
+ highWaterMark: 1,
54
+ transform (chunk: SpeechFlowChunk, encoding, callback) {
55
+ if (Buffer.isBuffer(chunk.payload))
56
+ callback(new Error("invalid chunk payload type"))
57
+ else if (chunk.payload === "") {
58
+ this.push(chunk)
59
+ callback()
60
+ }
61
+ else {
62
+ const payload = modify(chunk.payload)
63
+ const chunkNew = chunk.clone()
64
+ chunkNew.payload = payload
65
+ this.push(chunkNew)
66
+ callback()
67
+ }
68
+ },
69
+ final (callback) {
70
+ this.push(null)
71
+ callback()
72
+ }
73
+ })
74
+ }
75
+
76
+ /* close node */
77
+ async close () {
78
+ /* close stream */
79
+ if (this.stream !== null) {
80
+ this.stream.destroy()
81
+ this.stream = null
82
+ }
83
+ }
84
+ }
@@ -12,16 +12,16 @@ import { Ollama, type ListResponse } from "ollama"
12
12
 
13
13
  /* internal dependencies */
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
- import * as utils from "./speechflow-utils"
15
+ import * as util from "./speechflow-util"
16
16
 
17
17
  /* internal utility types */
18
18
  type ConfigEntry = { systemPrompt: string, chat: Array<{ role: string, content: string }> }
19
19
  type Config = { [ key: string ]: ConfigEntry }
20
20
 
21
21
  /* SpeechFlow node for Ollama text-to-text translation */
22
- export default class SpeechFlowNodeOllama extends SpeechFlowNode {
22
+ export default class SpeechFlowNodeT2TOllama extends SpeechFlowNode {
23
23
  /* declare official node name */
24
- public static name = "ollama"
24
+ public static name = "t2t-ollama"
25
25
 
26
26
  /* internal state */
27
27
  private ollama: Ollama | null = null
@@ -252,7 +252,7 @@ export default class SpeechFlowNodeOllama extends SpeechFlowNode {
252
252
  this.push(chunkNew)
253
253
  callback()
254
254
  }).catch((error: unknown) => {
255
- callback(utils.ensureError(error))
255
+ callback(util.ensureError(error))
256
256
  })
257
257
  }
258
258
  }
@@ -12,16 +12,16 @@ import OpenAI from "openai"
12
12
 
13
13
  /* internal dependencies */
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
- import * as utils from "./speechflow-utils"
15
+ import * as util from "./speechflow-util"
16
16
 
17
17
  /* internal utility types */
18
18
  type ConfigEntry = { systemPrompt: string, chat: OpenAI.ChatCompletionMessageParam[] }
19
19
  type Config = { [ key: string ]: ConfigEntry }
20
20
 
21
21
  /* SpeechFlow node for OpenAI/GPT text-to-text translation */
22
- export default class SpeechFlowNodeOpenAI extends SpeechFlowNode {
22
+ export default class SpeechFlowNodeT2TOpenAI extends SpeechFlowNode {
23
23
  /* declare official node name */
24
- public static name = "openai"
24
+ public static name = "t2t-openai"
25
25
 
26
26
  /* internal state */
27
27
  private openai: OpenAI | null = null
@@ -221,7 +221,7 @@ export default class SpeechFlowNodeOpenAI extends SpeechFlowNode {
221
221
  this.push(chunkNew)
222
222
  callback()
223
223
  }).catch((error: unknown) => {
224
- callback(utils.ensureError(error))
224
+ callback(util.ensureError(error))
225
225
  })
226
226
  }
227
227
  },
@@ -12,7 +12,7 @@ import { Duration } from "luxon"
12
12
 
13
13
  /* internal dependencies */
14
14
  import SpeechFlowNode, { SpeechFlowChunk } from "./speechflow-node"
15
- import * as utils from "./speechflow-utils"
15
+ import * as util from "./speechflow-util"
16
16
 
17
17
  /* text stream queue element */
18
18
  type TextQueueElement = {
@@ -24,12 +24,12 @@ type TextQueueElement = {
24
24
  }
25
25
 
26
26
  /* SpeechFlow node for sentence splitting */
27
- export default class SpeechFlowNodeSentence extends SpeechFlowNode {
27
+ export default class SpeechFlowNodeT2TSentence extends SpeechFlowNode {
28
28
  /* declare official node name */
29
- public static name = "sentence"
29
+ public static name = "t2t-sentence"
30
30
 
31
31
  /* internal state */
32
- private queue = new utils.Queue<TextQueueElement>()
32
+ private queue = new util.Queue<TextQueueElement>()
33
33
  private queueRecv = this.queue.pointerUse("recv")
34
34
  private queueSplit = this.queue.pointerUse("split")
35
35
  private queueSend = this.queue.pointerUse("send")