speechflow 1.0.0 → 1.2.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 (75) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +46 -11
  3. package/dst/speechflow-node-a2a-gender.d.ts +17 -0
  4. package/dst/speechflow-node-a2a-gender.js +272 -0
  5. package/dst/speechflow-node-a2a-gender.js.map +1 -0
  6. package/dst/speechflow-node-a2a-meter.js +7 -3
  7. package/dst/speechflow-node-a2a-meter.js.map +1 -1
  8. package/dst/speechflow-node-a2a-mute.js +1 -0
  9. package/dst/speechflow-node-a2a-mute.js.map +1 -1
  10. package/dst/speechflow-node-a2a-vad.js +47 -63
  11. package/dst/speechflow-node-a2a-vad.js.map +1 -1
  12. package/dst/speechflow-node-a2a-wav.js +145 -122
  13. package/dst/speechflow-node-a2a-wav.js.map +1 -1
  14. package/dst/speechflow-node-a2t-deepgram.d.ts +3 -0
  15. package/dst/speechflow-node-a2t-deepgram.js +29 -4
  16. package/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  17. package/dst/speechflow-node-t2a-elevenlabs.d.ts +3 -0
  18. package/dst/speechflow-node-t2a-elevenlabs.js +18 -6
  19. package/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
  20. package/dst/speechflow-node-t2a-kokoro.js.map +1 -1
  21. package/dst/speechflow-node-t2t-deepl.d.ts +3 -0
  22. package/dst/speechflow-node-t2t-deepl.js +8 -1
  23. package/dst/speechflow-node-t2t-deepl.js.map +1 -1
  24. package/dst/speechflow-node-t2t-format.js.map +1 -1
  25. package/dst/speechflow-node-t2t-ollama.js.map +1 -1
  26. package/dst/speechflow-node-t2t-openai.js +1 -1
  27. package/dst/speechflow-node-t2t-openai.js.map +1 -1
  28. package/dst/speechflow-node-t2t-subtitle.js.map +1 -1
  29. package/dst/speechflow-node-t2t-transformers.js.map +1 -1
  30. package/dst/speechflow-node-x2x-filter.d.ts +11 -0
  31. package/dst/speechflow-node-x2x-filter.js +113 -0
  32. package/dst/speechflow-node-x2x-filter.js.map +1 -0
  33. package/dst/speechflow-node-x2x-trace.js +25 -11
  34. package/dst/speechflow-node-x2x-trace.js.map +1 -1
  35. package/dst/speechflow-node-xio-device.js +17 -6
  36. package/dst/speechflow-node-xio-device.js.map +1 -1
  37. package/dst/speechflow-node-xio-file.js +61 -28
  38. package/dst/speechflow-node-xio-file.js.map +1 -1
  39. package/dst/speechflow-node-xio-mqtt.js +7 -5
  40. package/dst/speechflow-node-xio-mqtt.js.map +1 -1
  41. package/dst/speechflow-node-xio-websocket.js +5 -5
  42. package/dst/speechflow-node-xio-websocket.js.map +1 -1
  43. package/dst/speechflow-node.d.ts +5 -1
  44. package/dst/speechflow-node.js +9 -2
  45. package/dst/speechflow-node.js.map +1 -1
  46. package/dst/speechflow-utils.d.ts +14 -1
  47. package/dst/speechflow-utils.js +110 -2
  48. package/dst/speechflow-utils.js.map +1 -1
  49. package/dst/speechflow.js +73 -14
  50. package/dst/speechflow.js.map +1 -1
  51. package/etc/speechflow.yaml +53 -26
  52. package/package.json +12 -10
  53. package/src/speechflow-node-a2a-gender.ts +272 -0
  54. package/src/speechflow-node-a2a-meter.ts +8 -4
  55. package/src/speechflow-node-a2a-mute.ts +1 -0
  56. package/src/speechflow-node-a2a-vad.ts +58 -68
  57. package/src/speechflow-node-a2a-wav.ts +128 -91
  58. package/src/speechflow-node-a2t-deepgram.ts +32 -5
  59. package/src/speechflow-node-t2a-elevenlabs.ts +21 -8
  60. package/src/speechflow-node-t2a-kokoro.ts +3 -3
  61. package/src/speechflow-node-t2t-deepl.ts +11 -3
  62. package/src/speechflow-node-t2t-format.ts +2 -2
  63. package/src/speechflow-node-t2t-ollama.ts +2 -2
  64. package/src/speechflow-node-t2t-openai.ts +3 -3
  65. package/src/speechflow-node-t2t-subtitle.ts +1 -1
  66. package/src/speechflow-node-t2t-transformers.ts +2 -2
  67. package/src/speechflow-node-x2x-filter.ts +122 -0
  68. package/src/speechflow-node-x2x-trace.ts +29 -12
  69. package/src/speechflow-node-xio-device.ts +24 -9
  70. package/src/speechflow-node-xio-file.ts +76 -36
  71. package/src/speechflow-node-xio-mqtt.ts +11 -9
  72. package/src/speechflow-node-xio-websocket.ts +7 -7
  73. package/src/speechflow-node.ts +11 -2
  74. package/src/speechflow-utils.ts +81 -2
  75. package/src/speechflow.ts +96 -35
