speechflow 1.4.3 → 1.4.5
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.
- package/CHANGELOG.md +15 -0
- package/README.md +53 -0
- package/etc/speechflow.png +0 -0
- package/etc/speechflow.yaml +25 -9
- package/package.json +3 -3
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js +153 -0
- package/speechflow-cli/dst/speechflow-node-a2a-ffmpeg.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gender.d.ts +20 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js +349 -0
- package/speechflow-cli/dst/speechflow-node-a2a-gender.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-meter.d.ts +15 -0
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js +210 -0
- package/speechflow-cli/dst/speechflow-node-a2a-meter.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-mute.d.ts +17 -0
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js +117 -0
- package/speechflow-cli/dst/speechflow-node-a2a-mute.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-vad.d.ts +19 -0
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js +374 -0
- package/speechflow-cli/dst/speechflow-node-a2a-vad.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2a-wav.d.ts +11 -0
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js +211 -0
- package/speechflow-cli/dst/speechflow-node-a2a-wav.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.d.ts +19 -0
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js +309 -0
- package/speechflow-cli/dst/speechflow-node-a2t-deepgram.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.d.ts +18 -0
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js +238 -0
- package/speechflow-cli/dst/speechflow-node-t2a-elevenlabs.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.d.ts +14 -0
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js +155 -0
- package/speechflow-cli/dst/speechflow-node-t2a-kokoro.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.d.ts +15 -0
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js +146 -0
- package/speechflow-cli/dst/speechflow-node-t2t-deepl.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-format.d.ts +11 -0
- package/speechflow-cli/dst/speechflow-node-t2t-format.js +82 -0
- package/speechflow-cli/dst/speechflow-node-t2t-format.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.js +247 -0
- package/speechflow-cli/dst/speechflow-node-t2t-ollama.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-openai.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-t2t-openai.js +227 -0
- package/speechflow-cli/dst/speechflow-node-t2t-openai.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.d.ts +17 -0
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js +250 -0
- package/speechflow-cli/dst/speechflow-node-t2t-sentence.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js +278 -0
- package/speechflow-cli/dst/speechflow-node-t2t-subtitle.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-t2t-transformers.d.ts +14 -0
- package/speechflow-cli/dst/speechflow-node-t2t-transformers.js +265 -0
- package/speechflow-cli/dst/speechflow-node-t2t-transformers.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-x2x-filter.d.ts +11 -0
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js +121 -0
- package/speechflow-cli/dst/speechflow-node-x2x-filter.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-x2x-trace.d.ts +11 -0
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js +111 -0
- package/speechflow-cli/dst/speechflow-node-x2x-trace.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-device.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-xio-device.js +230 -0
- package/speechflow-cli/dst/speechflow-node-xio-device.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-file.d.ts +11 -0
- package/speechflow-cli/dst/speechflow-node-xio-file.js +216 -0
- package/speechflow-cli/dst/speechflow-node-xio-file.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js +188 -0
- package/speechflow-cli/dst/speechflow-node-xio-mqtt.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node-xio-websocket.d.ts +13 -0
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js +278 -0
- package/speechflow-cli/dst/speechflow-node-xio-websocket.js.map +1 -0
- package/speechflow-cli/dst/speechflow-node.d.ts +65 -0
- package/speechflow-cli/dst/speechflow-node.js +180 -0
- package/speechflow-cli/dst/speechflow-node.js.map +1 -0
- package/speechflow-cli/dst/speechflow-utils.d.ts +74 -0
- package/speechflow-cli/dst/speechflow-utils.js +519 -0
- package/speechflow-cli/dst/speechflow-utils.js.map +1 -0
- package/speechflow-cli/dst/speechflow.d.ts +7 -0
- package/speechflow-cli/dst/speechflow.js +869 -0
- package/speechflow-cli/dst/speechflow.js.map +1 -0
- package/speechflow-cli/package.json +1 -1
- package/speechflow-cli/src/speechflow-node-a2a-meter.ts +29 -52
- package/speechflow-cli/src/speechflow-node-a2t-deepgram.ts +1 -20
- package/speechflow-cli/src/speechflow.ts +44 -13
- package/speechflow-ui-db/dst/app-font-TypoPRO-SourceSansPro-Bold.eot +0 -0
- package/speechflow-ui-db/dst/app-font-TypoPRO-SourceSansPro-Bold.ttf +0 -0
- package/speechflow-ui-db/dst/app-font-TypoPRO-SourceSansPro-Bold.woff +0 -0
- package/speechflow-ui-db/dst/app-font-TypoPRO-SourceSansPro-Regular.eot +0 -0
- package/speechflow-ui-db/dst/app-font-TypoPRO-SourceSansPro-Regular.ttf +0 -0
- package/speechflow-ui-db/dst/app-font-TypoPRO-SourceSansPro-Regular.woff +0 -0
- package/speechflow-ui-db/dst/app-font-fa-brands-400.woff2 +0 -0
- package/speechflow-ui-db/dst/app-font-fa-regular-400.woff2 +0 -0
- package/speechflow-ui-db/dst/app-font-fa-solid-900.woff2 +0 -0
- package/speechflow-ui-db/dst/app-font-fa-v4compatibility.woff2 +0 -0
- package/speechflow-ui-db/dst/app-icon.svg +26 -0
- package/speechflow-ui-db/dst/index.css +5 -0
- package/speechflow-ui-db/dst/index.html +24 -0
- package/speechflow-ui-db/dst/index.js +616 -0
- package/speechflow-ui-db/src/app.vue +77 -73
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Bold.eot +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Bold.ttf +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Bold.woff +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Regular.eot +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Regular.ttf +0 -0
- package/speechflow-ui-st/dst/app-font-TypoPRO-SourceSansPro-Regular.woff +0 -0
- package/speechflow-ui-st/dst/app-font-fa-brands-400.woff2 +0 -0
- package/speechflow-ui-st/dst/app-font-fa-regular-400.woff2 +0 -0
- package/speechflow-ui-st/dst/app-font-fa-solid-900.woff2 +0 -0
- package/speechflow-ui-st/dst/app-font-fa-v4compatibility.woff2 +0 -0
- package/speechflow-ui-st/dst/app-icon.svg +26 -0
- package/speechflow-ui-st/dst/index.css +5 -0
- package/speechflow-ui-st/dst/index.html +24 -0
- package/speechflow-ui-st/dst/index.js +610 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
ChangeLog
|
|
3
3
|
=========
|
|
4
4
|
|
|
5
|
+
1.4.5 (2025-08-07)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
- IMPROVEMENT: better CLI option handling
|
|
9
|
+
- IMPROVEMENT: better optical appearance of dashboard
|
|
10
|
+
- BUGFIX: do not complain if no .env file is found
|
|
11
|
+
- BUGFIX: avoid read-timeouts in "deepgram" node
|
|
12
|
+
- CLEANUP: output stack traces only for "info" and "debug" verbosity levels
|
|
13
|
+
|
|
14
|
+
1.4.4 (2025-08-07)
|
|
15
|
+
------------------
|
|
16
|
+
|
|
17
|
+
- BUGFIX: do not ignore "dst" files in NPM distribution
|
|
18
|
+
- UPGRADE: upgrade NPM dependencies
|
|
19
|
+
|
|
5
20
|
1.4.3 (2025-08-06)
|
|
6
21
|
------------------
|
|
7
22
|
|
package/README.md
CHANGED
|
@@ -53,6 +53,59 @@ derived from the exported `SpeechFlowNode` class of the `speechflow` package.
|
|
|
53
53
|
**SpeechFlow** is written in TypeScript and
|
|
54
54
|
ships as an installable package for the Node Package Manager (NPM).
|
|
55
55
|
|
|
56
|
+
Impression
|
|
57
|
+
----------
|
|
58
|
+
|
|
59
|
+
**SpeechFlow** is a command-line interface (CLI) based tool, so there
|
|
60
|
+
is no exciting screenshot possible from its CLI appearance, of course.
|
|
61
|
+
Instead, here is a sample of a fictive training which is held in German
|
|
62
|
+
and real-time translated to English.
|
|
63
|
+
|
|
64
|
+
First, the used configuration was a straight linear pipeline in file `sample.conf`:
|
|
65
|
+
|
|
66
|
+
```txt
|
|
67
|
+
device(device: "coreaudio:Elgato Wave:3", mode: "r") |
|
|
68
|
+
meter(interval: 50, dashboard: "meter1") |
|
|
69
|
+
deepgram(language: "de", model: "nova-2", interim: true) |
|
|
70
|
+
trace(type: "text", dashboard: "text1") |
|
|
71
|
+
filter(name: "final", type: "text", var: "kind", op: "==", val: "final") |
|
|
72
|
+
sentence() |
|
|
73
|
+
trace(type: "text", dashboard: "text2") |
|
|
74
|
+
deepl(src: "de", dst: "en") |
|
|
75
|
+
trace(type: "text", dashboard: "text3") |
|
|
76
|
+
elevenlabs(voice: "Mark", optimize: "latency", speed: 1.05, language: "en") |
|
|
77
|
+
meter(interval: 50, dashboard: "meter2") |
|
|
78
|
+
device(device: "coreaudio:USBAudio2.0", mode: "w")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Second, the corresponding **SpeechFlow** command was:
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
$ speechflow -v info -c sample.conf \
|
|
85
|
+
-d audio:meter1:DE,text:text1:DE-Interim,text:text2:DE-Final,text:text3:EN,audio:meter2:EN
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Finally, the resulting dashboard under URL `http://127.0.0.1:8484/` was:
|
|
89
|
+
|
|
90
|
+

