speechflow 2.0.3 → 2.1.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 (78) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +43 -14
  3. package/etc/speechflow.yaml +20 -48
  4. package/etc/stx.conf +2 -2
  5. package/package.json +5 -5
  6. package/speechflow-cli/dst/speechflow-node-a2a-gtcrn-wt.d.ts +1 -0
  7. package/speechflow-cli/dst/speechflow-node-a2a-gtcrn-wt.js +60 -0
  8. package/speechflow-cli/dst/speechflow-node-a2a-gtcrn-wt.js.map +1 -0
  9. package/speechflow-cli/dst/speechflow-node-a2a-gtcrn.d.ts +15 -0
  10. package/speechflow-cli/dst/speechflow-node-a2a-gtcrn.js +234 -0
  11. package/speechflow-cli/dst/speechflow-node-a2a-gtcrn.js.map +1 -0
  12. package/speechflow-cli/dst/speechflow-node-a2a-meter.js +2 -2
  13. package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -1
  14. package/speechflow-cli/dst/speechflow-node-a2t-amazon.d.ts +1 -0
  15. package/speechflow-cli/dst/speechflow-node-a2t-amazon.js +19 -11
  16. package/speechflow-cli/dst/speechflow-node-a2t-amazon.js.map +1 -1
  17. package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.d.ts +16 -0
  18. package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.js +275 -0
  19. package/speechflow-cli/dst/speechflow-node-a2t-assemblyai.js.map +1 -0
  20. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +32 -15
  21. package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -1
  22. package/speechflow-cli/dst/speechflow-node-a2t-openai.js +7 -6
  23. package/speechflow-cli/dst/speechflow-node-a2t-openai.js.map +1 -1
  24. package/speechflow-cli/dst/speechflow-node-t2a-amazon.js +2 -4
  25. package/speechflow-cli/dst/speechflow-node-t2a-amazon.js.map +1 -1
  26. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +3 -3
  27. package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -1
  28. package/speechflow-cli/dst/speechflow-node-t2a-google.js.map +1 -1
  29. package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js +1 -1
  30. package/speechflow-cli/dst/speechflow-node-t2a-supertonic.js.map +1 -1
  31. package/speechflow-cli/dst/speechflow-node-t2t-amazon.js +9 -8
  32. package/speechflow-cli/dst/speechflow-node-t2t-amazon.js.map +1 -1
  33. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +3 -3
  34. package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -1
  35. package/speechflow-cli/dst/speechflow-node-t2t-opus.js +5 -5
  36. package/speechflow-cli/dst/speechflow-node-t2t-opus.js.map +1 -1
  37. package/speechflow-cli/dst/speechflow-node-t2t-profanity.js +26 -6
  38. package/speechflow-cli/dst/speechflow-node-t2t-profanity.js.map +1 -1
  39. package/speechflow-cli/dst/speechflow-node-t2t-punctuation.js.map +1 -1
  40. package/speechflow-cli/dst/speechflow-node-t2t-sentence.d.ts +1 -0
  41. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +72 -5
  42. package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -1
  43. package/speechflow-cli/dst/speechflow-node-t2t-spellcheck.js.map +1 -1
  44. package/speechflow-cli/dst/speechflow-node-t2t-summary.js.map +1 -1
  45. package/speechflow-cli/dst/speechflow-node-t2t-translate.js +50 -25
  46. package/speechflow-cli/dst/speechflow-node-t2t-translate.js.map +1 -1
  47. package/speechflow-cli/etc/oxlint.jsonc +9 -1
  48. package/speechflow-cli/etc/stx.conf +1 -1
  49. package/speechflow-cli/package.d/sherpa-onnx+1.12.23.patch +12 -0
  50. package/speechflow-cli/package.json +23 -19
  51. package/speechflow-cli/src/lib.d.ts +30 -4
  52. package/speechflow-cli/src/speechflow-node-a2a-gtcrn-wt.ts +68 -0
  53. package/speechflow-cli/src/speechflow-node-a2a-gtcrn.ts +219 -0
  54. package/speechflow-cli/src/speechflow-node-a2a-meter.ts +2 -2
  55. package/speechflow-cli/src/speechflow-node-a2t-amazon.ts +21 -12
  56. package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +33 -15
  57. package/speechflow-cli/src/speechflow-node-a2t-openai.ts +9 -8
  58. package/speechflow-cli/src/speechflow-node-t2a-amazon.ts +2 -4
  59. package/speechflow-cli/src/speechflow-node-t2a-elevenlabs.ts +3 -3
  60. package/speechflow-cli/src/speechflow-node-t2a-google.ts +2 -2
  61. package/speechflow-cli/src/speechflow-node-t2a-supertonic.ts +1 -1
  62. package/speechflow-cli/src/speechflow-node-t2t-amazon.ts +11 -10
  63. package/speechflow-cli/src/speechflow-node-t2t-deepl.ts +3 -3
  64. package/speechflow-cli/src/speechflow-node-t2t-opus.ts +6 -6
  65. package/speechflow-cli/src/speechflow-node-t2t-profanity.ts +30 -11
  66. package/speechflow-cli/src/speechflow-node-t2t-punctuation.ts +1 -1
  67. package/speechflow-cli/src/speechflow-node-t2t-sentence.ts +86 -10
  68. package/speechflow-cli/src/speechflow-node-t2t-spellcheck.ts +1 -1
  69. package/speechflow-cli/src/speechflow-node-t2t-summary.ts +1 -1
  70. package/speechflow-cli/src/speechflow-node-t2t-translate.ts +54 -29
  71. package/speechflow-ui-db/dst/index.css +1 -1
  72. package/speechflow-ui-db/dst/index.js +13 -13
  73. package/speechflow-ui-db/package.json +16 -15
  74. package/speechflow-ui-db/src/app.vue +62 -17
  75. package/speechflow-ui-st/dst/index.css +1 -1
  76. package/speechflow-ui-st/dst/index.js +32 -32
  77. package/speechflow-ui-st/package.json +17 -16
  78. package/speechflow-ui-st/src/app.vue +9 -8
