@nodetool-ai/video-nodes 0.8.1
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 +58 -0
- package/dist/.nodetool-build-stamp +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/nodes/ffmpeg-helpers.d.ts +77 -0
- package/dist/nodes/ffmpeg-helpers.d.ts.map +1 -0
- package/dist/nodes/ffmpeg-helpers.js +220 -0
- package/dist/nodes/ffmpeg-helpers.js.map +1 -0
- package/dist/nodes/lib-video-download.d.ts +29 -0
- package/dist/nodes/lib-video-download.d.ts.map +1 -0
- package/dist/nodes/lib-video-download.js +353 -0
- package/dist/nodes/lib-video-download.js.map +1 -0
- package/dist/nodes/model3d/analysis.d.ts +16 -0
- package/dist/nodes/model3d/analysis.d.ts.map +1 -0
- package/dist/nodes/model3d/analysis.js +38 -0
- package/dist/nodes/model3d/analysis.js.map +1 -0
- package/dist/nodes/model3d/base.d.ts +28 -0
- package/dist/nodes/model3d/base.d.ts.map +1 -0
- package/dist/nodes/model3d/base.js +20 -0
- package/dist/nodes/model3d/base.js.map +1 -0
- package/dist/nodes/model3d/boolean-ops.d.ts +2 -0
- package/dist/nodes/model3d/boolean-ops.d.ts.map +1 -0
- package/dist/nodes/model3d/boolean-ops.js +172 -0
- package/dist/nodes/model3d/boolean-ops.js.map +1 -0
- package/dist/nodes/model3d/cleanup.d.ts +56 -0
- package/dist/nodes/model3d/cleanup.d.ts.map +1 -0
- package/dist/nodes/model3d/cleanup.js +144 -0
- package/dist/nodes/model3d/cleanup.js.map +1 -0
- package/dist/nodes/model3d/convert.d.ts +27 -0
- package/dist/nodes/model3d/convert.d.ts.map +1 -0
- package/dist/nodes/model3d/convert.js +66 -0
- package/dist/nodes/model3d/convert.js.map +1 -0
- package/dist/nodes/model3d/defaults.d.ts +34 -0
- package/dist/nodes/model3d/defaults.d.ts.map +1 -0
- package/dist/nodes/model3d/defaults.js +28 -0
- package/dist/nodes/model3d/defaults.js.map +1 -0
- package/dist/nodes/model3d/document-ops.d.ts +4 -0
- package/dist/nodes/model3d/document-ops.d.ts.map +1 -0
- package/dist/nodes/model3d/document-ops.js +40 -0
- package/dist/nodes/model3d/document-ops.js.map +1 -0
- package/dist/nodes/model3d/generation.d.ts +56 -0
- package/dist/nodes/model3d/generation.d.ts.map +1 -0
- package/dist/nodes/model3d/generation.js +203 -0
- package/dist/nodes/model3d/generation.js.map +1 -0
- package/dist/nodes/model3d/glb.d.ts +29 -0
- package/dist/nodes/model3d/glb.d.ts.map +1 -0
- package/dist/nodes/model3d/glb.js +255 -0
- package/dist/nodes/model3d/glb.js.map +1 -0
- package/dist/nodes/model3d/index.d.ts +22 -0
- package/dist/nodes/model3d/index.d.ts.map +1 -0
- package/dist/nodes/model3d/index.js +41 -0
- package/dist/nodes/model3d/index.js.map +1 -0
- package/dist/nodes/model3d/io.d.ts +81 -0
- package/dist/nodes/model3d/io.d.ts.map +1 -0
- package/dist/nodes/model3d/io.js +162 -0
- package/dist/nodes/model3d/io.js.map +1 -0
- package/dist/nodes/model3d/mesh-ops.d.ts +40 -0
- package/dist/nodes/model3d/mesh-ops.d.ts.map +1 -0
- package/dist/nodes/model3d/mesh-ops.js +775 -0
- package/dist/nodes/model3d/mesh-ops.js.map +1 -0
- package/dist/nodes/model3d/nodes.d.ts +2 -0
- package/dist/nodes/model3d/nodes.d.ts.map +1 -0
- package/dist/nodes/model3d/nodes.js +2 -0
- package/dist/nodes/model3d/nodes.js.map +1 -0
- package/dist/nodes/model3d/ops.d.ts +44 -0
- package/dist/nodes/model3d/ops.d.ts.map +1 -0
- package/dist/nodes/model3d/ops.js +142 -0
- package/dist/nodes/model3d/ops.js.map +1 -0
- package/dist/nodes/model3d/render.d.ts +51 -0
- package/dist/nodes/model3d/render.d.ts.map +1 -0
- package/dist/nodes/model3d/render.js +124 -0
- package/dist/nodes/model3d/render.js.map +1 -0
- package/dist/nodes/model3d/render3d-core.d.ts +177 -0
- package/dist/nodes/model3d/render3d-core.d.ts.map +1 -0
- package/dist/nodes/model3d/render3d-core.js +366 -0
- package/dist/nodes/model3d/render3d-core.js.map +1 -0
- package/dist/nodes/model3d/render3d-headless.d.ts +75 -0
- package/dist/nodes/model3d/render3d-headless.d.ts.map +1 -0
- package/dist/nodes/model3d/render3d-headless.js +190 -0
- package/dist/nodes/model3d/render3d-headless.js.map +1 -0
- package/dist/nodes/model3d/render3d-page.d.ts +16 -0
- package/dist/nodes/model3d/render3d-page.d.ts.map +1 -0
- package/dist/nodes/model3d/render3d-page.js +51 -0
- package/dist/nodes/model3d/render3d-page.js.map +1 -0
- package/dist/nodes/model3d/transforms.d.ts +56 -0
- package/dist/nodes/model3d/transforms.d.ts.map +1 -0
- package/dist/nodes/model3d/transforms.js +148 -0
- package/dist/nodes/model3d/transforms.js.map +1 -0
- package/dist/nodes/model3d/types.d.ts +82 -0
- package/dist/nodes/model3d/types.d.ts.map +1 -0
- package/dist/nodes/model3d/types.js +2 -0
- package/dist/nodes/model3d/types.js.map +1 -0
- package/dist/nodes/model3d/utils.d.ts +46 -0
- package/dist/nodes/model3d/utils.d.ts.map +1 -0
- package/dist/nodes/model3d/utils.js +190 -0
- package/dist/nodes/model3d/utils.js.map +1 -0
- package/dist/nodes/model3d.d.ts +2 -0
- package/dist/nodes/model3d.d.ts.map +1 -0
- package/dist/nodes/model3d.js +2 -0
- package/dist/nodes/model3d.js.map +1 -0
- package/dist/nodes/placeholder-values.d.ts +10 -0
- package/dist/nodes/placeholder-values.d.ts.map +1 -0
- package/dist/nodes/placeholder-values.js +19 -0
- package/dist/nodes/placeholder-values.js.map +1 -0
- package/dist/nodes/script.d.ts +161 -0
- package/dist/nodes/script.d.ts.map +1 -0
- package/dist/nodes/script.js +673 -0
- package/dist/nodes/script.js.map +1 -0
- package/dist/nodes/storyboard.d.ts +269 -0
- package/dist/nodes/storyboard.d.ts.map +1 -0
- package/dist/nodes/storyboard.js +1017 -0
- package/dist/nodes/storyboard.js.map +1 -0
- package/dist/nodes/timeline/assetFiles.d.ts +19 -0
- package/dist/nodes/timeline/assetFiles.d.ts.map +1 -0
- package/dist/nodes/timeline/assetFiles.js +52 -0
- package/dist/nodes/timeline/assetFiles.js.map +1 -0
- package/dist/nodes/timeline/compositeRender.d.ts +60 -0
- package/dist/nodes/timeline/compositeRender.d.ts.map +1 -0
- package/dist/nodes/timeline/compositeRender.js +508 -0
- package/dist/nodes/timeline/compositeRender.js.map +1 -0
- package/dist/nodes/timeline/contactSheet.d.ts +43 -0
- package/dist/nodes/timeline/contactSheet.d.ts.map +1 -0
- package/dist/nodes/timeline/contactSheet.js +78 -0
- package/dist/nodes/timeline/contactSheet.js.map +1 -0
- package/dist/nodes/timeline/outputFormats.d.ts +69 -0
- package/dist/nodes/timeline/outputFormats.d.ts.map +1 -0
- package/dist/nodes/timeline/outputFormats.js +173 -0
- package/dist/nodes/timeline/outputFormats.js.map +1 -0
- package/dist/nodes/timeline/pngSequence.d.ts +44 -0
- package/dist/nodes/timeline/pngSequence.d.ts.map +1 -0
- package/dist/nodes/timeline/pngSequence.js +172 -0
- package/dist/nodes/timeline/pngSequence.js.map +1 -0
- package/dist/nodes/timeline/rasterizers.d.ts +47 -0
- package/dist/nodes/timeline/rasterizers.d.ts.map +1 -0
- package/dist/nodes/timeline/rasterizers.js +103 -0
- package/dist/nodes/timeline/rasterizers.js.map +1 -0
- package/dist/nodes/timeline/rawFrames.d.ts +149 -0
- package/dist/nodes/timeline/rawFrames.d.ts.map +1 -0
- package/dist/nodes/timeline/rawFrames.js +598 -0
- package/dist/nodes/timeline/rawFrames.js.map +1 -0
- package/dist/nodes/timeline.d.ts +206 -0
- package/dist/nodes/timeline.d.ts.map +1 -0
- package/dist/nodes/timeline.js +1395 -0
- package/dist/nodes/timeline.js.map +1 -0
- package/dist/nodes/video.d.ts +705 -0
- package/dist/nodes/video.d.ts.map +1 -0
- package/dist/nodes/video.js +2672 -0
- package/dist/nodes/video.js.map +1 -0
- package/dist/render3d-page.js +4118 -0
- package/package.json +95 -0
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw RGBA plumbing between ffmpeg and the timeline compositor.
|
|
3
|
+
*
|
|
4
|
+
* The compositor wants CPU-side straight-alpha RGBA for every layer of every
|
|
5
|
+
* frame, and hands back the composited frame in the same form. ffmpeg does the
|
|
6
|
+
* decoding and encoding on both ends:
|
|
7
|
+
*
|
|
8
|
+
* - {@link decodeImageRgba} decodes a still once.
|
|
9
|
+
* - {@link openVideoFrameStream} decodes a clip lazily, one frame at a time.
|
|
10
|
+
* Frames are consumed in timeline order, which for a clip is source order, so
|
|
11
|
+
* a single streaming decode covers the whole render — no seeking, and no
|
|
12
|
+
* multi-gigabyte scratch file.
|
|
13
|
+
* - {@link openFrameEncoder} pipes composited frames into one long-running
|
|
14
|
+
* encoder.
|
|
15
|
+
*/
|
|
16
|
+
import { spawn } from "node:child_process";
|
|
17
|
+
import { MissingBinaryError, execFfmpeg, execFfprobe } from "../ffmpeg-helpers.js";
|
|
18
|
+
/**
|
|
19
|
+
* Largest size that fits `source` inside `canvas` without upscaling and
|
|
20
|
+
* without changing its aspect ratio. Decoding beyond the frame the layer is
|
|
21
|
+
* composited into buys nothing; upscaling below it would change what a
|
|
22
|
+
* source-pixel unit (a blur radius, a corner radius) means.
|
|
23
|
+
*/
|
|
24
|
+
export function fitWithin(source, canvas) {
|
|
25
|
+
const scale = Math.min(1, canvas.width / Math.max(1, source.width), canvas.height / Math.max(1, source.height));
|
|
26
|
+
return {
|
|
27
|
+
width: Math.max(1, Math.round(source.width * scale)),
|
|
28
|
+
height: Math.max(1, Math.round(source.height * scale))
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Probe a media file's video dimensions, or `null` when it has no video. */
|
|
32
|
+
export async function probeVideoSize(filePath) {
|
|
33
|
+
const { stdout } = await execFfprobe([
|
|
34
|
+
"-v",
|
|
35
|
+
"error",
|
|
36
|
+
"-select_streams",
|
|
37
|
+
"v:0",
|
|
38
|
+
"-show_entries",
|
|
39
|
+
"stream=width,height",
|
|
40
|
+
"-of",
|
|
41
|
+
"csv=p=0:s=x",
|
|
42
|
+
filePath
|
|
43
|
+
]);
|
|
44
|
+
const match = /^(\d+)x(\d+)/.exec(stdout.trim());
|
|
45
|
+
if (!match)
|
|
46
|
+
return null;
|
|
47
|
+
return { width: Number(match[1]), height: Number(match[2]) };
|
|
48
|
+
}
|
|
49
|
+
function spawnFfmpeg(args) {
|
|
50
|
+
return spawn("ffmpeg", args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
51
|
+
}
|
|
52
|
+
/** Collect a process's stderr so a failure can say what ffmpeg complained about. */
|
|
53
|
+
function captureStderr(stream) {
|
|
54
|
+
const chunks = [];
|
|
55
|
+
stream.on("data", (chunk) => {
|
|
56
|
+
// Keep the tail only: a failing decode can be verbose, and the last lines
|
|
57
|
+
// are the ones that name the cause.
|
|
58
|
+
chunks.push(chunk);
|
|
59
|
+
if (chunks.length > 32)
|
|
60
|
+
chunks.shift();
|
|
61
|
+
});
|
|
62
|
+
return () => Buffer.concat(chunks).toString("utf8").trim();
|
|
63
|
+
}
|
|
64
|
+
/** Decode a still image to straight-alpha RGBA at `size`. */
|
|
65
|
+
export async function decodeImageRgba(filePath, size) {
|
|
66
|
+
const child = spawnFfmpeg([
|
|
67
|
+
"-v",
|
|
68
|
+
"error",
|
|
69
|
+
"-i",
|
|
70
|
+
filePath,
|
|
71
|
+
"-vf",
|
|
72
|
+
`scale=${size.width}:${size.height}`,
|
|
73
|
+
"-frames:v",
|
|
74
|
+
"1",
|
|
75
|
+
"-f",
|
|
76
|
+
"rawvideo",
|
|
77
|
+
"-pix_fmt",
|
|
78
|
+
"rgba",
|
|
79
|
+
"pipe:1"
|
|
80
|
+
]);
|
|
81
|
+
const stderr = captureStderr(child.stderr);
|
|
82
|
+
const chunks = [];
|
|
83
|
+
child.stdout.on("data", (chunk) => chunks.push(chunk));
|
|
84
|
+
await new Promise((resolve, reject) => {
|
|
85
|
+
child.on("error", (error) => reject(error.code === "ENOENT" ? new MissingBinaryError("ffmpeg") : error));
|
|
86
|
+
child.on("close", (code) => code === 0
|
|
87
|
+
? resolve()
|
|
88
|
+
: reject(new Error(`ffmpeg failed to decode image: ${stderr()}`)));
|
|
89
|
+
});
|
|
90
|
+
const rgba = new Uint8Array(Buffer.concat(chunks));
|
|
91
|
+
const expected = size.width * size.height * 4;
|
|
92
|
+
if (rgba.length < expected) {
|
|
93
|
+
throw new Error(`ffmpeg produced ${rgba.length} bytes for a ${size.width}x${size.height} frame (expected ${expected})`);
|
|
94
|
+
}
|
|
95
|
+
return { rgba: rgba.subarray(0, expected), ...size };
|
|
96
|
+
}
|
|
97
|
+
/** How many decoded frames ffmpeg may run ahead of the consumer. */
|
|
98
|
+
const READAHEAD_FRAMES = 4;
|
|
99
|
+
/**
|
|
100
|
+
* Start decoding `filePath` into RGBA frames at the timeline's frame rate.
|
|
101
|
+
* `setpts` applies the clip's speed so decoded frame *k* is exactly the source
|
|
102
|
+
* frame the preview shows at timeline frame *k* of the clip.
|
|
103
|
+
*/
|
|
104
|
+
export function openVideoFrameStream(opts) {
|
|
105
|
+
const { filePath, size, fps, startSec, speed } = opts;
|
|
106
|
+
const filters = [
|
|
107
|
+
speed !== 1 ? `setpts=PTS/${speed}` : null,
|
|
108
|
+
`fps=${fps}`,
|
|
109
|
+
`scale=${size.width}:${size.height}`,
|
|
110
|
+
"format=rgba"
|
|
111
|
+
].filter((f) => f !== null);
|
|
112
|
+
const child = spawnFfmpeg([
|
|
113
|
+
"-v",
|
|
114
|
+
"error",
|
|
115
|
+
...(startSec > 0 ? ["-ss", String(startSec)] : []),
|
|
116
|
+
"-i",
|
|
117
|
+
filePath,
|
|
118
|
+
"-vf",
|
|
119
|
+
filters.join(","),
|
|
120
|
+
"-f",
|
|
121
|
+
"rawvideo",
|
|
122
|
+
"-pix_fmt",
|
|
123
|
+
"rgba",
|
|
124
|
+
"pipe:1"
|
|
125
|
+
]);
|
|
126
|
+
const stderr = captureStderr(child.stderr);
|
|
127
|
+
const frameBytes = size.width * size.height * 4;
|
|
128
|
+
const reader = new FrameReader(child.stdout, frameBytes);
|
|
129
|
+
let spawnError = null;
|
|
130
|
+
child.on("error", (error) => {
|
|
131
|
+
spawnError =
|
|
132
|
+
error.code === "ENOENT" ? new MissingBinaryError("ffmpeg") : error;
|
|
133
|
+
reader.fail(spawnError);
|
|
134
|
+
});
|
|
135
|
+
child.on("close", (code) => {
|
|
136
|
+
if (code !== 0 && code !== null && !reader.done) {
|
|
137
|
+
reader.fail(new Error(`ffmpeg failed to decode clip: ${stderr()}`));
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
let nextIndex = 0;
|
|
141
|
+
let last = null;
|
|
142
|
+
return {
|
|
143
|
+
width: size.width,
|
|
144
|
+
height: size.height,
|
|
145
|
+
async frameAt(index) {
|
|
146
|
+
if (spawnError)
|
|
147
|
+
throw spawnError;
|
|
148
|
+
while (nextIndex <= index) {
|
|
149
|
+
const frame = await reader.next();
|
|
150
|
+
nextIndex += 1;
|
|
151
|
+
if (!frame)
|
|
152
|
+
return last;
|
|
153
|
+
last = frame;
|
|
154
|
+
}
|
|
155
|
+
return last;
|
|
156
|
+
},
|
|
157
|
+
close() {
|
|
158
|
+
reader.close();
|
|
159
|
+
child.kill("SIGKILL");
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/** Only a verified regular source grid can be indexed inside a decode window. */
|
|
164
|
+
async function hasRegularFrameGrid(filePath, fps, signal) {
|
|
165
|
+
if (signal.aborted)
|
|
166
|
+
return false;
|
|
167
|
+
const stdout = await new Promise((resolve) => {
|
|
168
|
+
const child = spawn("ffprobe", [
|
|
169
|
+
"-v", "error", "-select_streams", "v:0",
|
|
170
|
+
"-show_entries", "packet=pts_time", "-of", "csv=p=0", filePath
|
|
171
|
+
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
172
|
+
const chunks = [];
|
|
173
|
+
let bytes = 0;
|
|
174
|
+
let settled = false;
|
|
175
|
+
const finish = (value) => {
|
|
176
|
+
if (settled)
|
|
177
|
+
return;
|
|
178
|
+
settled = true;
|
|
179
|
+
clearTimeout(deadline);
|
|
180
|
+
signal.removeEventListener("abort", cancel);
|
|
181
|
+
resolve(value);
|
|
182
|
+
};
|
|
183
|
+
const cancel = () => {
|
|
184
|
+
child.kill("SIGKILL");
|
|
185
|
+
finish(null);
|
|
186
|
+
};
|
|
187
|
+
const deadline = setTimeout(cancel, 1000);
|
|
188
|
+
signal.addEventListener("abort", cancel, { once: true });
|
|
189
|
+
child.stdout.on("data", (chunk) => {
|
|
190
|
+
bytes += chunk.length;
|
|
191
|
+
if (bytes > 8 * 1024 * 1024) {
|
|
192
|
+
cancel();
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
chunks.push(chunk);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
child.on("error", () => finish(null));
|
|
199
|
+
child.on("close", (code) => finish(code === 0 ? Buffer.concat(chunks).toString("utf8") : null));
|
|
200
|
+
if (signal.aborted)
|
|
201
|
+
cancel();
|
|
202
|
+
});
|
|
203
|
+
if (stdout === null)
|
|
204
|
+
return false;
|
|
205
|
+
const times = stdout.trim().split(/\r?\n/).map(Number);
|
|
206
|
+
if (times.length < 2 || times.some((time) => !Number.isFinite(time)))
|
|
207
|
+
return false;
|
|
208
|
+
times.sort((left, right) => left - right);
|
|
209
|
+
for (const [index, time] of times.entries()) {
|
|
210
|
+
const expected = index / fps;
|
|
211
|
+
const millisecondGrid = Math.round(expected * 1000) / 1000;
|
|
212
|
+
if (Math.min(Math.abs(time - expected), Math.abs(time - millisecondGrid)) > 0.000002)
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Open a source-time-addressed decode of `filePath`, sampling the source on a
|
|
219
|
+
* `1/fps` grid when it matches a verified regular source grid. Other requests
|
|
220
|
+
* use a fresh FFmpeg seek to retain its timestamp and timebase behavior.
|
|
221
|
+
*
|
|
222
|
+
* The underlying decode always runs at the source's own rate (`speed: 1`): the
|
|
223
|
+
* remap curve, not `setpts`, decides which source instant a timeline frame
|
|
224
|
+
* shows.
|
|
225
|
+
*/
|
|
226
|
+
export function openSourceFrameStream(opts) {
|
|
227
|
+
const { filePath, size, fps } = opts;
|
|
228
|
+
const frameBytes = size.width * size.height * 4;
|
|
229
|
+
const byteLimit = opts.maxWindowBytes ?? 128 * 1024 * 1024;
|
|
230
|
+
const durationLimitMs = opts.maxWindowMs ?? 2000;
|
|
231
|
+
// One frame is the minimum useful window, even when its dimensions alone
|
|
232
|
+
// exceed the configured byte limit.
|
|
233
|
+
const windowFrames = Math.max(1, Math.min(Math.floor(byteLimit / frameBytes), Math.floor((durationLimitMs * fps) / 1000) + 1));
|
|
234
|
+
let originFrame = 0;
|
|
235
|
+
let decodedIndex = -1;
|
|
236
|
+
let reopens = 0;
|
|
237
|
+
let reverseWindow = [];
|
|
238
|
+
let closed = false;
|
|
239
|
+
let stream = null;
|
|
240
|
+
let mode = null;
|
|
241
|
+
let lastSeekTarget = null;
|
|
242
|
+
let lastFrame = null;
|
|
243
|
+
const probeController = new AbortController();
|
|
244
|
+
const regularGrid = hasRegularFrameGrid(filePath, fps, probeController.signal);
|
|
245
|
+
const openAt = (sec) => openVideoFrameStream({
|
|
246
|
+
filePath, size, fps, startSec: sec, speed: 1
|
|
247
|
+
});
|
|
248
|
+
const replaceStream = (sec) => {
|
|
249
|
+
if (stream) {
|
|
250
|
+
stream.close();
|
|
251
|
+
reopens += 1;
|
|
252
|
+
}
|
|
253
|
+
stream = openAt(sec);
|
|
254
|
+
return stream;
|
|
255
|
+
};
|
|
256
|
+
return {
|
|
257
|
+
width: size.width,
|
|
258
|
+
height: size.height,
|
|
259
|
+
get reopens() {
|
|
260
|
+
return reopens;
|
|
261
|
+
},
|
|
262
|
+
get reverseWindowBytes() {
|
|
263
|
+
return reverseWindow.length * frameBytes;
|
|
264
|
+
},
|
|
265
|
+
async frameAtSourceSec(sec) {
|
|
266
|
+
if (closed)
|
|
267
|
+
return null;
|
|
268
|
+
const target = Math.max(0, sec);
|
|
269
|
+
const regular = await regularGrid;
|
|
270
|
+
if (closed)
|
|
271
|
+
return null;
|
|
272
|
+
const position = target * fps;
|
|
273
|
+
const targetFrame = Math.round(position);
|
|
274
|
+
const aligned = Math.abs(position - targetFrame) <= 1e-7;
|
|
275
|
+
if (!regular || !aligned) {
|
|
276
|
+
// A source-grid index cannot identify a fractional fresh seek or an
|
|
277
|
+
// unknown/different-rate frame grid. Use FFmpeg's exact seek instead.
|
|
278
|
+
let active = stream;
|
|
279
|
+
if (mode !== "seek" || lastSeekTarget !== target || !active) {
|
|
280
|
+
active = replaceStream(target);
|
|
281
|
+
mode = "seek";
|
|
282
|
+
lastSeekTarget = target;
|
|
283
|
+
reverseWindow = [];
|
|
284
|
+
decodedIndex = -1;
|
|
285
|
+
}
|
|
286
|
+
const frame = await active.frameAt(0);
|
|
287
|
+
if (closed)
|
|
288
|
+
return null;
|
|
289
|
+
if (frame)
|
|
290
|
+
lastFrame = frame;
|
|
291
|
+
return frame ?? lastFrame;
|
|
292
|
+
}
|
|
293
|
+
if (mode !== "window" || !stream) {
|
|
294
|
+
replaceStream(targetFrame / fps);
|
|
295
|
+
mode = "window";
|
|
296
|
+
originFrame = targetFrame;
|
|
297
|
+
decodedIndex = -1;
|
|
298
|
+
reverseWindow = [];
|
|
299
|
+
lastSeekTarget = null;
|
|
300
|
+
}
|
|
301
|
+
let index = targetFrame - originFrame;
|
|
302
|
+
if (index >= 0 && index < reverseWindow.length) {
|
|
303
|
+
const frame = reverseWindow[index] ?? null;
|
|
304
|
+
if (frame)
|
|
305
|
+
lastFrame = frame;
|
|
306
|
+
return frame;
|
|
307
|
+
}
|
|
308
|
+
if (index < 0 || index < decodedIndex) {
|
|
309
|
+
// Decode a bounded window ending at the requested source instant.
|
|
310
|
+
// Later descending requests read its retained frames without seeking.
|
|
311
|
+
const count = Math.min(windowFrames, targetFrame + 1);
|
|
312
|
+
reverseWindow = [];
|
|
313
|
+
if (closed)
|
|
314
|
+
return null;
|
|
315
|
+
originFrame = targetFrame - (count - 1);
|
|
316
|
+
decodedIndex = -1;
|
|
317
|
+
stream = replaceStream(originFrame / fps);
|
|
318
|
+
for (let i = 0; i < count; i++) {
|
|
319
|
+
const frame = await stream.frameAt(i);
|
|
320
|
+
if (closed || !frame)
|
|
321
|
+
return null;
|
|
322
|
+
reverseWindow.push(frame);
|
|
323
|
+
decodedIndex = i;
|
|
324
|
+
}
|
|
325
|
+
index = targetFrame - originFrame;
|
|
326
|
+
}
|
|
327
|
+
if (index < reverseWindow.length) {
|
|
328
|
+
const frame = reverseWindow[index] ?? null;
|
|
329
|
+
if (frame)
|
|
330
|
+
lastFrame = frame;
|
|
331
|
+
return frame;
|
|
332
|
+
}
|
|
333
|
+
reverseWindow = [];
|
|
334
|
+
const active = stream;
|
|
335
|
+
if (!active)
|
|
336
|
+
return null;
|
|
337
|
+
const frame = await active.frameAt(index);
|
|
338
|
+
decodedIndex = Math.max(decodedIndex, index);
|
|
339
|
+
if (frame)
|
|
340
|
+
lastFrame = frame;
|
|
341
|
+
return frame;
|
|
342
|
+
},
|
|
343
|
+
close() {
|
|
344
|
+
closed = true;
|
|
345
|
+
reverseWindow = [];
|
|
346
|
+
probeController.abort();
|
|
347
|
+
stream?.close();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Pull exact-size frames out of a byte stream, with the read-ahead bounded by
|
|
353
|
+
* pausing the stream — a 1080p frame is 8 MB, so an unbounded buffer would let
|
|
354
|
+
* a fast decoder outrun the compositor into gigabytes of RAM.
|
|
355
|
+
*/
|
|
356
|
+
class FrameReader {
|
|
357
|
+
stream;
|
|
358
|
+
frameBytes;
|
|
359
|
+
chunks = [];
|
|
360
|
+
buffered = 0;
|
|
361
|
+
waiting = null;
|
|
362
|
+
failure = null;
|
|
363
|
+
rejectWaiting = null;
|
|
364
|
+
ended = false;
|
|
365
|
+
closed = false;
|
|
366
|
+
constructor(stream, frameBytes) {
|
|
367
|
+
this.stream = stream;
|
|
368
|
+
this.frameBytes = frameBytes;
|
|
369
|
+
stream.on("data", (chunk) => {
|
|
370
|
+
this.chunks.push(chunk);
|
|
371
|
+
this.buffered += chunk.length;
|
|
372
|
+
this.drain();
|
|
373
|
+
if (this.buffered > this.frameBytes * READAHEAD_FRAMES) {
|
|
374
|
+
stream.pause();
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
stream.on("end", () => {
|
|
378
|
+
this.ended = true;
|
|
379
|
+
this.drain();
|
|
380
|
+
});
|
|
381
|
+
stream.on("error", (error) => this.fail(error));
|
|
382
|
+
}
|
|
383
|
+
get done() {
|
|
384
|
+
return this.ended || this.closed;
|
|
385
|
+
}
|
|
386
|
+
next() {
|
|
387
|
+
if (this.failure)
|
|
388
|
+
return Promise.reject(this.failure);
|
|
389
|
+
const ready = this.take();
|
|
390
|
+
if (ready)
|
|
391
|
+
return Promise.resolve(ready);
|
|
392
|
+
if (this.ended || this.closed)
|
|
393
|
+
return Promise.resolve(null);
|
|
394
|
+
this.stream.resume();
|
|
395
|
+
return new Promise((resolve, reject) => {
|
|
396
|
+
this.waiting = resolve;
|
|
397
|
+
this.rejectWaiting = reject;
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
fail(error) {
|
|
401
|
+
this.failure = error;
|
|
402
|
+
const reject = this.rejectWaiting;
|
|
403
|
+
this.waiting = null;
|
|
404
|
+
this.rejectWaiting = null;
|
|
405
|
+
reject?.(error);
|
|
406
|
+
}
|
|
407
|
+
close() {
|
|
408
|
+
this.closed = true;
|
|
409
|
+
this.chunks = [];
|
|
410
|
+
this.buffered = 0;
|
|
411
|
+
this.waiting?.(null);
|
|
412
|
+
this.waiting = null;
|
|
413
|
+
this.rejectWaiting = null;
|
|
414
|
+
}
|
|
415
|
+
drain() {
|
|
416
|
+
if (!this.waiting)
|
|
417
|
+
return;
|
|
418
|
+
const frame = this.take();
|
|
419
|
+
if (frame) {
|
|
420
|
+
const resolve = this.waiting;
|
|
421
|
+
this.waiting = null;
|
|
422
|
+
this.rejectWaiting = null;
|
|
423
|
+
resolve(frame);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
if (this.ended) {
|
|
427
|
+
const resolve = this.waiting;
|
|
428
|
+
this.waiting = null;
|
|
429
|
+
this.rejectWaiting = null;
|
|
430
|
+
resolve(null);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/** Splice one frame out of the buffered chunks, or `null` if short. */
|
|
434
|
+
take() {
|
|
435
|
+
if (this.buffered < this.frameBytes)
|
|
436
|
+
return null;
|
|
437
|
+
const merged = this.chunks.length === 1 ? this.chunks[0] : Buffer.concat(this.chunks);
|
|
438
|
+
const frame = merged.subarray(0, this.frameBytes);
|
|
439
|
+
const rest = merged.subarray(this.frameBytes);
|
|
440
|
+
this.chunks = rest.length > 0 ? [rest] : [];
|
|
441
|
+
this.buffered = rest.length;
|
|
442
|
+
if (this.buffered <= this.frameBytes * READAHEAD_FRAMES) {
|
|
443
|
+
this.stream.resume();
|
|
444
|
+
}
|
|
445
|
+
return new Uint8Array(frame);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Report whether this ffmpeg build ships `encoder`.
|
|
450
|
+
*
|
|
451
|
+
* ProRes 4444 and VP9 are both optional at build time — a distro ffmpeg may
|
|
452
|
+
* carry neither — and a render that discovers this after compositing every
|
|
453
|
+
* frame has burned the whole render. Probed once before the frame loop starts.
|
|
454
|
+
*
|
|
455
|
+
* A build that cannot be asked (no ffmpeg, an unparsable listing) answers
|
|
456
|
+
* `false`, so the caller refuses with a message naming the encoder rather than
|
|
457
|
+
* failing on ffmpeg's own output an hour later.
|
|
458
|
+
*/
|
|
459
|
+
export async function ffmpegHasEncoder(encoder) {
|
|
460
|
+
try {
|
|
461
|
+
const { stdout } = await execFfmpeg(["-hide_banner", "-encoders"], {
|
|
462
|
+
maxBuffer: 8 * 1024 * 1024
|
|
463
|
+
});
|
|
464
|
+
// The listing is `<flags> <name> <description>`; match the name column so
|
|
465
|
+
// an encoder merely mentioned in a description does not count.
|
|
466
|
+
return stdout
|
|
467
|
+
.split("\n")
|
|
468
|
+
.some((line) => line.trim().split(/\s+/)[1] === encoder);
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* H.264 at `yuv420p`, converted to BT.709 and tagged as such.
|
|
476
|
+
*
|
|
477
|
+
* The same reasoning as `outputFormats.ts`: raw RGBA in, YUV out, and without
|
|
478
|
+
* the scaler and the tags ffmpeg uses BT.601 and records nothing, so the file
|
|
479
|
+
* plays back off-hue everywhere. A caller that passes its own `encoderArgs`
|
|
480
|
+
* owns its own colour handling.
|
|
481
|
+
*/
|
|
482
|
+
export function defaultEncoderArgs() {
|
|
483
|
+
return [
|
|
484
|
+
"-c:v",
|
|
485
|
+
"libx264",
|
|
486
|
+
"-preset",
|
|
487
|
+
"veryfast",
|
|
488
|
+
"-pix_fmt",
|
|
489
|
+
"yuv420p",
|
|
490
|
+
"-vf",
|
|
491
|
+
"scale=out_color_matrix=bt709:out_range=tv",
|
|
492
|
+
"-colorspace",
|
|
493
|
+
"bt709",
|
|
494
|
+
"-color_primaries",
|
|
495
|
+
"bt709",
|
|
496
|
+
"-color_trc",
|
|
497
|
+
"bt709"
|
|
498
|
+
];
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Start encoding RGBA frames written at `fps` into `outPath`.
|
|
502
|
+
*
|
|
503
|
+
* `encoderArgs` decides the codec, profile and pixel format — the alpha-capable
|
|
504
|
+
* combinations are the table in `outputFormats.ts`. Frames arrive as
|
|
505
|
+
* straight-alpha RGBA either way; a `yuv*` pixel format drops the channel, a
|
|
506
|
+
* `yuva*` one keeps it.
|
|
507
|
+
*/
|
|
508
|
+
export function openFrameEncoder(opts) {
|
|
509
|
+
const { outPath, width, height, fps } = opts;
|
|
510
|
+
const encoderArgs = opts.encoderArgs ?? defaultEncoderArgs();
|
|
511
|
+
const child = spawnFfmpeg([
|
|
512
|
+
"-y",
|
|
513
|
+
"-v",
|
|
514
|
+
"error",
|
|
515
|
+
"-f",
|
|
516
|
+
"rawvideo",
|
|
517
|
+
"-pix_fmt",
|
|
518
|
+
"rgba",
|
|
519
|
+
"-s",
|
|
520
|
+
`${width}x${height}`,
|
|
521
|
+
"-r",
|
|
522
|
+
String(fps),
|
|
523
|
+
"-i",
|
|
524
|
+
"pipe:0",
|
|
525
|
+
...encoderArgs,
|
|
526
|
+
outPath
|
|
527
|
+
]);
|
|
528
|
+
const stderr = captureStderr(child.stderr);
|
|
529
|
+
// The encoder writes nothing to stdout, but an unread pipe would eventually
|
|
530
|
+
// block the process.
|
|
531
|
+
child.stdout.resume();
|
|
532
|
+
let failure = null;
|
|
533
|
+
const pendingDrains = new Set();
|
|
534
|
+
const fail = (error) => {
|
|
535
|
+
if (failure)
|
|
536
|
+
return;
|
|
537
|
+
failure = error;
|
|
538
|
+
for (const reject of pendingDrains)
|
|
539
|
+
reject(error);
|
|
540
|
+
pendingDrains.clear();
|
|
541
|
+
};
|
|
542
|
+
child.on("error", (error) => {
|
|
543
|
+
fail(error.code === "ENOENT" ? new MissingBinaryError("ffmpeg") : error);
|
|
544
|
+
});
|
|
545
|
+
child.stdin.on("error", fail);
|
|
546
|
+
const closed = new Promise((resolve) => child.on("close", (code) => {
|
|
547
|
+
if (code !== 0) {
|
|
548
|
+
fail(new Error(`ffmpeg failed to encode the timeline: ${stderr()}`));
|
|
549
|
+
}
|
|
550
|
+
else if (pendingDrains.size > 0) {
|
|
551
|
+
fail(new Error("ffmpeg closed before the frame write drained"));
|
|
552
|
+
}
|
|
553
|
+
resolve(code);
|
|
554
|
+
}));
|
|
555
|
+
return {
|
|
556
|
+
async write(rgba) {
|
|
557
|
+
if (failure)
|
|
558
|
+
throw failure;
|
|
559
|
+
const ok = child.stdin.write(Buffer.from(rgba.buffer, rgba.byteOffset, rgba.byteLength));
|
|
560
|
+
if (!ok) {
|
|
561
|
+
await new Promise((resolve, reject) => {
|
|
562
|
+
const rejectPending = (error) => {
|
|
563
|
+
child.stdin.off("drain", onDrain);
|
|
564
|
+
pendingDrains.delete(rejectPending);
|
|
565
|
+
reject(error);
|
|
566
|
+
};
|
|
567
|
+
const onDrain = () => {
|
|
568
|
+
pendingDrains.delete(rejectPending);
|
|
569
|
+
resolve();
|
|
570
|
+
};
|
|
571
|
+
pendingDrains.add(rejectPending);
|
|
572
|
+
child.stdin.once("drain", onDrain);
|
|
573
|
+
if (failure)
|
|
574
|
+
rejectPending(failure);
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
if (failure)
|
|
578
|
+
throw failure;
|
|
579
|
+
},
|
|
580
|
+
async finish() {
|
|
581
|
+
if (failure)
|
|
582
|
+
throw failure;
|
|
583
|
+
child.stdin.end();
|
|
584
|
+
const code = await closed;
|
|
585
|
+
if (failure)
|
|
586
|
+
throw failure;
|
|
587
|
+
if (code !== 0) {
|
|
588
|
+
throw new Error(`ffmpeg failed to encode the timeline: ${stderr()}`);
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
abort() {
|
|
592
|
+
fail(new Error("ffmpeg encoding aborted"));
|
|
593
|
+
child.stdin.destroy();
|
|
594
|
+
child.kill("SIGKILL");
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
//# sourceMappingURL=rawFrames.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rawFrames.js","sourceRoot":"","sources":["../../../src/nodes/timeline/rawFrames.ts"],"names":[],"mappings":"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"}
|