speechflow 0.9.9 → 1.0.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 (110) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +48 -1
  3. package/dst/speechflow-node-a2a-ffmpeg.js +1 -0
  4. package/dst/speechflow-node-a2a-ffmpeg.js.map +1 -0
  5. package/dst/{speechflow-node-gemma.d.ts → speechflow-node-a2a-meter.d.ts} +2 -3
  6. package/dst/speechflow-node-a2a-meter.js +147 -0
  7. package/dst/speechflow-node-a2a-meter.js.map +1 -0
  8. package/dst/speechflow-node-a2a-mute.d.ts +16 -0
  9. package/dst/speechflow-node-a2a-mute.js +90 -0
  10. package/dst/speechflow-node-a2a-mute.js.map +1 -0
  11. package/dst/speechflow-node-a2a-vad.js +130 -289
  12. package/dst/speechflow-node-a2a-vad.js.map +1 -0
  13. package/dst/speechflow-node-a2a-wav.js +1 -0
  14. package/dst/speechflow-node-a2a-wav.js.map +1 -0
  15. package/dst/speechflow-node-a2t-deepgram.js +2 -1
  16. package/dst/speechflow-node-a2t-deepgram.js.map +1 -0
  17. package/dst/speechflow-node-t2a-elevenlabs.js +1 -0
  18. package/dst/speechflow-node-t2a-elevenlabs.js.map +1 -0
  19. package/dst/speechflow-node-t2a-kokoro.js +1 -0
  20. package/dst/speechflow-node-t2a-kokoro.js.map +1 -0
  21. package/dst/speechflow-node-t2t-deepl.js +1 -0
  22. package/dst/speechflow-node-t2t-deepl.js.map +1 -0
  23. package/dst/speechflow-node-t2t-format.js +1 -0
  24. package/dst/speechflow-node-t2t-format.js.map +1 -0
  25. package/dst/speechflow-node-t2t-ollama.js +1 -0
  26. package/dst/speechflow-node-t2t-ollama.js.map +1 -0
  27. package/dst/speechflow-node-t2t-openai.js +1 -0
  28. package/dst/speechflow-node-t2t-openai.js.map +1 -0
  29. package/dst/speechflow-node-t2t-subtitle.js +1 -0
  30. package/dst/speechflow-node-t2t-subtitle.js.map +1 -0
  31. package/dst/speechflow-node-t2t-transformers.js +10 -6
  32. package/dst/speechflow-node-t2t-transformers.js.map +1 -0
  33. package/dst/speechflow-node-x2x-trace.js +1 -0
  34. package/dst/speechflow-node-x2x-trace.js.map +1 -0
  35. package/dst/speechflow-node-xio-device.js +1 -0
  36. package/dst/speechflow-node-xio-device.js.map +1 -0
  37. package/dst/speechflow-node-xio-file.js +1 -0
  38. package/dst/speechflow-node-xio-file.js.map +1 -0
  39. package/dst/speechflow-node-xio-mqtt.js +1 -0
  40. package/dst/speechflow-node-xio-mqtt.js.map +1 -0
  41. package/dst/speechflow-node-xio-websocket.js +1 -0
  42. package/dst/speechflow-node-xio-websocket.js.map +1 -0
  43. package/dst/speechflow-node.d.ts +3 -0
  44. package/dst/speechflow-node.js +10 -0
  45. package/dst/speechflow-node.js.map +1 -0
  46. package/dst/speechflow-utils.d.ts +33 -0
  47. package/dst/speechflow-utils.js +183 -1
  48. package/dst/speechflow-utils.js.map +1 -0
  49. package/dst/speechflow.js +209 -6
  50. package/dst/speechflow.js.map +1 -0
  51. package/etc/speechflow.yaml +5 -3
  52. package/etc/stx.conf +1 -1
  53. package/etc/tsconfig.json +2 -2
  54. package/package.json +14 -8
  55. package/src/speechflow-node-a2a-meter.ts +125 -0
  56. package/src/speechflow-node-a2a-mute.ts +101 -0
  57. package/src/speechflow-node-a2a-vad.ts +266 -0
  58. package/src/speechflow-node-a2t-deepgram.ts +1 -1
  59. package/src/speechflow-node-t2t-transformers.ts +12 -7
  60. package/src/speechflow-node-xio-websocket.ts +5 -5
  61. package/src/speechflow-node.ts +12 -0
  62. package/src/speechflow-utils.ts +195 -0
  63. package/src/speechflow.ts +193 -6
  64. package/dst/speechflow-node-deepgram.d.ts +0 -12
  65. package/dst/speechflow-node-deepgram.js +0 -220
  66. package/dst/speechflow-node-deepl.d.ts +0 -12
  67. package/dst/speechflow-node-deepl.js +0 -128
  68. package/dst/speechflow-node-device.d.ts +0 -13
  69. package/dst/speechflow-node-device.js +0 -205
  70. package/dst/speechflow-node-elevenlabs.d.ts +0 -13
  71. package/dst/speechflow-node-elevenlabs.js +0 -182
  72. package/dst/speechflow-node-ffmpeg.d.ts +0 -13
  73. package/dst/speechflow-node-ffmpeg.js +0 -152
  74. package/dst/speechflow-node-file.d.ts +0 -11
  75. package/dst/speechflow-node-file.js +0 -176
  76. package/dst/speechflow-node-format.d.ts +0 -11
  77. package/dst/speechflow-node-format.js +0 -80
  78. package/dst/speechflow-node-gemma.js +0 -213
  79. package/dst/speechflow-node-mqtt.d.ts +0 -13
  80. package/dst/speechflow-node-mqtt.js +0 -181
  81. package/dst/speechflow-node-opus.d.ts +0 -12
  82. package/dst/speechflow-node-opus.js +0 -135
  83. package/dst/speechflow-node-subtitle.d.ts +0 -12
  84. package/dst/speechflow-node-subtitle.js +0 -96
  85. package/dst/speechflow-node-t2t-gemma.d.ts +0 -13
  86. package/dst/speechflow-node-t2t-gemma.js +0 -233
  87. package/dst/speechflow-node-t2t-opus.d.ts +0 -12
  88. package/dst/speechflow-node-t2t-opus.js +0 -135
  89. package/dst/speechflow-node-trace.d.ts +0 -11
  90. package/dst/speechflow-node-trace.js +0 -88
  91. package/dst/speechflow-node-wav.d.ts +0 -11
  92. package/dst/speechflow-node-wav.js +0 -170
  93. package/dst/speechflow-node-websocket.d.ts +0 -13
  94. package/dst/speechflow-node-websocket.js +0 -275
  95. package/dst/speechflow-node-whisper-common.d.ts +0 -34
  96. package/dst/speechflow-node-whisper-common.js +0 -7
  97. package/dst/speechflow-node-whisper-ggml.d.ts +0 -1
  98. package/dst/speechflow-node-whisper-ggml.js +0 -97
  99. package/dst/speechflow-node-whisper-onnx.d.ts +0 -1
  100. package/dst/speechflow-node-whisper-onnx.js +0 -131
  101. package/dst/speechflow-node-whisper-worker-ggml.d.ts +0 -1
  102. package/dst/speechflow-node-whisper-worker-ggml.js +0 -97
  103. package/dst/speechflow-node-whisper-worker-onnx.d.ts +0 -1
  104. package/dst/speechflow-node-whisper-worker-onnx.js +0 -131
  105. package/dst/speechflow-node-whisper-worker.d.ts +0 -1
  106. package/dst/speechflow-node-whisper-worker.js +0 -116
  107. package/dst/speechflow-node-whisper-worker2.d.ts +0 -1
  108. package/dst/speechflow-node-whisper-worker2.js +0 -82
  109. package/dst/speechflow-node-whisper.d.ts +0 -19
  110. package/dst/speechflow-node-whisper.js +0 -604