@@ -14,23 +14,23 @@
14
14
  "url": "http://engelschall.com"
15
15
  },
16
16
  "dependencies": {
17
- "vue": "3.5.26",
17
+ "vue": "3.5.27",
18
18
  "luxon": "3.7.2",
19
19
  "@opensumi/reconnecting-websocket": "4.4.0",
20
- "axios": "1.13.2",
20
+ "axios": "1.13.3",
21
21
  "typopro-web": "4.2.8",
22
22
  "@fortawesome/fontawesome-free": "7.1.0",
23
23
  "patch-package": "8.0.1",
24
24
  "@rse/stx": "1.1.4"
25
25
  },
26
26
  "devDependencies": {
27
- "vite": "7.3.0",
28
- "typescript-eslint": "8.50.1",
29
- "@typescript-eslint/eslint-plugin": "8.50.1",
30
- "@typescript-eslint/parser": "8.50.1",
27
+ "vite": "7.3.1",
28
+ "typescript-eslint": "8.54.0",
29
+ "@typescript-eslint/eslint-plugin": "8.54.0",
30
+ "@typescript-eslint/parser": "8.54.0",
31
31
  "@vitejs/plugin-vue": "6.0.3",
32
32
  "@rollup/plugin-yaml": "4.1.2",
33
- "vite-plugin-node-polyfills": "0.24.0",
33
+ "vite-plugin-node-polyfills": "0.25.0",
34
34
  "vite-svg-loader": "5.1.0",
35
35
  "@liuli-util/vite-plugin-node": "0.10.0",
36
36
  "mkdirp": "3.0.1",
@@ -41,10 +41,10 @@
41
41
  "@eslint/js": "9.39.2",
42
42
  "neostandard": "0.12.2",
43
43
  "eslint-plugin-import": "2.32.0",
44
- "eslint-plugin-vue": "10.6.2",
44
+ "eslint-plugin-vue": "10.7.0",
45
45
 
46
- "oxlint": "1.35.0",
47
- "eslint-plugin-oxlint": "1.35.0",
46
+ "oxlint": "1.42.0",
47
+ "eslint-plugin-oxlint": "1.42.0",
48
48
 
49
49
  "htmllint": "0.8.0",
50
50
  "htmllint-cli": "0.0.7",
@@ -52,16 +52,16 @@
52
52
  "check-dependencies": "2.0.0",
53
53
  "nodemon": "3.1.11",
54
54
  "shx": "0.4.0",
55
- "stylelint": "16.26.1",
55
+ "stylelint": "17.0.0",
56
56
  "stylelint-config-html": "1.1.0",
57
57
  "stylelint-config-recommended-vue": "1.6.1",
58
- "stylelint-config-standard": "39.0.1",
58
+ "stylelint-config-standard": "40.0.0",
59
59
  "stylelint-config-standard-vue": "1.0.0",
60
60
  "stylelint-stylus": "1.0.0",
61
- "postcss-html": "1.8.0",
61
+ "postcss-html": "1.8.1",
62
62
  "stylus": "0.64.0",
63
63
  "typescript": "5.9.3",
64
- "vue-tsc": "3.2.1",
64
+ "vue-tsc": "3.2.4",
65
65
  "delay-cli": "3.0.0",
66
66
  "cross-env": "10.1.0",
67
67
  "serve": "14.2.5",
@@ -69,7 +69,8 @@
69
69
  "@types/luxon": "3.7.1"
70
70
  },
