speechflow 1.4.5 → 1.5.0

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 (166) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +220 -7
  3. package/etc/claude.md +70 -0
  4. package/etc/speechflow.yaml +5 -3
  5. package/etc/stx.conf +7 -0
  6. package/package.json +7 -6
  7. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.d.ts +1 -0
  8. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js +155 -0
  9. package/speechflow-cli/dst/speechflow-node-a2a-compressor-wt.js.map +1 -0
  10. package/speechflow-cli/dst/speechflow-node-a2a-compressor.d.ts +15 -0
  11. package/speechflow-cli/dst/speechflow-node-a2a-compressor.js +287 -0
  12. package/speechflow-cli/dst/speechflow-node-a2a-compressor.js.map +1 -0
  13. package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.d.ts +1 -0
  14. package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.js +208 -0
  15. package/speechflow-cli/dst/speechflow-node-a2a-dynamics-wt.js.map +1 -0
  16. package/speechflow-cli/dst/speechflow-node-a2a-dynamics.d.ts +15 -0
  17. package/speechflow-cli/dst/speechflow-node-a2a-dynamics.js +312 -0
  18. package/speechflow-cli/dst/speechflow-node-a2a-dynamics.js.map +1 -0
  19. package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.d.ts +1 -0
  20. package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js +161 -0
  21. package/speechflow-cli/dst/speechflow-node-a2a-expander-wt.js.map +1 -0
  22. package/speechflow-cli/dst/speechflow-node-a2a-expander.d.ts +13 -0
  23. package/speechflow-cli/dst/speechflow-node-a2a-expander.js +208 -0
  24. package/speechflow-cli/dst/speechflow-node-a2a-expander.js.map +1 -0
  25. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js +13 -3
  26. package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js.map +1 -1
  27. package/speechflow-cli/dst/speechflow-node-a2a-filler.d.ts +14 -0
  28. package/speechflow-cli/dst/speechflow-node-a2a-filler.js +233 -0
  29. package/speechflow-cli/dst/speechflow-node-a2a-filler.js.map +1 -0
  30. package/speechflow-cli/dst/speechflow-node-a2a-gain.d.ts +12 -0
  31. package/speechflow-cli/dst/speechflow-node-a2a-gain.js +125 -0
  32. package/speechflow-cli/dst/speechflow-node-a2a-gain.js.map +1 -0
  33. package/speechflow-cli/dst/speechflow-node-a2a-gender.d.ts +0 -1
  34. package/speechflow-cli/dst/speechflow-node-a2a-gender.js +28 -12
  35. package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -1
  36. package/speechflow-cli/dst/speechflow-node-a2a-meter.d.ts +1 -0
  37. package/speechflow-cli/dst/speechflow-node-a2a-meter.js +12 -8
  38. package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -1
  39. package/speechflow-cli/dst/speechflow-node-a2a-mute.js +2 -1
  40. package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -1
  41. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.d.ts +1 -0
  42. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js +55 -0
  43. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise-wt.js.map +1 -0
  44. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.d.ts +14 -0
  45. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js +184 -0
  46. package/speechflow-cli/dst/speechflow-node-a2a-rnnoise.js.map +1 -0
  47. package/speechflow-cli/dst/speechflow-node-a2a-speex.d.ts +14 -0
  48. package/speechflow-cli/dst/speechflow-node-a2a-speex.js +156 -0
  49. package/speechflow-cli/dst/speechflow-node-a2a-speex.js.map +1 -0
  50. package/speechflow-cli/dst/speechflow-node-a2a-vad.js +3 -3
  51. package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -1
  52. package/speechflow-cli/dst/speechflow-node-a2a-wav.js +22 -17
  53. package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -1
  54. package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.d.ts +18 -0
  55. package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.js +317 -0
  56. package/speechflow-cli/dst/speechflow-node-a2t-awstranscribe.js.map +1 -0
  57. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +15 -13
  58. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  59. package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.d.ts +19 -0
  60. package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.js +351 -0
  61. package/speechflow-cli/dst/speechflow-node-a2t-openaitranscribe.js.map +1 -0
  62. package/speechflow-cli/dst/speechflow-node-t2a-awspolly.d.ts +16 -0
  63. package/speechflow-cli/dst/speechflow-node-t2a-awspolly.js +171 -0
  64. package/speechflow-cli/dst/speechflow-node-t2a-awspolly.js.map +1 -0
  65. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +19 -14
  66. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
  67. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +11 -6
  68. package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -1
  69. package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.d.ts +13 -0
  70. package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.js +141 -0
  71. package/speechflow-cli/dst/speechflow-node-t2t-awstranslate.js.map +1 -0
  72. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +13 -15
  73. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
  74. package/speechflow-cli/dst/speechflow-node-t2t-format.js +10 -15
  75. package/speechflow-cli/dst/speechflow-node-t2t-format.js.map +1 -1
  76. package/speechflow-cli/dst/speechflow-node-t2t-ollama.js +44 -31
  77. package/speechflow-cli/dst/speechflow-node-t2t-ollama.js.map +1 -1
  78. package/speechflow-cli/dst/speechflow-node-t2t-openai.js +44 -45
  79. package/speechflow-cli/dst/speechflow-node-t2t-openai.js.map +1 -1
  80. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +8 -8
  81. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
  82. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +10 -12
  83. package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -1
  84. package/speechflow-cli/dst/speechflow-node-t2t-transformers.js +22 -27
  85. package/speechflow-cli/dst/speechflow-node-t2t-transformers.js.map +1 -1
  86. package/speechflow-cli/dst/speechflow-node-x2x-filter.d.ts +1 -0
  87. package/speechflow-cli/dst/speechflow-node-x2x-filter.js +50 -15
  88. package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -1
  89. package/speechflow-cli/dst/speechflow-node-x2x-trace.js +17 -18
  90. package/speechflow-cli/dst/speechflow-node-x2x-trace.js.map +1 -1
  91. package/speechflow-cli/dst/speechflow-node-xio-device.js +13 -21
  92. package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -1
  93. package/speechflow-cli/dst/speechflow-node-xio-mqtt.d.ts +1 -0
  94. package/speechflow-cli/dst/speechflow-node-xio-mqtt.js +22 -16
  95. package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -1
  96. package/speechflow-cli/dst/speechflow-node-xio-websocket.js +19 -19
  97. package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -1
  98. package/speechflow-cli/dst/speechflow-node.d.ts +6 -3
  99. package/speechflow-cli/dst/speechflow-node.js +13 -2
  100. package/speechflow-cli/dst/speechflow-node.js.map +1 -1
  101. package/speechflow-cli/dst/speechflow-utils-audio-wt.d.ts +1 -0
  102. package/speechflow-cli/dst/speechflow-utils-audio-wt.js +124 -0
  103. package/speechflow-cli/dst/speechflow-utils-audio-wt.js.map +1 -0
  104. package/speechflow-cli/dst/speechflow-utils-audio.d.ts +13 -0
  105. package/speechflow-cli/dst/speechflow-utils-audio.js +137 -0
  106. package/speechflow-cli/dst/speechflow-utils-audio.js.map +1 -0
  107. package/speechflow-cli/dst/speechflow-utils.d.ts +18 -0
  108. package/speechflow-cli/dst/speechflow-utils.js +123 -35
  109. package/speechflow-cli/dst/speechflow-utils.js.map +1 -1
  110. package/speechflow-cli/dst/speechflow.js +69 -14
  111. package/speechflow-cli/dst/speechflow.js.map +1 -1
  112. package/speechflow-cli/etc/oxlint.jsonc +112 -11
  113. package/speechflow-cli/etc/stx.conf +2 -2
  114. package/speechflow-cli/etc/tsconfig.json +1 -1
  115. package/speechflow-cli/package.d/@shiguredo+rnnoise-wasm+2025.1.5.patch +25 -0
  116. package/speechflow-cli/package.json +102 -94
  117. package/speechflow-cli/src/lib.d.ts +24 -0
  118. package/speechflow-cli/src/speechflow-node-a2a-compressor-wt.ts +151 -0
  119. package/speechflow-cli/src/speechflow-node-a2a-compressor.ts +303 -0
  120. package/speechflow-cli/src/speechflow-node-a2a-expander-wt.ts +158 -0
  121. package/speechflow-cli/src/speechflow-node-a2a-expander.ts +212 -0
  122. package/speechflow-cli/src/speechflow-node-a2a-ffmpeg.ts +13 -3
  123. package/speechflow-cli/src/speechflow-node-a2a-filler.ts +223 -0
  124. package/speechflow-cli/src/speechflow-node-a2a-gain.ts +98 -0
  125. package/speechflow-cli/src/speechflow-node-a2a-gender.ts +31 -17
  126. package/speechflow-cli/src/speechflow-node-a2a-meter.ts +13 -9
  127. package/speechflow-cli/src/speechflow-node-a2a-mute.ts +3 -2
  128. package/speechflow-cli/src/speechflow-node-a2a-rnnoise-wt.ts +62 -0
  129. package/speechflow-cli/src/speechflow-node-a2a-rnnoise.ts +164 -0
  130. package/speechflow-cli/src/speechflow-node-a2a-speex.ts +137 -0
  131. package/speechflow-cli/src/speechflow-node-a2a-vad.ts +3 -3
  132. package/speechflow-cli/src/speechflow-node-a2a-wav.ts +20 -13
  133. package/speechflow-cli/src/speechflow-node-a2t-awstranscribe.ts +308 -0
  134. package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +15 -13
  135. package/speechflow-cli/src/speechflow-node-a2t-openaitranscribe.ts +337 -0
  136. package/speechflow-cli/src/speechflow-node-t2a-awspolly.ts +187 -0
  137. package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +19 -14
  138. package/speechflow-cli/src/speechflow-node-t2a-kokoro.ts +12 -7
  139. package/speechflow-cli/src/speechflow-node-t2t-awstranslate.ts +152 -0
  140. package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +13 -15
  141. package/speechflow-cli/src/speechflow-node-t2t-format.ts +10 -15
  142. package/speechflow-cli/src/speechflow-node-t2t-ollama.ts +55 -42
  143. package/speechflow-cli/src/speechflow-node-t2t-openai.ts +58 -58
  144. package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +10 -10
  145. package/speechflow-cli/src/speechflow-node-t2t-subtitle.ts +15 -16
  146. package/speechflow-cli/src/speechflow-node-t2t-transformers.ts +27 -32
  147. package/speechflow-cli/src/speechflow-node-x2x-filter.ts +20 -16
  148. package/speechflow-cli/src/speechflow-node-x2x-trace.ts +20 -19
  149. package/speechflow-cli/src/speechflow-node-xio-device.ts +15 -23
  150. package/speechflow-cli/src/speechflow-node-xio-mqtt.ts +23 -16
  151. package/speechflow-cli/src/speechflow-node-xio-websocket.ts +19 -19
  152. package/speechflow-cli/src/speechflow-node.ts +21 -8
  153. package/speechflow-cli/src/speechflow-utils-audio-wt.ts +172 -0
  154. package/speechflow-cli/src/speechflow-utils-audio.ts +147 -0
  155. package/speechflow-cli/src/speechflow-utils.ts +125 -32
  156. package/speechflow-cli/src/speechflow.ts +74 -17
  157. package/speechflow-ui-db/dst/index.js +31 -31
  158. package/speechflow-ui-db/etc/eslint.mjs +0 -1
  159. package/speechflow-ui-db/etc/tsc-client.json +3 -3
  160. package/speechflow-ui-db/package.json +11 -10
  161. package/speechflow-ui-db/src/app.vue +20 -6
  162. package/speechflow-ui-st/dst/index.js +26 -26
  163. package/speechflow-ui-st/etc/eslint.mjs +0 -1
  164. package/speechflow-ui-st/etc/tsc-client.json +3 -3
  165. package/speechflow-ui-st/package.json +11 -10
  166. package/speechflow-ui-st/src/app.vue +5 -12