@@ -1,220 +0,0 @@
1
- "use strict";
2
- /*
3
- ** SpeechFlow - Speech Processing Flow Graph
4
- ** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
5
- ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- var __importDefault = (this && this.__importDefault) || function (mod) {
41
- return (mod && mod.__esModule) ? mod : { "default": mod };
42
- };
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- /* standard dependencies */
45
- const node_stream_1 = __importDefault(require("node:stream"));
46
- /* external dependencies */
47
- const Deepgram = __importStar(require("@deepgram/sdk"));
48
- const luxon_1 = require("luxon");
49
- /* internal dependencies */
50
- const speechflow_node_1 = __importStar(require("./speechflow-node"));
51
- const utils = __importStar(require("./speechflow-utils"));
52
- /* SpeechFlow node for Deepgram speech-to-text conversion */
53
- class SpeechFlowNodeDeepgram extends speechflow_node_1.default {
54
- /* declare official node name */
55
- static name = "deepgram";
56
- /* internal state */
57
- dg = null;
58
- /* construct node */
59
- constructor(id, cfg, opts, args) {
60
- super(id, cfg, opts, args);
61
- /* declare node configuration parameters */
62
- this.configure({
63
- key: { type: "string", val: process.env.SPEECHFLOW_KEY_DEEPGRAM },
64
- model: { type: "string", val: "nova-3", pos: 0 },
65
- version: { type: "string", val: "latest", pos: 1 },
66
- language: { type: "string", val: "multi", pos: 2 }
67
- });
68
- /* declare node input/output format */
69
- this.input = "audio";
70
- this.output = "text";
71
- }
72
- /* open node */
73
- async open() {
74
- /* sanity check situation */
75
- if (this.config.audioBitDepth !== 16 || !this.config.audioLittleEndian)
76
- throw new Error("Deepgram node currently supports PCM-S16LE audio only");
77
- /* create queue for results */
78
- const queue = new utils.SingleQueue();
79
- /* connect to Deepgram API */
80
- const deepgram = Deepgram.createClient(this.params.key);
81
- let language = "en";
82
- if (this.params.model.match(/^nova-2/) && this.params.language !== "en")
83
- language = this.params.language;
84
- else if (this.params.model.match(/^nova-3/) && this.params.language !== "en")
85
- language = "multi";
86
- this.dg = deepgram.listen.live({
87
- mip_opt_out: true,
88
- model: this.params.model,
89
- version: this.params.version,
90
- language,
91
- channels: this.config.audioChannels,
92
- sample_rate: this.config.audioSampleRate,
93
- encoding: "linear16",
94
- multichannel: false,
95
- endpointing: 10,
96
- interim_results: false,
97
- smart_format: true,
98
- punctuate: true,
99
- filler_words: true,
100
- diarize: true, /* still not used by us */
101
- numerals: true,
102
- profanity_filter: false
103
- });
104
- /* hook onto Deepgram API events */
105
- this.dg.on(Deepgram.LiveTranscriptionEvents.Transcript, async (data) => {
106
- const text = data.channel?.alternatives[0].transcript ?? "";
107
- if (text === "")
108
- this.log("info", `Deepgram: empty/dummy text received (start: ${data.start}s, duration: ${data.duration}s)`);
109
- else {
110
- this.log("info", `Deepgram: text received (start: ${data.start}s, duration: ${data.duration}s): "${text}"`);
111
- const start = luxon_1.Duration.fromMillis(data.start * 1000).plus(this.timeZeroOffset);
112
- const end = start.plus({ seconds: data.duration });
113
- const chunk = new speechflow_node_1.SpeechFlowChunk(start, end, "final", "text", text);
114
- queue.write(chunk);
115
- }
116
- });
117
- this.dg.on(Deepgram.LiveTranscriptionEvents.Metadata, (data) => {
118
- this.log("info", "Deepgram: metadata received");
119
- });
120
- this.dg.on(Deepgram.LiveTranscriptionEvents.Close, () => {
121
- this.log("info", "Deepgram: connection close");
122
- });
123
- this.dg.on(Deepgram.LiveTranscriptionEvents.Error, (error) => {
124
- this.log("error", `Deepgram: ${error.message}`);
125
- this.emit("error");
126
- });
127
- /* wait for Deepgram API to be available */
128
- await new Promise((resolve, reject) => {
129
- let timer = setTimeout(() => {
130
- if (timer !== null) {
131
- timer = null;
132
- reject(new Error("Deepgram: timeout waiting for connection open"));
133
- }
134
- }, 3000);
135
- this.dg.once(Deepgram.LiveTranscriptionEvents.Open, () => {
136
- this.log("info", "Deepgram: connection open");
137
- if (timer !== null) {
138
- clearTimeout(timer);
139
- timer = null;
140
- }
141
- resolve(true);
142
- });
143
- });
144
- /* remember opening time to receive time zero offset */
145
- this.timeOpen = luxon_1.DateTime.now();
146
- /* workaround Deepgram initialization problems */
147
- let initDone = false;
148
- let initTimeout = null;
149
- const initTimeoutStart = () => {
150
- if (initDone)
151
- return;
152
- setTimeout(async () => {
153
- if (initTimeout === null)
154
- return;
155
- initTimeout = null;
156
- this.log("warning", "Deepgram: initialization timeout -- restarting service usage");
157
- await this.close();
158
- this.open();
159
- }, 3000);
160
- };
161
- const initTimeoutStop = () => {
162
- if (initDone)
163
- return;
164
- initDone = true;
165
- if (initTimeout !== null) {
166
- clearTimeout(initTimeout);
167
- initTimeout = null;
168
- }
169
- };
170
- /* provide Duplex stream and internally attach to Deepgram API */
171
- const dg = this.dg;
172
- const log = (level, msg) => {
173
- this.log(level, msg);
174
- };
175
- const encoding = this.config.textEncoding;
176
- this.stream = new node_stream_1.default.Duplex({
177
- writableObjectMode: true,
178
- readableObjectMode: true,
179
- decodeStrings: false,
180
- write(chunk, encoding, callback) {
181
- if (chunk.type !== "audio")
182
- callback(new Error("expected audio input chunk"));
183
- else if (!Buffer.isBuffer(chunk.payload))
184
- callback(new Error("expected Buffer input chunk"));
185
- else {
186
- if (chunk.payload.byteLength > 0) {
187
- log("info", `Deepgram: send data (${chunk.payload.byteLength} bytes)`);
188
- initTimeoutStart();
189
- dg.send(chunk.payload); /* intentionally discard all time information */
190
- }
191
- callback();
192
- }
193
- },
194
- read(size) {
195
- queue.read().then((chunk) => {
196
- log("info", `Deepgram: receive data (${chunk.payload.length} bytes)`);
197
- initTimeoutStop();
198
- this.push(chunk, encoding);
199
- });
200
- },
201
- final(callback) {
202
- dg.requestClose();
203
- this.push(null);
204
- callback();
205
- }
206
- });
207
- }
208
- /* close node */
209
- async close() {
210
- /* close stream */
211
- if (this.stream !== null) {
212
- this.stream.destroy();
213
- this.stream = null;
214
- }
215
- /* shutdown Deepgram API */
216
- if (this.dg !== null)
217
- this.dg.requestClose();
218
- }
219
- }
220
- exports.default = SpeechFlowNodeDeepgram;
@@ -1,12 +0,0 @@
1
- import SpeechFlowNode from "./speechflow-node";
2
- export default class SpeechFlowNodeDeepL extends SpeechFlowNode {
3
- static name: string;
4
- private deepl;
5
- constructor(id: string, cfg: {
6
- [id: string]: any;
7
- }, opts: {
8
- [id: string]: any;
9
- }, args: any[]);
10
- open(): Promise<void>;
11
- close(): Promise<void>;
12
- }
@@ -1,128 +0,0 @@
1
- "use strict";
2
- /*
3
- ** SpeechFlow - Speech Processing Flow Graph
4
- ** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
5
- ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- var __importDefault = (this && this.__importDefault) || function (mod) {
41
- return (mod && mod.__esModule) ? mod : { "default": mod };
42
- };
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- /* standard dependencies */
45
- const node_stream_1 = __importDefault(require("node:stream"));
46
- /* external dependencies */
47
- const DeepL = __importStar(require("deepl-node"));
48
- /* internal dependencies */
49
- const speechflow_node_1 = __importDefault(require("./speechflow-node"));
50
- /* SpeechFlow node for DeepL text-to-text translations */
51
- class SpeechFlowNodeDeepL extends speechflow_node_1.default {
52
- /* declare official node name */
53
- static name = "deepl";
54
- /* internal state */
55
- deepl = null;
56
- /* construct node */
57
- constructor(id, cfg, opts, args) {
58
- super(id, cfg, opts, args);
59
- /* declare node configuration parameters */
60
- this.configure({
61
- key: { type: "string", val: process.env.SPEECHFLOW_KEY_DEEPL },
62
- src: { type: "string", pos: 0, val: "de", match: /^(?:de|en-US)$/ },
63
- dst: { type: "string", pos: 1, val: "en-US", match: /^(?:de|en-US)$/ },
64
- optimize: { type: "string", pos: 2, val: "latency", match: /^(?:latency|quality)$/ }
65
- });
66
- /* declare node input/output format */
67
- this.input = "text";
68
- this.output = "text";
69
- }
70
- /* open node */
71
- async open() {
72
- /* instantiate DeepL API SDK */
73
- this.deepl = new DeepL.Translator(this.params.key);
74
- /* provide text-to-text translation */
75
- const translate = async (text) => {
76
- const result = await this.deepl.translateText(text, this.params.src, this.params.dst, {
77
- splitSentences: "off",
78
- modelType: this.params.optimize === "latency" ?
79
- "latency_optimized" : "prefer_quality_optimized",
80
- preserveFormatting: true,
81
- formality: "prefer_more"
82
- });
83
- return (result?.text ?? text);
84
- };
85
- /* establish a duplex stream and connect it to DeepL translation */
86
- this.stream = new node_stream_1.default.Transform({
87
- readableObjectMode: true,
88
- writableObjectMode: true,
89
- decodeStrings: false,
90
- transform(chunk, encoding, callback) {
91
- if (Buffer.isBuffer(chunk.payload))
92
- callback(new Error("invalid chunk payload type"));
93
- else {
94
- if (chunk.payload === "") {
95
- this.push(chunk);
96
- callback();
97
- }
98
- else {
99
- translate(chunk.payload).then((payload) => {
100
- const chunkNew = chunk.clone();
101
- chunkNew.payload = payload;
102
- this.push(chunkNew);
103
- callback();
104
- }).catch((err) => {
105
- callback(err);
106
- });
107
- }
108
- }
109
- },
110
- final(callback) {
111
- this.push(null);
112
- callback();
113
- }
114
- });
115
- }
116
- /* open node */
117
- async close() {
118
- /* close stream */
119
- if (this.stream !== null) {
120
- this.stream.destroy();
121
- this.stream = null;
122
- }
123
- /* shutdown DeepL API */
124
- if (this.deepl !== null)
125
- this.deepl = null;
126
- }
127
- }
128
- exports.default = SpeechFlowNodeDeepL;
@@ -1,13 +0,0 @@
1
- import SpeechFlowNode from "./speechflow-node";
2
- export default class SpeechFlowNodeDevice extends SpeechFlowNode {
3
- static name: string;
4
- private io;
5
- constructor(id: string, cfg: {
6
- [id: string]: any;
7
- }, opts: {
8
- [id: string]: any;
9
- }, args: any[]);
10
- private audioDeviceFromURL;
11
- open(): Promise<void>;
12
- close(): Promise<void>;
13
- }
@@ -1,205 +0,0 @@
1
- "use strict";
2
- /*
3
- ** SpeechFlow - Speech Processing Flow Graph
4
- ** Copyright (c) 2024-2025 Dr. Ralf S. Engelschall <rse@engelschall.com>
5
- ** Licensed under GPL 3.0 <https://spdx.org/licenses/GPL-3.0-only>
6
- */
7
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
- if (k2 === undefined) k2 = k;
9
- var desc = Object.getOwnPropertyDescriptor(m, k);
10
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
- desc = { enumerable: true, get: function() { return m[k]; } };
12
- }
13
- Object.defineProperty(o, k2, desc);
14
- }) : (function(o, m, k, k2) {
15
- if (k2 === undefined) k2 = k;
16
- o[k2] = m[k];
17
- }));
18
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
- Object.defineProperty(o, "default", { enumerable: true, value: v });
20
- }) : function(o, v) {
21
- o["default"] = v;
22
- });
23
- var __importStar = (this && this.__importStar) || (function () {
24
- var ownKeys = function(o) {
25
- ownKeys = Object.getOwnPropertyNames || function (o) {
26
- var ar = [];
27
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
- return ar;
29
- };
30
- return ownKeys(o);
31
- };
32
- return function (mod) {
33
- if (mod && mod.__esModule) return mod;
34
- var result = {};
35
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
- __setModuleDefault(result, mod);
37
- return result;
38
- };
39
- })();
40
- var __importDefault = (this && this.__importDefault) || function (mod) {
41
- return (mod && mod.__esModule) ? mod : { "default": mod };
42
- };
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- /* standard dependencies */
45
- const node_stream_1 = __importDefault(require("node:stream"));
46
- /* external dependencies */
47
- const naudiodon_1 = __importDefault(require("@gpeng/naudiodon"));
48
- /* internal dependencies */
49
- const speechflow_node_1 = __importDefault(require("./speechflow-node"));
50
- const utils = __importStar(require("./speechflow-utils"));
51
- /* SpeechFlow node for device access */
52
- class SpeechFlowNodeDevice extends speechflow_node_1.default {
53
- /* declare official node name */
54
- static name = "device";
55
- /* internal state */
56
- io = null;
57
- /* construct node */
58
- constructor(id, cfg, opts, args) {
59
- super(id, cfg, opts, args);
60
- /* declare node configuration parameters */
61
- this.configure({
62
- device: { type: "string", pos: 0, match: /^(.+?):(.+)$/ },
63
- mode: { type: "string", pos: 1, val: "rw", match: /^(?:r|w|rw)$/ }
64
- });
65
- /* declare node input/output format */
66
- if (this.params.mode === "rw") {
67
- this.input = "audio";
68
- this.output = "audio";
69
- }
70
- else if (this.params.mode === "r") {
71
- this.input = "none";
72
- this.output = "audio";
73
- }
74
- else if (this.params.mode === "w") {
75
- this.input = "audio";
76
- this.output = "none";
77
- }
78
- }
79
- /* INTERNAL: utility function for finding audio device by pseudo-URL notation */
80
- audioDeviceFromURL(mode, url) {
81
- /* parse URL */
82
- const m = url.match(/^(.+?):(.+)$/);
83
- if (m === null)
84
- throw new Error(`invalid audio device URL "${url}"`);
85
- const [, type, name] = m;
86
- /* determine audio API */
87
- const apis = naudiodon_1.default.getHostAPIs();
88
- const api = apis.HostAPIs.find((api) => api.type.toLowerCase() === type.toLowerCase());
89
- if (!api)
90
- throw new Error(`invalid audio API type "${type}"`);
91
- /* determine device of audio API */
92
- const devices = naudiodon_1.default.getDevices();
93
- for (const device of devices)
94
- this.log("info", `found audio device "${device.name}" ` +
95
- `(inputs: ${device.maxInputChannels}, outputs: ${device.maxOutputChannels}`);
96
- const device = devices.find((device) => {
97
- return (((mode === "r" && device.maxInputChannels > 0)
98
- || (mode === "w" && device.maxOutputChannels > 0)
99
- || (mode === "rw" && device.maxInputChannels > 0 && device.maxOutputChannels > 0)
100
- || (mode === "any" && (device.maxInputChannels > 0 || device.maxOutputChannels > 0)))
101
- && device.name.match(name)
102
- && device.hostAPIName === api.name);
103
- });
104
- if (!device)
105
- throw new Error(`invalid audio device "${name}" (of audio API type "${type}")`);
106
- return device;
107
- }
108
- /* open node */
109
- async open() {
110
- /* determine device */
111
- const device = this.audioDeviceFromURL(this.params.mode, this.params.device);
112
- /* sanity check sample rate compatibility
113
- (we still do not resample in input/output for simplification reasons) */
114
- if (device.defaultSampleRate !== this.config.audioSampleRate)
115
- throw new Error(`audio device sample rate ${device.defaultSampleRate} is ` +
116
- `incompatible with required sample rate ${this.config.audioSampleRate}`);
117
- /* establish device connection
118
- Notice: "naudion" actually implements Stream.{Readable,Writable,Duplex}, but
119
- declares just its sub-interface NodeJS.{Readable,Writable,Duplex}Stream,
120
- so it is correct to cast it back to Stream.{Readable,Writable,Duplex} */
121
- /* FIXME: the underlying PortAudio outputs verbose/debugging messages */
122
- if (this.params.mode === "rw") {
123
- /* input/output device */
124
- if (device.maxInputChannels === 0)
125
- throw new Error(`device "${device.id}" does not have any input channels (required by read/write mode)`);
126
- if (device.maxOutputChannels === 0)
127
- throw new Error(`device "${device.id}" does not have any output channels (required by read/write mode)`);
128
- this.log("info", `resolved "${this.params.device}" to duplex device "${device.id}"`);
129
- this.io = naudiodon_1.default.AudioIO({
130
- inOptions: {
131
- deviceId: device.id,
132
- channelCount: this.config.audioChannels,
133
- sampleRate: this.config.audioSampleRate,
134
- sampleFormat: this.config.audioBitDepth
135
- },
136
- outOptions: {
137
- deviceId: device.id,
138
- channelCount: this.config.audioChannels,
139
- sampleRate: this.config.audioSampleRate,
140
- sampleFormat: this.config.audioBitDepth
141
- }
142
- });
143
- this.stream = this.io;
144
- /* convert regular stream into object-mode stream */
145
- const wrapper1 = utils.createTransformStreamForWritableSide();
146
- const wrapper2 = utils.createTransformStreamForReadableSide("audio", () => this.timeZero);
147
- this.stream = node_stream_1.default.compose(wrapper1, this.stream, wrapper2);
148
- }
149
- else if (this.params.mode === "r") {
150
- /* input device */
151
- if (device.maxInputChannels === 0)
152
- throw new Error(`device "${device.id}" does not have any input channels (required by read mode)`);
153
- this.log("info", `resolved "${this.params.device}" to input device "${device.id}"`);
154
- this.io = naudiodon_1.default.AudioIO({
155
- inOptions: {
156
- deviceId: device.id,
157
- channelCount: this.config.audioChannels,
158
- sampleRate: this.config.audioSampleRate,
159
- sampleFormat: this.config.audioBitDepth
160
- }
161
- });
162
- this.stream = this.io;
163
- /* convert regular stream into object-mode stream */
164
- const wrapper = utils.createTransformStreamForReadableSide("audio", () => this.timeZero);
165
- this.stream.pipe(wrapper);
166
- this.stream = wrapper;
167
- }
168
- else if (this.params.mode === "w") {
169
- /* output device */
170
- if (device.maxOutputChannels === 0)
171
- throw new Error(`device "${device.id}" does not have any output channels (required by write mode)`);
172
- this.log("info", `resolved "${this.params.device}" to output device "${device.id}"`);
173
- this.io = naudiodon_1.default.AudioIO({
174
- outOptions: {
175
- deviceId: device.id,
176
- channelCount: this.config.audioChannels,
177
- sampleRate: this.config.audioSampleRate,
178
- sampleFormat: this.config.audioBitDepth
179
- }
180
- });
181
- this.stream = this.io;
182
- /* convert regular stream into object-mode stream */
183
- const wrapper = utils.createTransformStreamForWritableSide();
184
- wrapper.pipe(this.stream);
185
- this.stream = wrapper;
186
- }
187
- else
188
- throw new Error(`device "${device.id}" does not have any input or output channels`);
189
- /* pass-through PortAudio errors */
190
- this.io.on("error", (err) => {
191
- this.emit("error", err);
192
- });
193
- /* start PortAudio */
194
- this.io.start();
195
- }
196
- /* close node */
197
- async close() {
198
- /* shutdown PortAudio */
199
- if (this.io !== null) {
200
- this.io.quit();
201
- this.io = null;
202
- }
203
- }
204
- }
205
- exports.default = SpeechFlowNodeDevice;
@@ -1,13 +0,0 @@
1
- import SpeechFlowNode from "./speechflow-node";
2
- export default class SpeechFlowNodeElevenlabs extends SpeechFlowNode {
3
- static name: string;
4
- private elevenlabs;
5
- private static speexInitialized;
6
- constructor(id: string, cfg: {
7
- [id: string]: any;
8
- }, opts: {
9
- [id: string]: any;
10
- }, args: any[]);
11
- open(): Promise<void>;
12
- close(): Promise<void>;
13
- }