@buffered-audio/nodes 0.17.0 → 0.18.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.
- package/README.md +0 -12
- package/dist/cli.js +46 -42
- package/dist/index.d.ts +127 -184
- package/dist/index.js +1814 -1996
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -318,18 +318,6 @@ Invert or rotate signal phase
|
|
|
318
318
|
| `invert` | boolean | `true` | Invert |
|
|
319
319
|
| `angle` | number (-180 to 180, step 1), optional | — | Angle |
|
|
320
320
|
|
|
321
|
-
### Read
|
|
322
|
-
|
|
323
|
-
Read audio from a file
|
|
324
|
-
|
|
325
|
-
[Source](./src/sources/read/index.ts)
|
|
326
|
-
|
|
327
|
-
| Parameter | Type | Default | Description |
|
|
328
|
-
| --- | --- | --- | --- |
|
|
329
|
-
| `path` | string | `""` | |
|
|
330
|
-
| `ffmpegPath` | string | `""` | FFmpeg — audio/video processing tool Download: [ffmpeg](https://ffmpeg.org/download.html) |
|
|
331
|
-
| `ffprobePath` | string | `""` | FFprobe — media file analyzer (included with FFmpeg) Download: [ffprobe](https://ffmpeg.org/download.html) |
|
|
332
|
-
|
|
333
321
|
### Read FFmpeg
|
|
334
322
|
|
|
335
323
|
Read audio from a file using FFmpeg
|
package/dist/cli.js
CHANGED
|
@@ -2,9 +2,17 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { existsSync, readFileSync } from 'fs';
|
|
4
4
|
import { resolve } from 'path';
|
|
5
|
-
import { SourceNode, validateGraphDefinition,
|
|
5
|
+
import { SourceNode, validateGraphDefinition, createRenderJobs, BufferedSourceStream } from '@buffered-audio/core';
|
|
6
6
|
|
|
7
7
|
var labelOf = (node) => node.id ? `${node.nodeName}#${node.id}` : node.nodeName;
|
|
8
|
+
function sourceLabel(job) {
|
|
9
|
+
for (const [node, streams] of job.streams) {
|
|
10
|
+
if (streams.some((stream) => stream instanceof BufferedSourceStream)) {
|
|
11
|
+
return labelOf({ nodeName: node.constructor.nodeName, id: node.id });
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return void 0;
|
|
15
|
+
}
|
|
8
16
|
var collect = (value, previous) => [...previous, value];
|
|
9
17
|
function parseParams(entries) {
|
|
10
18
|
const parameters = /* @__PURE__ */ new Map();
|
|
@@ -33,39 +41,36 @@ function parseParams(entries) {
|
|
|
33
41
|
}
|
|
34
42
|
function createEventSink() {
|
|
35
43
|
const totals = /* @__PURE__ */ new Map();
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
case "started":
|
|
40
|
-
process.stdout.write(`[${label}] started
|
|
44
|
+
const subscribe = (events) => {
|
|
45
|
+
events.on("started", (node) => {
|
|
46
|
+
process.stdout.write(`[${labelOf(node)}] started
|
|
41
47
|
`);
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
});
|
|
49
|
+
events.on("progress", (node, payload) => {
|
|
50
|
+
const label = labelOf(node);
|
|
51
|
+
if (payload.framesTotal !== void 0) {
|
|
52
|
+
const percent = Math.round(payload.framesDone / payload.framesTotal * 100);
|
|
53
|
+
process.stdout.write(`[${label}] ${payload.phase} ${percent}%
|
|
47
54
|
`);
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
} else {
|
|
56
|
+
process.stdout.write(`[${label}] ${payload.phase} frames=${payload.framesDone}
|
|
50
57
|
`);
|
|
51
|
-
}
|
|
52
|
-
break;
|
|
53
|
-
case "log": {
|
|
54
|
-
const data = event.data ? Object.entries(event.data).map(([key, value]) => `${key}=${String(value)}`) : [];
|
|
55
|
-
const parts = [event.message, ...data].join(" ");
|
|
56
|
-
const prefix = event.level === "warn" ? "warn: " : "";
|
|
57
|
-
process.stdout.write(`${prefix}[${label}] ${parts}
|
|
58
|
-
`);
|
|
59
|
-
break;
|
|
60
58
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
59
|
+
});
|
|
60
|
+
events.on("log", (node, payload) => {
|
|
61
|
+
const data = payload.data ? Object.entries(payload.data).map(([key, value]) => `${key}=${String(value)}`) : [];
|
|
62
|
+
const parts = [payload.message, ...data].join(" ");
|
|
63
|
+
const prefix = payload.level === "warn" ? "warn: " : "";
|
|
64
|
+
process.stdout.write(`${prefix}[${labelOf(node)}] ${parts}
|
|
65
|
+
`);
|
|
66
|
+
});
|
|
67
|
+
events.on("finished", (node, payload) => {
|
|
68
|
+
totals.set(node, { framesDone: payload.framesDone, processingMs: payload.processingMs });
|
|
69
|
+
process.stdout.write(`[${labelOf(node)}] finished
|
|
70
|
+
`);
|
|
71
|
+
});
|
|
67
72
|
};
|
|
68
|
-
const printSummary = (
|
|
73
|
+
const printSummary = (jobs) => {
|
|
69
74
|
for (const [node, { framesDone, processingMs }] of totals) {
|
|
70
75
|
const label = labelOf(node);
|
|
71
76
|
if (processingMs !== void 0) {
|
|
@@ -76,15 +81,15 @@ function createEventSink() {
|
|
|
76
81
|
`);
|
|
77
82
|
}
|
|
78
83
|
}
|
|
79
|
-
for (const
|
|
80
|
-
const timing =
|
|
84
|
+
for (const job of jobs) {
|
|
85
|
+
const timing = job.timing;
|
|
81
86
|
if (!timing) continue;
|
|
82
|
-
const label =
|
|
87
|
+
const label = sourceLabel(job) ?? "source";
|
|
83
88
|
process.stdout.write(`[${label}] total ${(timing.totalMs / 1e3).toFixed(1)}s, ${timing.realTimeMultiplier.toFixed(1)}x RT
|
|
84
89
|
`);
|
|
85
90
|
}
|
|
86
91
|
};
|
|
87
|
-
return {
|
|
92
|
+
return { subscribe, printSummary };
|
|
88
93
|
}
|
|
89
94
|
var program = new Command();
|
|
90
95
|
program.name("buffered-audio-nodes").description("Process audio through buffered audio node pipelines");
|
|
@@ -117,15 +122,12 @@ program.command("process").description("Run an async audio processing pipeline")
|
|
|
117
122
|
process.exit(1);
|
|
118
123
|
}
|
|
119
124
|
const sink = createEventSink();
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
highWaterMark,
|
|
123
|
-
onEvent: sink.onEvent
|
|
124
|
-
};
|
|
125
|
+
const job = source.createRenderJob({ chunkSize, highWaterMark });
|
|
126
|
+
sink.subscribe(job.events);
|
|
125
127
|
process.stdout.write(`Processing pipeline: ${pipelinePath}
|
|
126
128
|
`);
|
|
127
|
-
await
|
|
128
|
-
sink.printSummary([
|
|
129
|
+
await job.render();
|
|
130
|
+
sink.printSummary([job]);
|
|
129
131
|
process.stdout.write("Done.\n");
|
|
130
132
|
} finally {
|
|
131
133
|
await unregister();
|
|
@@ -164,8 +166,10 @@ program.command("render").description("Render a .bag graph definition file").arg
|
|
|
164
166
|
process.stdout.write(`Rendering graph: ${definition.name}
|
|
165
167
|
`);
|
|
166
168
|
try {
|
|
167
|
-
const
|
|
168
|
-
sink.
|
|
169
|
+
const jobs = createRenderJobs(definition, registry, { chunkSize, highWaterMark, parameters });
|
|
170
|
+
for (const job of jobs) sink.subscribe(job.events);
|
|
171
|
+
await Promise.all(jobs.map((job) => job.render()));
|
|
172
|
+
sink.printSummary(jobs);
|
|
169
173
|
process.stdout.write("Done.\n");
|
|
170
174
|
} catch (error) {
|
|
171
175
|
process.stderr.write(`Error: ${error instanceof Error ? error.message : String(error)}
|