@@ -15,6 +15,7 @@ import Inert from "@hapi/inert"
15
15
  import WebSocket from "ws"
16
16
  import HAPIWebSocket from "hapi-plugin-websocket"
17
17
  import HAPIHeader from "hapi-plugin-header"
18
+ import OSC from "osc-js"
18
19
 
19
20
  /* external dependencies */
20
21
  import { DateTime } from "luxon"
@@ -70,6 +71,7 @@ let debug = false
70
71
  "[-p|--port <tcp-port>] " +
71
72
  "[-C|--cache <directory>] " +
72
73
  "[-d|--dashboard <type>:<id>:<name>[,...]] " +
74
+ "[-o|--osc <ip-address>:<udp-port> " +
73
75
  "[-e|--expression <expression>] " +
74
76
  "[-f|--file <file>] " +
75
77
  "[-c|--config <id>@<yaml-config-file>] " +
@@ -137,6 +139,15 @@ let debug = false
137
139
  default: "",
138
140
  describe: "list of dashboard block types and names"
139
141
  })
142
+ .option("o", {
143
+ alias: "osc",
144
+ type: "string",
145
+ array: false,
146
+ coerce,
147
+ nargs: 1,
148
+ default: "",
149
+ describe: "OSC/UDP endpoint to send dashboard information"
150
+ })
140
151
  .option("e", {
141
152
  alias: "expression",
142
153
  type: "string",
@@ -267,15 +278,25 @@ let debug = false
267
278
 
268
279
  /* load internal SpeechFlow nodes */
269
280
  const pkgsI = [
281
+ "./speechflow-node-a2a-compressor.js",
282
+ "./speechflow-node-a2a-expander.js",
270
283
  "./speechflow-node-a2a-ffmpeg.js",
284
+ "./speechflow-node-a2a-filler.js",
285
+ "./speechflow-node-a2a-gain.js",
271
286
  "./speechflow-node-a2a-gender.js",
272
287
  "./speechflow-node-a2a-meter.js",
273
288
  "./speechflow-node-a2a-mute.js",
289
+ "./speechflow-node-a2a-rnnoise.js",
290
+ "./speechflow-node-a2a-speex.js",
274
291
  "./speechflow-node-a2a-vad.js",
275
292
  "./speechflow-node-a2a-wav.js",
293
+ "./speechflow-node-a2t-awstranscribe.js",
276
294
  "./speechflow-node-a2t-deepgram.js",
295
+ "./speechflow-node-a2t-openaitranscribe.js",
296
+ "./speechflow-node-t2a-awspolly.js",
277
297
  "./speechflow-node-t2a-elevenlabs.js",
278
298
  "./speechflow-node-t2a-kokoro.js",
299
+ "./speechflow-node-t2t-awstranslate.js",
279
300
  "./speechflow-node-t2t-deepl.js",
280
301
  "./speechflow-node-t2t-format.js",
281
302
  "./speechflow-node-t2t-ollama.js",
@@ -329,6 +350,19 @@ let debug = false
329
350
  cacheDir: args.C
330
351
  }
331
352
 
353
+ /* provide access to internal communication busses */
354
+ const busses = new Map<string, EventEmitter>()
355
+ const accessBus = (name: string): EventEmitter => {
356
+ let bus: EventEmitter
357
+ if (busses.has(name))
358
+ bus = busses.get(name)!
359
+ else {
360
+ bus = new EventEmitter()
361
+ busses.set(name, bus)
362
+ }
363
+ return bus
364
+ }
365
+
332
366
  /* handle one-time status query of nodes */
333
367
  if (args.S) {
334
368
  const table = new Table({
@@ -344,6 +378,7 @@ let debug = false
344
378
  for (const name of Object.keys(nodes)) {
345
379
  cli!.log("info", `gathering status of node <${name}>`)
346
380
  const node = new nodes[name](name, cfg, {}, [])
381
+ node._accessBus = accessBus
347
382
  const status = await Promise.race<{ [ key: string ]: string | number }>([
348
383
  node.status(),
349
384
  new Promise<never>((resolve, reject) => setTimeout(() =>
@@ -403,6 +438,7 @@ let debug = false
403
438
  nodeNums.set(NodeClass, ++num)
404
439
  const name = num === 1 ? id : `${id}:${num}`
405
440
  node = new NodeClass(name, cfg, opts, args)
441
+ node._accessBus = accessBus
406
442
  }
407
443
  catch (err) {
408
444
  /* fatal error */
@@ -418,7 +454,7 @@ let debug = false
418
454
  graphNodes.add(node)
419
455
  return node
420
456
  },
421
- connectNode (node1: SpeechFlowNode, node2: SpeechFlowNode) {
457
+ connectNodes (node1: SpeechFlowNode, node2: SpeechFlowNode) {
422
458
  cli!.log("info", `connect node <${node1.id}> to node <${node2.id}>`)
423
459
  node1.connect(node2)
424
460
  }
@@ -481,7 +517,7 @@ let debug = false
481
517
  new Promise<never>((resolve, reject) => setTimeout(() =>
482
518
  reject(new Error("timeout")), 10 * 1000))
483
519
  ]).catch((err: Error) => {
484
- cli!.log("error", `[${node.id}]: failed to open node <${node.id}>: ${err.message}`)
520
+ cli!.log("error", `<${node.id}>: failed to open node <${node.id}>: ${err.message}`)
485
521
  throw new Error(`failed to open node <${node.id}>: ${err.message}`)
486
522
  })
487
523
  }
@@ -631,8 +667,7 @@ let debug = false
631
667
  hapi.route({
632
668
  method: "GET",
633
669
  path: "/api/{req}/{node}/{params*}",
634
- options: {
635
- },
670
+ options: {},
636
671
  handler: (request: HAPI.Request, h: HAPI.ResponseToolkit) => {
637
672
  const peer = request.info.remoteAddress
638
673
  const params = request.params.params as string ?? ""
@@ -644,11 +679,9 @@ let debug = false
644
679
  args: params.split("/").filter((seg) => seg !== "")
645
680
  }
646
681
  cli!.log("info", `HAPI: peer ${peer}: GET: ${JSON.stringify(req)}`)
647
- return consumeExternalRequest(req).then(() => {
648
- return h.response({ response: "OK" }).code(200)
649
- }).catch((err) => {
650
- return h.response({ response: "ERROR", data: err.message }).code(417)
651
- })
682
+ return consumeExternalRequest(req)
683
+ .then(() => h.response({ response: "OK" }).code(200))
684
+ .catch((err) => h.response({ response: "ERROR", data: err.message }).code(417))
652
685
  }
653
686
  })
654
687
  hapi.route({
@@ -691,11 +724,9 @@ let debug = false
691
724
  if (req instanceof arktype.type.errors)
692
725
  return h.response({ response: "ERROR", data: `invalid request: ${req.summary}` }).code(417)
693
726
  cli!.log("info", `HAPI: peer ${peer}: POST: ${JSON.stringify(req)}`)
694
- return consumeExternalRequest(req).then(() => {
695
- return h.response({ response: "OK" }).code(200)
696
- }).catch((err: Error) => {
697
- return h.response({ response: "ERROR", data: err.message }).code(417)
698
- })
727
+ return consumeExternalRequest(req)
728
+ .then(() => h.response({ response: "OK" }).code(200))
729
+ .catch((err: Error) => h.response({ response: "ERROR", data: err.message }).code(417))
699
730
  }
700
731
  })
701
732
  await hapi.start()
@@ -713,10 +744,25 @@ let debug = false
713
744
  })
714
745
  }
715
746
 
716
- /* hook for dashboardInfo method of nodes */
747
+ /* establish OSC event emission */
748
+ let sendOSC: (url: string, ...args: any[]) => void
749
+ if (args.o !== "") {
750
+ const osc = new OSC({ plugin: new OSC.DatagramPlugin({ type: "udp4" }) })
751
+ const m = args.o.match(/^(.+?):(\d+)$/)
752
+ if (m === null)
753
+ throw new Error("invalid OSC/UDP endpoint (expected <ip-adress>:<udp-port>)")
754
+ const host = m[1]
755
+ const port = m[2]
756
+ sendOSC = (url: string, ...args: any[]) => {
757
+ const msg = new OSC.Message(url, ...args)
758
+ osc.send(msg, { host, port })
759
+ }
760
+ }
761
+
762
+ /* hook for send-dashboard method of nodes */
717
763
  for (const node of graphNodes) {
718
- node.on("dashboard-info", (info: {
719
- type: string,
764
+ node.on("send-dashboard", (info: {
765
+ type: "audio" | "text",
720
766
  id: string,
721
767
  kind: "final" | "intermediate",
722
768
  value: string | number
@@ -730,6 +776,17 @@ let debug = false
730
776
  cli!.log("debug", `HAPI: dashboard peer ${peer}: send ${data}`)
731
777
  info.ws.send(data)
732
778
  }
779
+ for (const node of graphNodes) {
780
+ Promise.race<void>([
781
+ node.receiveDashboard(info.type, info.id, info.kind, info.value),
782
+ new Promise<never>((resolve, reject) => setTimeout(() =>
783
+ reject(new Error("timeout")), 10 * 1000))
784
+ ]).catch((err: Error) => {
785
+ cli!.log("warning", `sending dashboard info to node <${node.id}> failed: ${err.message}`)
786
+ })
787
+ }
788
+ if (args.o !== "")
789
+ sendOSC("/speechflow/dashboard", info.type, info.id, info.kind, info.value)
733
790
  })
734
791
  }
735
792