package/src/speechflow.ts CHANGED
@@ -5,31 +5,33 @@
5
5
  */
6
6
 
7
7
  /* standard dependencies */
8
- import path from "node:path"
9
- import Stream from "node:stream"
10
- import { EventEmitter } from "node:events"
11
- import http from "node:http"
12
- import * as HAPI from "@hapi/hapi"
13
- import WebSocket from "ws"
14
- import HAPIWebSocket from "hapi-plugin-websocket"
15
- import HAPIHeader from "hapi-plugin-header"
8
+ import path from "node:path"
9
+ import Stream from "node:stream"
10
+ import { EventEmitter } from "node:events"
11
+ import http from "node:http"
12
+ import * as HAPI from "@hapi/hapi"
13
+ import WebSocket from "ws"
14
+ import HAPIWebSocket from "hapi-plugin-websocket"
15
+ import HAPIHeader from "hapi-plugin-header"
16
16
 
17
17
  /* external dependencies */
18
- import { DateTime } from "luxon"
19
- import CLIio from "cli-io"
20
- import yargs from "yargs"
21
- import { hideBin } from "yargs/helpers"
22
- import jsYAML from "js-yaml"
23
- import FlowLink from "flowlink"
24
- import objectPath from "object-path"
25
- import installedPackages from "installed-packages"
26
- import dotenvx from "@dotenvx/dotenvx"
27
- import syspath from "syspath"
28
- import * as arktype from "arktype"
18
+ import { DateTime } from "luxon"
19
+ import CLIio from "cli-io"
20
+ import yargs from "yargs"
21
+ import { hideBin } from "yargs/helpers"
22
+ import jsYAML from "js-yaml"
23
+ import FlowLink from "flowlink"
24
+ import objectPath from "object-path"
25
+ import installedPackages from "installed-packages"
26
+ import dotenvx from "@dotenvx/dotenvx"
27
+ import syspath from "syspath"
28
+ import * as arktype from "arktype"
29
+ import Table from "cli-table3"
30
+ import chalk from "chalk"
29
31
 
30
32
  /* internal dependencies */
31
- import SpeechFlowNode from "./speechflow-node"
32
- import pkg from "../package.json"
33
+ import SpeechFlowNode from "./speechflow-node"
34
+ import pkg from "../package.json"
33
35
 
34
36
  /* central CLI context */
35
37
  let cli: CLIio | null = null
@@ -63,11 +65,13 @@ type wsPeerInfo = {
63
65
  "[-a|--address <ip-address>] " +
64
66
  "[-p|--port <tcp-port>] " +
65
67
  "[-C|--cache <directory>] " +
68
+ "[-S|--status] " +
66
69
  "[-e|--expression <expression>] " +
67
70
  "[-f|--file <file>] " +
68
71
  "[-c|--config <id>@<yaml-config-file>] " +
69
72
  "[<argument> [...]]"
70
73
  )