71
71
  "overrides": {
72
- "@liuli-util/vite-plugin-node": { "vite": ">=6.0.0" }
72
+ "@liuli-util/vite-plugin-node": { "vite": ">=6.0.0" },
73
+ "stylelint-stylus": { "stylelint": "^17.0.0" }
73
74
  },
74
75
  "engines" : {
75
76
  "npm": ">=10.0.0",
@@ -72,6 +72,7 @@
72
72
  flex-grow: 1
73
73
  flex-shrink: 1
74
74
  flex-basis: 0
75
+ min-width: 0
75
76
  .block-name
76
77
  width: 100%
77
78
  height: 2.5vw
@@ -142,24 +143,38 @@ import axios from "axios"
142
143
  </script>
143
144
 
144
145
  <script lang="ts">
146
+ /* LUFS value with timestamp for temporal averaging */
147
+ interface LufsEntry {
148
+ value: number,
149
+ time: number
150
+ }
151
+
152
+ /* duration for LUFS-M display averaging window (ms) */
153
+ const lufsWindowMs = 400
154
+
155
+ /* type of a single text or audio block */
145
156
  type Info = {
146
- type: string,
147
- id: string,
148
- name: string,
149
- value: number | string[],
150
- lastKind: string
157
+ type: string,
158
+ id: string,
159
+ name: string,
160
+ value: number | string[],
161
+ lastKind: string,
162
+ lufsBuffer?: LufsEntry[]
151
163
  }
152
164
 
165
+ /* type of a websocket event message */
153
166
  interface WebSocketEvent {
154
167
  response: string,
155
168
  args: [ string, string, string, number | string ]
156
169
  }
157
170
 
171
+ /* the Vue component */
158
172
  export default defineComponent({
159
173
  name: "app",
160
174
  data: () => ({
161
- info: [] as Info[],
162
- ws: null as ReconnectingWebSocket | null
175
+ info: [] as Info[],
176
+ ws: null as ReconnectingWebSocket | null,
177
+ lufsTimer: null as ReturnType<typeof setInterval> | null
163
178
  }),
164
179
  async mounted () {
165
180
  /* determine API URLs */
@@ -171,15 +186,15 @@ export default defineComponent({
171
186
  const response = await axios.get(`${urlHTTP.toString()}/dashboard`)
172
187
  for (const block of response.data) {
173
188
  if (block.type === "audio")
174
- this.info.push({ type: block.type, id: block.id, name: block.name, value: 0, lastKind: "" })
189
+ this.info.push({ type: block.type, id: block.id, name: block.name, value: -60, lastKind: "", lufsBuffer: [] })
175
190
  else if (block.type === "text")
176
191
  this.info.push({ type: block.type, id: block.id, name: block.name, value: [], lastKind: "" })
177
192
  }
178
193
 
179
- /* initialize meters */
180
- for (const block of this.info)
181
- if (block.type === "audio")
182
- block.value = -60
194
+ /* start timer to update LUFS display values from buffered entries */
195
+ this.lufsTimer = setInterval(() => {
196
+ this.updateLufsDisplayValues()
197
+ }, 50)
183
198
 
184
199
  /* connect to WebSocket API for receiving dashboard information */
185
200
  this.ws = new ReconnectingWebSocket(urlWS.toString(), [], {
@@ -200,10 +215,13 @@ export default defineComponent({
200
215
  this.ws.addEventListener("close", (ev) => {
201
216
  this.log("INFO", "WebSocket connection destroyed")
202
217
 
203
- /* reset meters */
204
- for (const block of this.info)
205
- if (block.type === "audio")
218
+ /* reset meters and clear LUFS buffers */
219
+ for (const block of this.info) {
220
+ if (block.type === "audio" && block.lufsBuffer !== undefined) {
206
221
  block.value = -60
222
+ block.lufsBuffer.length = 0
223
+ }
224
+ }
207
225
  })
208
226
 
209
227
  /* receive messages */
@@ -223,9 +241,10 @@ export default defineComponent({
223
241
  const [ type, id, kind, value ] = event.args
224
242
  for (const block of this.info) {
225
243
  if (block.type === type && block.id === id) {
226
- if (block.type === "audio") {
244
+ if (block.type === "audio" && block.lufsBuffer !== undefined) {
245
+ /* buffer LUFS values for temporal averaging */
227
246
  if (kind === "final" && typeof value === "number")
228
- block.value = value
247
+ block.lufsBuffer.push({ value, time: Date.now() })
229
248
  }
230
249
  else {
231
250
  if (typeof value === "string") {
@@ -248,6 +267,10 @@ export default defineComponent({
248
267
  })
249
268
  },
250
269
  beforeUnmount () {
270
+ if (this.lufsTimer) {
271
+ clearInterval(this.lufsTimer)
272
+ this.lufsTimer = null
273
+ }
251
274
  if (this.ws) {
252
275
  this.ws.close()
253
276
  this.ws = null
@@ -263,6 +286,28 @@ export default defineComponent({
263
286
  .join(", ")
264
287
  })`
265
288
  console.log(output)
289
+ },
290
+
291
+ /* update LUFS display values from buffered entries */
292
+ updateLufsDisplayValues () {
293
+ const now = Date.now()
294
+ for (const block of this.info) {
295
+ if (block.type !== "audio" || block.lufsBuffer === undefined)
296
+ continue
297
+
298
+ /* remove entries older than the window duration */
299
+ const buffer = block.lufsBuffer
300
+ while (buffer.length > 0 && (now - buffer[0].time) > lufsWindowMs)
301
+ buffer.shift()
302
+
303
+ /* calculate average of remaining entries or fall back to silence */
304
+ if (buffer.length > 0) {
305
+ const sum = buffer.reduce((acc, entry) => acc + entry.value, 0)
306
+ block.value = sum / buffer.length
307
+ }
308
+ else
309
+ block.value = -60
310
+ }
266
311
  }
267
312
  }
268
313
  })