|
|
91
|
+
|
|
92
|
+
On the left you can see the volume meter of the microphone (`device`),
|
|
93
|
+
followed by the German result of the speech-to-text conversion
|
|
94
|
+
(`deepgram`), followed by the still German results of the text-to-text
|
|
95
|
+
sentence splitting/aggregation (`sentence`), followed by the English
|
|
96
|
+
results of the text-to-text translation (`deepl`) and then finally on
|
|
97
|
+
the right you can see the volume meter of the text-to-speech conversion
|
|
98
|
+
(`elevenlabs`).
|
|
99
|
+
|
|
100
|
+
The entire **SpeechFlow** processing pipeline runs in real-time and
|
|
101
|
+
the latency between input and output audio is about 2-3 seconds, very
|
|
102
|
+
similar to the usual latency human live translators also cause. The
|
|
103
|
+
latency primarily comes from the speech-to-text part in the pipeline,
|
|
104
|
+
as the end of sentences have to be awaited -- especially in the German
|
|
105
|
+
language where the verb can come very late in a sentence. So, the
|
|
106
|
+
latency is primarily not caused by any technical aspects, but by the
|
|
107
|
+
nature of live translation.
|
|
108
|
+
|
|
56
109
|
Installation
|
|
57
110
|
------------
|
|
58
111
|
|
|
Binary file
|
package/etc/speechflow.yaml
CHANGED
|
@@ -79,31 +79,30 @@ studio-transcription: |
|
|
|
79
79
|
studio-translation: |
|
|
80
80
|
device(device: "coreaudio:Elgato Wave:3", mode: "r") | {
|
|
81
81
|
gender() | {
|
|
82
|
-
meter(interval: 250) |
|
|
82
|
+
meter(interval: 250, dashboard: "meter1") |
|
|
83
83
|
wav(mode: "encode") |
|
|
84
84
|
file(path: "program-de.wav", mode: "w", type: "audio"),
|
|
85
|
-
deepgram(language: "de", key: env.SPEECHFLOW_DEEPGRAM_KEY) | {
|
|
85
|
+
deepgram(language: "de", key: env.SPEECHFLOW_DEEPGRAM_KEY, interim: true) | {
|
|
86
|
+
trace(name: "trace1", type: "text", dashboard: "text1")
|
|
86
87
|
subtitle(format: "vtt", words: true) |
|
|
87
88
|
file(path: "program-de.vtt", mode: "w", type: "text"),
|
|
88
89
|
sentence() | {
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
trace(name: "trace2", type: "text", notify: true, dashboard: "text2") |
|
|
91
|
+
format(width: 80) |
|
|
92
|
+
file(path: "program-de.txt", mode: "w", type: "text"),
|
|
91
93
|
deepl(src: "de", dst: "en", key: env.SPEECHFLOW_DEEPL_KEY) | {
|
|
92
|
-
trace(name: "
|
|
94
|
+
trace(name: "trace3", type: "text", dashboard: "text3") | {
|
|
93
95
|
format(width: 80) |
|
|
94
96
|
file(path: "program-en.txt", mode: "w", type: "text"),
|
|
95
97
|
subtitle(format: "vtt", words: false) |
|
|
96
98
|
file(path: "program-en.vtt", mode: "w", type: "text"),
|
|
97
|
-
mqtt(url: "mqtt://10.1.0.10:1883",
|
|
98
|
-
username: env.SPEECHFLOW_MQTT_USER,
|
|
99
|
-
password: env.SPEECHFLOW_MQTT_PASS,
|
|
100
|
-
topicWrite: "stream/studio/sender"),
|
|
101
99
|
{
|
|
102
100
|
filter(name: "S2T-male", type: "text", var: "meta:gender", op: "==", val: "male") |
|
|
103
101
|
elevenlabs(voice: "Mark", optimize: "latency", speed: 1.05, language: "en"),
|
|
104
102
|
filter(name: "S2T-female", type: "text", var: "meta:gender", op: "==", val: "female") |
|
|
105
103
|
elevenlabs(voice: "Brittney", optimize: "latency", speed: 1.05, language: "en")
|
|
106
104
|
} | {
|
|
105
|
+
meter(interval: 250, dashboard: "meter2", dashboard: "meter2"),
|
|
107
106
|
wav(mode: "encode") |
|
|
108
107
|
file(path: "program-en.wav", mode: "w", type: "audio"),
|
|
109
108
|
device(device: "coreaudio:USBAudio2.0", mode: "w")
|
|
@@ -115,3 +114,20 @@ studio-translation: |
|
|
|
115
114
|
}
|
|
116
115
|
}
|
|
117
116
|
|
|
117
|
+
# Test-drive for development
|
|
118
|
+
test: |
|
|
119
|
+
device(device: "coreaudio:Elgato Wave:3", mode: "r") |
|
|
120
|
+
meter(interval: 50, dashboard: "meter1") |
|
|
121
|
+
deepgram(language: "de", model: "nova-2", key: env.SPEECHFLOW_DEEPGRAM_KEY, interim: true) |
|
|
122
|
+
trace(type: "text", dashboard: "text1") | {
|
|
123
|
+
subtitle(mode: "render", addr: "127.0.0.1", port: 8585),
|
|
124
|
+
filter(name: "final", type: "text", var: "kind", op: "==", val: "final") |
|
|
125
|
+
sentence() |
|
|
126
|
+
trace(type: "text", dashboard: "text2") |
|
|
127
|
+
deepl(src: "de", dst: "en", key: env.SPEECHFLOW_DEEPL_KEY) |
|
|
128
|
+
trace(type: "text", dashboard: "text3") |
|
|
129
|
+
elevenlabs(voice: "Mark", optimize: "latency", speed: 1.05, language: "en") |
|
|
130
|
+
meter(interval: 50, dashboard: "meter2") |
|
|
131
|
+
device(device: "coreaudio:USBAudio2.0", mode: "w")
|
|
132
|
+
}
|
|
133
|
+
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "speechflow",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"x-stdver": "1.4.
|
|
5
|
-
"x-release": "2025-08-
|
|
3
|
+
"version": "1.4.5",
|
|
4
|
+
"x-stdver": "1.4.5-GA",
|
|
5
|
+
"x-release": "2025-08-07",
|
|
6
6
|
"homepage": "https://github.com/rse/speechflow",
|
|
7
7
|
"description": "Speech Processing Flow Graph",
|
|
8
8
|
"license": "GPL-3.0-only",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import SpeechFlowNode from "./speechflow-node";
|
|
2
|
+
export default class SpeechFlowNodeFFmpeg extends SpeechFlowNode {
|
|
3
|
+
static name: string;
|
|
4
|
+
private ffmpegBinary;
|
|
5
|
+
private ffmpeg;
|
|
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
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
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 ffmpeg_1 = __importDefault(require("@rse/ffmpeg"));
|
|
48
|
+
const ffmpeg_stream_1 = require("ffmpeg-stream");
|
|
49
|
+
/* internal dependencies */
|
|
50
|
+
const speechflow_node_1 = __importDefault(require("./speechflow-node"));
|
|
51
|
+
const utils = __importStar(require("./speechflow-utils"));
|
|
52
|
+
/* SpeechFlow node for FFmpeg */
|
|
53
|
+
class SpeechFlowNodeFFmpeg extends speechflow_node_1.default {
|
|
54
|
+
/* declare official node name */
|
|
55
|
+
static name = "ffmpeg";
|
|
56
|
+
/* internal state */
|
|
57
|
+
ffmpegBinary = ffmpeg_1.default.supported ? ffmpeg_1.default.binary : "ffmpeg";
|
|
58
|
+
ffmpeg = null;
|
|
59
|
+
/* construct node */
|
|
60
|
+
constructor(id, cfg, opts, args) {
|
|
61
|
+
super(id, cfg, opts, args);
|
|
62
|
+
/* declare node configuration parameters */
|
|
63
|
+
this.configure({
|
|
64
|
+
src: { type: "string", pos: 0, val: "pcm", match: /^(?:pcm|wav|mp3|opus)$/ },
|
|
65
|
+
dst: { type: "string", pos: 1, val: "wav", match: /^(?:pcm|wav|mp3|opus)$/ }
|
|
66
|
+
});
|
|
67
|
+
/* declare node input/output format */
|
|
68
|
+
this.input = "audio";
|
|
69
|
+
this.output = "audio";
|
|
70
|
+
}
|
|
71
|
+
/* open node */
|
|
72
|
+
async open() {
|
|
73
|
+
/* sanity check situation */
|
|
74
|
+
if (this.params.src === this.params.dst)
|
|
75
|
+
throw new Error("source and destination formats should not be the same");
|
|
76
|
+
/* instantiate FFmpeg sub-process */
|
|
77
|
+
this.ffmpeg = new ffmpeg_stream_1.Converter(this.ffmpegBinary);
|
|
78
|
+
const streamInput = this.ffmpeg.createInputStream({
|
|
79
|
+
/* FFmpeg input options */
|
|
80
|
+
"fflags": "nobuffer",
|
|
81
|
+
"flags": "low_delay",
|
|
82
|
+
"probesize": 32,
|
|
83
|
+
"analyzeduration": 0,
|
|
84
|
+
...(this.params.src === "pcm" ? {
|
|
85
|
+
"f": "s16le",
|
|
86
|
+
"ar": this.config.audioSampleRate,
|
|
87
|
+
"ac": this.config.audioChannels
|
|
88
|
+
} : {}),
|
|
89
|
+
...(this.params.src === "wav" ? {
|
|
90
|
+
"f": "wav"
|
|
91
|
+
} : {}),
|
|
92
|
+
...(this.params.src === "mp3" ? {
|
|
93
|
+
"f": "mp3"
|
|
94
|
+
} : {}),
|
|
95
|
+
...(this.params.src === "opus" ? {
|
|
96
|
+
"f": "opus"
|
|
97
|
+
} : {})
|
|
98
|
+
});
|
|
99
|
+
const streamOutput = this.ffmpeg.createOutputStream({
|
|
100
|
+
/* FFmpeg output options */
|
|
101
|
+
"flush_packets": 1,
|
|
102
|
+
...(this.params.dst === "pcm" ? {
|
|
103
|
+
"c:a": "pcm_s16le",
|
|
104
|
+
"ar": this.config.audioSampleRate,
|
|
105
|
+
"ac": this.config.audioChannels,
|
|
106
|
+
"f": "s16le",
|
|
107
|
+
} : {}),
|
|
108
|
+
...(this.params.dst === "wav" ? {
|
|
109
|
+
"f": "wav"
|
|
110
|
+
} : {}),
|
|
111
|
+
...(this.params.dst === "mp3" ? {
|
|
112
|
+
"c:a": "libmp3lame",
|
|
113
|
+
"b:a": "192k",
|
|
114
|
+
"f": "mp3"
|
|
115
|
+
} : {}),
|
|
116
|
+
...(this.params.dst === "opus" ? {
|
|
117
|
+
"acodec": "libopus",
|
|
118
|
+
"f": "opus"
|
|
119
|
+
} : {})
|
|
120
|
+
});
|
|
121
|
+
this.ffmpeg.run();
|
|
122
|
+
/* establish a duplex stream and connect it to FFmpeg */
|
|
123
|
+
this.stream = node_stream_1.default.Duplex.from({
|
|
124
|
+
writable: streamInput,
|
|
125
|
+
readable: streamOutput
|
|
126
|
+
});
|
|
127
|
+
/* wrap streams with conversions for chunk vs plain audio */
|
|
128
|
+
const wrapper1 = utils.createTransformStreamForWritableSide();
|
|
129
|
+
const wrapper2 = utils.createTransformStreamForReadableSide("audio", () => this.timeZero);
|
|
130
|
+
this.stream = node_stream_1.default.compose(wrapper1, this.stream, wrapper2);
|
|
131
|
+
}
|
|
132
|
+
/* close node */
|
|
133
|
+
async close() {
|
|
134
|
+
/* close duplex stream */
|
|
135
|
+
if (this.stream !== null) {
|
|
136
|
+
await new Promise((resolve) => {
|
|
137
|
+
if (this.stream instanceof node_stream_1.default.Duplex)
|
|
138
|
+
this.stream.end(() => { resolve(); });
|
|
139
|
+
else
|
|
140
|
+
resolve();
|
|
141
|
+
});
|
|
142
|
+
this.stream.destroy();
|
|
143
|
+
this.stream = null;
|
|
144
|
+
}
|
|
145
|
+
/* shutdown FFmpeg */
|
|
146
|
+
if (this.ffmpeg !== null) {
|
|
147
|
+
this.ffmpeg.kill();
|
|
148
|
+
this.ffmpeg = null;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.default = SpeechFlowNodeFFmpeg;
|
|
153
|
+
//# sourceMappingURL=speechflow-node-a2a-ffmpeg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"speechflow-node-a2a-ffmpeg.js","sourceRoot":"","sources":["../src/speechflow-node-a2a-ffmpeg.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import SpeechFlowNode from "./speechflow-node";
|
|
2
|
+
export default class SpeechFlowNodeGender extends SpeechFlowNode {
|
|
3
|
+
static name: string;
|
|
4
|
+
private static speexInitialized;
|
|
5
|
+
private classifier;
|
|
6
|
+
private queue;
|
|
7
|
+
private queueRecv;
|
|
8
|
+
private queueAC;
|
|
9
|
+
private queueSend;
|
|
10
|
+
private shutdown;
|
|
11
|
+
private workingOffTimer;
|
|
12
|
+
private progressInterval;
|
|
13
|
+
constructor(id: string, cfg: {
|
|
14
|
+
[id: string]: any;
|
|
15
|
+
}, opts: {
|
|
16
|
+
[id: string]: any;
|
|
17
|
+
}, args: any[]);
|
|
18
|
+
open(): Promise<void>;
|
|
19
|
+
close(): Promise<void>;
|
|
20
|
+
}
|