74
+ .version(false)
71
75
  .option("V", {
72
76
  alias: "version",
73
77
  type: "boolean",
@@ -112,6 +116,14 @@ type wsPeerInfo = {
112
116
  default: path.join(dataDir, "cache"),
113
117
  describe: "directory for cached files (primarily AI model files)"
114
118
  })
119
+ .option("S", {
120
+ alias: "status",
121
+ type: "boolean",
122
+ array: false,
123
+ coerce,
124
+ default: false,
125
+ describe: "show one-time status of nodes"
126
+ })
115
127
  .option("e", {
116
128
  alias: "expression",
117
129
  type: "string",
@@ -142,7 +154,6 @@ type wsPeerInfo = {
142
154
  .help("h", "show usage help")
143
155
  .alias("h", "help")
144
156
  .showHelpOnFail(true)
145
- .version(false)
146
157
  .strict()
147
158
  .demand(0)
148
159
  .parse(hideBin(process.argv))
@@ -223,6 +234,7 @@ type wsPeerInfo = {
223
234
  "./speechflow-node-a2a-wav.js",
224
235
  "./speechflow-node-a2a-mute.js",
225
236
  "./speechflow-node-a2a-meter.js",
237
+ "./speechflow-node-a2a-gender.js",
226
238
  "./speechflow-node-a2a-vad.js",
227
239
  "./speechflow-node-a2t-deepgram.js",
228
240
  "./speechflow-node-t2a-elevenlabs.js",
@@ -233,6 +245,7 @@ type wsPeerInfo = {
233
245
  "./speechflow-node-t2t-transformers.js",
234
246
  "./speechflow-node-t2t-subtitle.js",
235
247
  "./speechflow-node-t2t-format.js",
248
+ "./speechflow-node-x2x-filter.js",
236
249
  "./speechflow-node-x2x-trace.js",
237
250
  "./speechflow-node-xio-device.js",
238
251
  "./speechflow-node-xio-file.js",
@@ -268,6 +281,45 @@ type wsPeerInfo = {
268
281
  }
269
282
  }
270
283
 
284
+ /* static configuration */
285
+ const cfg = {
286
+ audioChannels: 1,
287
+ audioBitDepth: 16,
288
+ audioLittleEndian: true,
289
+ audioSampleRate: 48000,
290
+ textEncoding: "utf8",
291
+ cacheDir: args.C
292
+ }
293
+
294
+ /* handle one-time status query of nodes */
295
+ if (args.S) {
296
+ const table = new Table({
297
+ head: [
298
+ chalk.reset.bold("NODE"),
299
+ chalk.reset.bold("PROPERTY"),
300
+ chalk.reset.bold("VALUE")
301
+ ],
302
+ colWidths: [ 15, 15, 50 - (2 * 2 + 2 * 3) ],
303
+ style: { "padding-left": 1, "padding-right": 1, border: [ "grey" ], compact: true },
304
+ chars: { "left-mid": "", mid: "", "mid-mid": "", "right-mid": "" }
305
+ })
306
+ for (const name of Object.keys(nodes)) {
307
+ cli!.log("info", `gathering status of node <${name}>`)
308
+ const node = new nodes[name](name, cfg, {}, [])
309
+ const status = await node.status()
310
+ if (Object.keys(status).length > 0) {
311
+ let first = true
312
+ for (const key of Object.keys(status)) {
313
+ table.push([ first ? chalk.bold(name) : "", key, chalk.blue(status[key]) ])
314
+ first = false
315
+ }
316
+ }
317
+ }
318
+ const output = table.toString()
319
+ process.stdout.write(output + "\n")
320
+ process.exit(0)
321
+ }
322
+
271
323
  /* graph processing: PASS 1: parse DSL and create and connect nodes */
272
324
  const flowlink = new FlowLink<SpeechFlowNode>({
273
325
  trace: (msg: string) => {
@@ -277,14 +329,6 @@ type wsPeerInfo = {
277
329
  const variables = { argv: args._, env: process.env }
278
330
  const graphNodes = new Set<SpeechFlowNode>()
279
331
  const nodeNums = new Map<typeof SpeechFlowNode, number>()
280
- const cfg = {
281
- audioChannels: 1,
282
- audioBitDepth: 16,
283
- audioLittleEndian: true,
284
- audioSampleRate: 48000,
285
- textEncoding: "utf8",
286
- cacheDir: args.C
287
- }
288
332
  let ast: unknown
289
333
  try {
290
334
  ast = flowlink.compile(config)
@@ -429,9 +473,22 @@ type wsPeerInfo = {
429
473
  throw new Error(`stream of node "${node.id}" still not initialized`)
430
474
  cli!.log("info", `observe stream of node "${node.id}" for finish event`)
431
475
  activeNodes.add(node)
476
+ node.stream.on("end", () => {
477
+ if (activeNodes.has(node))
478
+ activeNodes.delete(node)
479
+ cli!.log("info", `readable stream of node "${node.id}" ended (${activeNodes.size} nodes remaining active)`)
480
+ if (activeNodes.size === 0) {
481
+ const timeFinished = DateTime.now()
482
+ const duration = timeFinished.diff(timeZero)
483
+ cli!.log("info", "everything finished -- stream processing in SpeechFlow graph stops " +
484
+ `(total duration: ${duration.toFormat("hh:mm:ss.SSS")})`)
485
+ finishEvents.emit("finished")
486
+ }
487
+ })
432
488
  node.stream.on("finish", () => {
433
- activeNodes.delete(node)
434
- cli!.log("info", `stream of node "${node.id}" finished (${activeNodes.size} nodes remaining active)`)
489
+ if (activeNodes.has(node))
490
+ activeNodes.delete(node)
491
+ cli!.log("info", `writable stream of node "${node.id}" finished (${activeNodes.size} nodes remaining active)`)
435
492
  if (activeNodes.size === 0) {
436
493
  const timeFinished = DateTime.now()
437
494
  const duration = timeFinished.diff(timeZero)
@@ -654,10 +711,14 @@ type wsPeerInfo = {
654
711
  }
655
712
 
656
713
  /* terminate process */
657
- if (signal === "finished")
714
+ if (signal === "finished") {
715
+ cli!.log("info", "terminate process (exit code 0)")
658
716
  process.exit(0)
659
- else
717
+ }
718
+ else {
719
+ cli!.log("info", "terminate process (exit code 1)")
660
720
  process.exit(1)
721
+ }
661
722
  }
662
723
  finishEvents.on("finished", () => {
663
724
  shutdown("finished")
@@ -678,7 +739,7 @@ type wsPeerInfo = {
678
739
  if (cli !== null)
679
740
  cli.log("error", err.message)
680
741
  else
681
- process.stderr.write(`${pkg.name}: ERROR: ${err.message}\n`)
742
+ process.stderr.write(`${pkg.name}: ${chalk.red("ERROR")}: ${err.message} ${err.stack}\n`)
682
743
  process.exit(1)
683
744
  })
684
745