versioncam 0.1.3 → 0.3.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/CHANGELOG.md +174 -0
- package/README.md +152 -15
- package/dist/cli/commands/check.js +45 -4
- package/dist/cli/commands/check.js.map +1 -1
- package/dist/cli/commands/doctor.js +39 -2
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/init.js +25 -0
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/preview.js +10 -1
- package/dist/cli/commands/preview.js.map +1 -1
- package/dist/cli/commands/publish.d.ts +17 -0
- package/dist/cli/commands/publish.js +203 -0
- package/dist/cli/commands/publish.js.map +1 -0
- package/dist/cli/commands/record.js +2 -0
- package/dist/cli/commands/record.js.map +1 -1
- package/dist/cli/commands/render.d.ts +17 -0
- package/dist/cli/commands/render.js +98 -21
- package/dist/cli/commands/render.js.map +1 -1
- package/dist/cli/cwd.d.ts +46 -0
- package/dist/cli/cwd.js +102 -0
- package/dist/cli/cwd.js.map +1 -0
- package/dist/cli/main.js +19 -2
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/usage.d.ts +3 -2
- package/dist/cli/usage.js +17 -4
- package/dist/cli/usage.js.map +1 -1
- package/dist/config.d.ts +35 -1
- package/dist/config.js +44 -0
- package/dist/config.js.map +1 -1
- package/dist/core/camera-track.d.ts +63 -0
- package/dist/core/camera-track.js +230 -0
- package/dist/core/camera-track.js.map +1 -0
- package/dist/core/camera.d.ts +14 -1
- package/dist/core/camera.js +18 -2
- package/dist/core/camera.js.map +1 -1
- package/dist/core/follow.d.ts +129 -0
- package/dist/core/follow.js +151 -0
- package/dist/core/follow.js.map +1 -0
- package/dist/core/motion-defaults.d.ts +29 -0
- package/dist/core/motion-defaults.js +29 -0
- package/dist/core/motion-defaults.js.map +1 -1
- package/dist/core/timeline.d.ts +10 -2
- package/dist/core/timeline.js.map +1 -1
- package/dist/driver/clip.d.ts +6 -0
- package/dist/driver/clip.js +6 -3
- package/dist/driver/clip.js.map +1 -1
- package/dist/driver/reports.d.ts +34 -2
- package/dist/driver/reports.js +31 -3
- package/dist/driver/reports.js.map +1 -1
- package/dist/driver/session.d.ts +36 -1
- package/dist/driver/session.js +72 -14
- package/dist/driver/session.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +7 -1
- package/dist/loader.js +23 -8
- package/dist/loader.js.map +1 -1
- package/dist/page/assets/index-fZtacWyp.js +2 -0
- package/dist/page/index.html +1 -1
- package/dist/publish/client.d.ts +38 -0
- package/dist/publish/client.js +118 -0
- package/dist/publish/client.js.map +1 -0
- package/dist/publish/index.d.ts +12 -0
- package/dist/publish/index.js +11 -0
- package/dist/publish/index.js.map +1 -0
- package/dist/publish/manifest.d.ts +46 -0
- package/dist/publish/manifest.js +133 -0
- package/dist/publish/manifest.js.map +1 -0
- package/dist/publish/protocol.d.ts +203 -0
- package/dist/publish/protocol.js +56 -0
- package/dist/publish/protocol.js.map +1 -0
- package/dist/render/encode.d.ts +27 -1
- package/dist/render/encode.js +115 -37
- package/dist/render/encode.js.map +1 -1
- package/dist/render/presentation.d.ts +12 -0
- package/dist/render/presentation.js +15 -0
- package/dist/render/presentation.js.map +1 -1
- package/dist/render/render.js +19 -1
- package/dist/render/render.js.map +1 -1
- package/dist/render/sampling.d.ts +13 -0
- package/dist/render/sampling.js +47 -19
- package/dist/render/sampling.js.map +1 -1
- package/dist/render/scenes.d.ts +16 -0
- package/dist/render/scenes.js +108 -0
- package/dist/render/scenes.js.map +1 -0
- package/dist/render/sequence.d.ts +21 -1
- package/dist/render/sequence.js +71 -14
- package/dist/render/sequence.js.map +1 -1
- package/dist/review/review.js +46 -21
- package/dist/review/review.js.map +1 -1
- package/dsl.md +37 -0
- package/package.json +6 -2
- package/plugin/README.md +7 -2
- package/plugin/agents/versioncam-reviewer.md +3 -2
- package/plugin/skills/versioncam/SKILL.md +60 -14
- package/plugin/skills/versioncam/authoring.md +6 -1
- package/plugin/skills/versioncam/onboarding.md +17 -17
- package/dist/page/assets/index-DUom5amc.js +0 -1
package/dist/render/render.js
CHANGED
|
@@ -5,6 +5,7 @@ import { launchBrowser } from "../driver/launch.js";
|
|
|
5
5
|
import { renderConfigOf } from "../config.js";
|
|
6
6
|
import { bundleScenes } from "../loader.js";
|
|
7
7
|
import { contactSheet as encodeContactSheet, encodeFromPage, } from "./encode.js";
|
|
8
|
+
import { evenFrames } from "./sampling.js";
|
|
8
9
|
import { distPageDir, installRenderRoutes, RENDER_ORIGIN } from "./serve.js";
|
|
9
10
|
/**
|
|
10
11
|
* Open the render page at the exact output size, at DPR 1.
|
|
@@ -61,6 +62,21 @@ export async function openRenderPage(browser, config, target) {
|
|
|
61
62
|
}
|
|
62
63
|
return { page, ...info };
|
|
63
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* The frames a sheet shows when nobody chose them.
|
|
67
|
+
*
|
|
68
|
+
* For a recording, evenly spread and moved past the renderer's dissolves,
|
|
69
|
+
* which only the recording's own cuts can say where they are. Read from its
|
|
70
|
+
* directory rather than by id, since a target can be a recording anywhere. A
|
|
71
|
+
* scene draws every frame itself and never dissolves, so its sheet is the
|
|
72
|
+
* plain even spread the encoder falls back on.
|
|
73
|
+
*/
|
|
74
|
+
async function sheetFrames(config, target, durationFrames) {
|
|
75
|
+
if (target.kind !== "recording")
|
|
76
|
+
return undefined;
|
|
77
|
+
const timeline = JSON.parse(await readFile(join(target.dir, "timeline.json"), "utf8"));
|
|
78
|
+
return evenFrames(durationFrames, undefined, config.motion.crossfadeFrames, timeline.cuts);
|
|
79
|
+
}
|
|
64
80
|
async function renderTarget(browser, config, target) {
|
|
65
81
|
const { page, durationFrames, fps } = await openRenderPage(browser, config, target);
|
|
66
82
|
try {
|
|
@@ -69,10 +85,12 @@ async function renderTarget(browser, config, target) {
|
|
|
69
85
|
fps,
|
|
70
86
|
durationFrames,
|
|
71
87
|
outDir: config.outputDir,
|
|
88
|
+
threads: config.encoderThreads,
|
|
72
89
|
});
|
|
73
90
|
const sheet = await encodeContactSheet(page, {
|
|
74
91
|
id: target.id,
|
|
75
92
|
durationFrames,
|
|
93
|
+
frames: await sheetFrames(config, target, durationFrames),
|
|
76
94
|
outDir: config.outputDir,
|
|
77
95
|
});
|
|
78
96
|
return { ...encoded, id: target.id, durationFrames, fps, sheet };
|
|
@@ -97,7 +115,7 @@ export async function contactSheet(browser, config, target, options = {}) {
|
|
|
97
115
|
return await encodeContactSheet(page, {
|
|
98
116
|
id: target.id,
|
|
99
117
|
durationFrames,
|
|
100
|
-
frames: options.frames,
|
|
118
|
+
frames: options.frames ?? (await sheetFrames(config, target, durationFrames)),
|
|
101
119
|
outDir: config.outputDir,
|
|
102
120
|
});
|
|
103
121
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render/render.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/render/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,6 +8,19 @@ import type { Mark } from "../core/timeline.js";
|
|
|
8
8
|
export declare const SHEET_TILES = 8;
|
|
9
9
|
/** Evenly spaced, ends included: the shape of the clip, knowing nothing about it. */
|
|
10
10
|
export declare function uniformFrames(durationFrames: number, count?: number): number[];
|
|
11
|
+
/**
|
|
12
|
+
* Evenly spaced, ends included, and none of them inside a dissolve: the
|
|
13
|
+
* frames a sheet shows when nobody chose them.
|
|
14
|
+
*
|
|
15
|
+
* An even spread knows nothing about the clip, so it lands wherever the
|
|
16
|
+
* spacing puts it, and after a settle that can be the renderer's crossfade: a
|
|
17
|
+
* plain sheet of the example app showed two tiles with one page ghosting
|
|
18
|
+
* through the next, which `--at-marks` had stopped doing for its own tiles
|
|
19
|
+
* long before. A tile inside a dissolve moves to the first frame after it.
|
|
20
|
+
* The first frame is never inside one, the last stays the last, and two
|
|
21
|
+
* tiles that land on the same frame are one.
|
|
22
|
+
*/
|
|
23
|
+
export declare function evenFrames(durationFrames: number, count?: number, crossfadeFrames?: number, cuts?: readonly number[]): number[];
|
|
11
24
|
/**
|
|
12
25
|
* Frame 0, every beat, and the last frame.
|
|
13
26
|
*
|
package/dist/render/sampling.js
CHANGED
|
@@ -10,6 +10,44 @@ export function uniformFrames(durationFrames, count = SHEET_TILES) {
|
|
|
10
10
|
const tiles = Math.max(2, Math.min(count, durationFrames));
|
|
11
11
|
return Array.from({ length: tiles }, (_, i) => Math.round((i / (tiles - 1)) * (durationFrames - 1)));
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The first frame at or after `frame` that is not inside a dissolve.
|
|
15
|
+
*
|
|
16
|
+
* The renderer dissolves between states for `crossfadeFrames` after every
|
|
17
|
+
* cut, and a tile taken inside that window is two pages at once. A reviewer
|
|
18
|
+
* shown one said so and declined to judge the beat from it, which is the
|
|
19
|
+
* right answer to a question that should not have been asked.
|
|
20
|
+
*
|
|
21
|
+
* Two settles a few frames apart overlap their dissolves, and the first frame
|
|
22
|
+
* after one can be inside the next, so the frame moves on until it is clear
|
|
23
|
+
* of all of them. Never past the last frame, which has nothing after it.
|
|
24
|
+
*/
|
|
25
|
+
function pastCrossfade(frame, durationFrames, crossfadeFrames, cuts) {
|
|
26
|
+
let clear = frame;
|
|
27
|
+
for (;;) {
|
|
28
|
+
const cut = cuts.find((c) => clear > c && clear <= c + crossfadeFrames);
|
|
29
|
+
if (cut === undefined)
|
|
30
|
+
break;
|
|
31
|
+
clear = cut + crossfadeFrames + 1;
|
|
32
|
+
}
|
|
33
|
+
return Math.min(clear, durationFrames - 1);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Evenly spaced, ends included, and none of them inside a dissolve: the
|
|
37
|
+
* frames a sheet shows when nobody chose them.
|
|
38
|
+
*
|
|
39
|
+
* An even spread knows nothing about the clip, so it lands wherever the
|
|
40
|
+
* spacing puts it, and after a settle that can be the renderer's crossfade: a
|
|
41
|
+
* plain sheet of the example app showed two tiles with one page ghosting
|
|
42
|
+
* through the next, which `--at-marks` had stopped doing for its own tiles
|
|
43
|
+
* long before. A tile inside a dissolve moves to the first frame after it.
|
|
44
|
+
* The first frame is never inside one, the last stays the last, and two
|
|
45
|
+
* tiles that land on the same frame are one.
|
|
46
|
+
*/
|
|
47
|
+
export function evenFrames(durationFrames, count = SHEET_TILES, crossfadeFrames = 0, cuts = []) {
|
|
48
|
+
const tiles = uniformFrames(durationFrames, count).map((frame) => pastCrossfade(frame, durationFrames, crossfadeFrames, cuts));
|
|
49
|
+
return [...new Set(tiles)].sort((a, b) => a - b);
|
|
50
|
+
}
|
|
13
51
|
/**
|
|
14
52
|
* Frame 0, every beat, and the last frame.
|
|
15
53
|
*
|
|
@@ -23,23 +61,13 @@ export function uniformFrames(durationFrames, count = SHEET_TILES) {
|
|
|
23
61
|
*/
|
|
24
62
|
export function markedFrames(durationFrames, marks, count = SHEET_TILES, crossfadeFrames = 0, cuts = []) {
|
|
25
63
|
const inRange = (frame) => Number.isInteger(frame) && frame >= 0 && frame < durationFrames;
|
|
26
|
-
//
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
33
|
-
// A mark is the worst case — it sits on the cut's first frame, where the
|
|
34
|
-
// blend has barely begun and the tile still shows what was on screen
|
|
35
|
-
// *before* the wait — but any evenly spread tile can land there too. Marks
|
|
36
|
-
// stay where they are, because `review` wants the state boundary; only the
|
|
37
|
-
// picture waits for the dissolve to finish.
|
|
38
|
-
const settled = (frame) => {
|
|
39
|
-
const cut = cuts.find((c) => frame > c && frame <= c + crossfadeFrames);
|
|
40
|
-
const clear = cut === undefined ? frame : cut + crossfadeFrames + 1;
|
|
41
|
-
return Math.min(clear, durationFrames - 1);
|
|
42
|
-
};
|
|
64
|
+
// A mark is the worst case of a tile inside a dissolve: it sits on the
|
|
65
|
+
// cut's first frame, where the blend has barely begun and the tile still
|
|
66
|
+
// shows what was on screen *before* the wait. `beatFrame` moves its tile
|
|
67
|
+
// past the dissolve that starts there; the marks themselves stay where
|
|
68
|
+
// they are, because `review` wants the state boundary. The spare tiles
|
|
69
|
+
// below come from `evenFrames`, which moves them past any dissolve they
|
|
70
|
+
// land in.
|
|
43
71
|
const wanted = [
|
|
44
72
|
0,
|
|
45
73
|
...marks.map((m) => beatFrame(m, durationFrames, crossfadeFrames)),
|
|
@@ -55,10 +83,10 @@ export function markedFrames(durationFrames, marks, count = SHEET_TILES, crossfa
|
|
|
55
83
|
// the shape of the clip around them.
|
|
56
84
|
if (unique.length < count) {
|
|
57
85
|
const filled = new Set(unique);
|
|
58
|
-
for (const frame of
|
|
86
|
+
for (const frame of evenFrames(durationFrames, count, crossfadeFrames, cuts)) {
|
|
59
87
|
if (filled.size >= count)
|
|
60
88
|
break;
|
|
61
|
-
filled.add(
|
|
89
|
+
filled.add(frame);
|
|
62
90
|
}
|
|
63
91
|
return [...filled].sort((a, b) => a - b);
|
|
64
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../src/render/sampling.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC;AAE7B,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAC3B,cAAsB,EACtB,KAAK,GAAG,WAAW;IAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC,CAAC;IAC3D,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAC5C,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,CACrD,CAAC;AACJ,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"sampling.js","sourceRoot":"","sources":["../../src/render/sampling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Scene } from "../scene.js";
|
|
2
|
+
/**
|
|
3
|
+
* The scenes a module defines, by id, or why there are none to read.
|
|
4
|
+
*
|
|
5
|
+
* `file` names the module in the message: its path, wherever the path is
|
|
6
|
+
* known. The message is three lines at most (what is wrong, the shape, and
|
|
7
|
+
* the one-line fix when there is an obvious one), so `doctor` can print the
|
|
8
|
+
* first as its finding and the rest beneath it.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readScenes(module: Record<string, unknown>, file: string): {
|
|
11
|
+
scenes: Record<string, Scene>;
|
|
12
|
+
} | {
|
|
13
|
+
error: string;
|
|
14
|
+
};
|
|
15
|
+
/** What to say when scenes are asked for that the module does not define. */
|
|
16
|
+
export declare function missingScenes(asked: string[], defined: string[], file: string | null): string;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a scenes module has to export, checked the same way wherever one is
|
|
3
|
+
* read: in Node, where the CLI lists the ids to render and filter, and in the
|
|
4
|
+
* render page, which draws them.
|
|
5
|
+
*
|
|
6
|
+
* Both used to take `module.default` and carry on with whatever it was. A
|
|
7
|
+
* module whose record of scenes was a named export gave them nothing at all:
|
|
8
|
+
* `render` found no scenes, said nothing, and stitched a film without them.
|
|
9
|
+
* Anything that is not a record of scenes now stops the command, naming the
|
|
10
|
+
* file and the shape it should have.
|
|
11
|
+
*
|
|
12
|
+
* A record with nothing in it is still a record, and renders no scenes, which
|
|
13
|
+
* is what it says.
|
|
14
|
+
*/
|
|
15
|
+
/** The shape, as the second line of every refusal. */
|
|
16
|
+
const SHAPE = "versioncam reads scenes from a module's default export: a Record<string, Scene> " +
|
|
17
|
+
"keyed by scene id, as in `export default { [intro.id]: intro }`.";
|
|
18
|
+
/** For anything but a plain object, which is never what is being described. */
|
|
19
|
+
function describe(value) {
|
|
20
|
+
if (value === null || value === undefined)
|
|
21
|
+
return String(value);
|
|
22
|
+
if (Array.isArray(value))
|
|
23
|
+
return "an array";
|
|
24
|
+
return `a ${typeof value}`;
|
|
25
|
+
}
|
|
26
|
+
/** A value as it was written, so `"60"` does not read as the number 60. */
|
|
27
|
+
function shown(value) {
|
|
28
|
+
return typeof value === "string" ? JSON.stringify(value) : String(value);
|
|
29
|
+
}
|
|
30
|
+
function isPlainObject(value) {
|
|
31
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
32
|
+
}
|
|
33
|
+
/** What is wrong with one entry, or null when it can be drawn. */
|
|
34
|
+
function entryProblem(key, value) {
|
|
35
|
+
if (!isPlainObject(value))
|
|
36
|
+
return `"${key}" is ${describe(value)}, not a scene`;
|
|
37
|
+
const { draw, durationFrames, fps } = value;
|
|
38
|
+
if (typeof draw !== "function") {
|
|
39
|
+
return `"${key}" has no draw(ctx, frame, canvas)`;
|
|
40
|
+
}
|
|
41
|
+
if (!Number.isInteger(durationFrames) || durationFrames < 1) {
|
|
42
|
+
return `"${key}" has durationFrames ${shown(durationFrames)}, where a whole number of frames, 1 or more, belongs`;
|
|
43
|
+
}
|
|
44
|
+
if (typeof fps !== "number" || !Number.isFinite(fps) || fps <= 0) {
|
|
45
|
+
return `"${key}" has fps ${shown(fps)}, where a number above 0 belongs`;
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* What is wrong with a would-be record of scenes, as the end of a sentence
|
|
51
|
+
* that starts "default-exports", or null when nothing is.
|
|
52
|
+
*
|
|
53
|
+
* A single scene and an array are singled out because they are the two
|
|
54
|
+
* mistakes a clip file invites: a clip file default-exports one clip or an
|
|
55
|
+
* array of them, and a scenes module does neither.
|
|
56
|
+
*/
|
|
57
|
+
function recordProblem(value) {
|
|
58
|
+
if (!isPlainObject(value))
|
|
59
|
+
return describe(value);
|
|
60
|
+
if (typeof value.draw === "function") {
|
|
61
|
+
return "a single scene rather than a record of them";
|
|
62
|
+
}
|
|
63
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
64
|
+
const problem = entryProblem(key, entry);
|
|
65
|
+
if (problem)
|
|
66
|
+
return `a record in which ${problem}`;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The scenes a module defines, by id, or why there are none to read.
|
|
72
|
+
*
|
|
73
|
+
* `file` names the module in the message: its path, wherever the path is
|
|
74
|
+
* known. The message is three lines at most (what is wrong, the shape, and
|
|
75
|
+
* the one-line fix when there is an obvious one), so `doctor` can print the
|
|
76
|
+
* first as its finding and the rest beneath it.
|
|
77
|
+
*/
|
|
78
|
+
export function readScenes(module, file) {
|
|
79
|
+
if (module.default === undefined) {
|
|
80
|
+
const named = Object.keys(module).filter((name) => name !== "default");
|
|
81
|
+
const lines = [
|
|
82
|
+
`${file} has no default export.` +
|
|
83
|
+
(named.length > 0 ? ` It exports ${named.join(", ")}.` : ""),
|
|
84
|
+
SHAPE,
|
|
85
|
+
];
|
|
86
|
+
// The failure that made this check: the record was there, under a name.
|
|
87
|
+
const records = named.filter((name) => recordProblem(module[name]) === null &&
|
|
88
|
+
Object.keys(module[name]).length > 0);
|
|
89
|
+
if (records.length === 1) {
|
|
90
|
+
lines.push(`${records[0]} is one: add \`export default ${records[0]}\`.`);
|
|
91
|
+
}
|
|
92
|
+
return { error: lines.join("\n") };
|
|
93
|
+
}
|
|
94
|
+
const problem = recordProblem(module.default);
|
|
95
|
+
if (problem) {
|
|
96
|
+
return { error: `${file} default-exports ${problem}.\n${SHAPE}` };
|
|
97
|
+
}
|
|
98
|
+
return { scenes: module.default };
|
|
99
|
+
}
|
|
100
|
+
/** What to say when scenes are asked for that the module does not define. */
|
|
101
|
+
export function missingScenes(asked, defined, file) {
|
|
102
|
+
const names = asked.map((id) => `"${id}"`).join(", ");
|
|
103
|
+
const head = `No scene${asked.length === 1 ? "" : "s"} called ${names}.`;
|
|
104
|
+
if (file === null)
|
|
105
|
+
return `${head} The config names no \`scenes\` module.`;
|
|
106
|
+
return `${head} ${file} defines ${defined.length > 0 ? defined.join(", ") : "none"}.`;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=scenes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenes.js","sourceRoot":"","sources":["../../src/render/scenes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rendered clip. `frameRate` is the fraction ffprobe gives, `60/1` or
|
|
3
|
+
* `30000/1001`, kept as written rather than divided out: it is the rate the
|
|
4
|
+
* filter may convert every clip to, the fastest clip included, and only the
|
|
5
|
+
* exact rate leaves that clip's frames where they were.
|
|
6
|
+
*/
|
|
1
7
|
export type SequenceInput = {
|
|
2
8
|
id: string;
|
|
3
9
|
path: string;
|
|
4
10
|
duration: number;
|
|
11
|
+
frameRate: string;
|
|
5
12
|
};
|
|
6
13
|
/** Duration of a video file, in seconds. Blocking; ffprobe is quick. */
|
|
7
14
|
export declare function probeDuration(path: string): number;
|
|
15
|
+
/** Frame rate of a video file, as the fraction ffprobe gives. Blocking too. */
|
|
16
|
+
export declare function probeFrameRate(path: string): string;
|
|
8
17
|
/**
|
|
9
18
|
* The `xfade` chain. Each transition's `offset` is measured from the start of
|
|
10
19
|
* everything accumulated so far, and every crossfade shortens the total by its
|
|
11
20
|
* own duration — which is the part that is easy to get wrong and shows up as
|
|
12
21
|
* a clip that starts before the previous one has finished.
|
|
22
|
+
*
|
|
23
|
+
* `xfade` joins streams of one frame rate and one timebase only, and clips
|
|
24
|
+
* need not share a rate: a 15 fps draft among 60 fps recordings, or a scene
|
|
25
|
+
* or a clip with an `fps` of its own. When the rates differ, every clip goes
|
|
26
|
+
* through `fps` at the highest of them first. The highest, so that no clip
|
|
27
|
+
* loses a frame: a slower clip's frames are each held as long as they were.
|
|
28
|
+
* Every clip, the fastest included, because `fps` sets the timebase as well,
|
|
29
|
+
* and a clip left alone would keep its own. When the rates agree, the filter
|
|
30
|
+
* is the one it always was.
|
|
13
31
|
*/
|
|
14
32
|
export declare function buildFilter(inputs: SequenceInput[]): {
|
|
15
33
|
filter: string;
|
|
16
34
|
label: string;
|
|
17
35
|
total: number;
|
|
18
36
|
};
|
|
19
|
-
export declare function buildSequence(ids: readonly string[], outDir: string
|
|
37
|
+
export declare function buildSequence(ids: readonly string[], outDir: string, options?: {
|
|
38
|
+
threads?: number | null;
|
|
39
|
+
}): Promise<{
|
|
20
40
|
path: string;
|
|
21
41
|
total: number;
|
|
22
42
|
used: string[];
|
package/dist/render/sequence.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { REPRODUCIBLE, threadArgs } from "./encode.js";
|
|
1
2
|
import { spawn } from "node:child_process";
|
|
2
|
-
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
import { existsSync, renameSync, rmSync, statSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { ffmpegPath, ffprobeSync } from "./ffmpeg.js";
|
|
5
6
|
/**
|
|
@@ -32,28 +33,68 @@ export function probeDuration(path) {
|
|
|
32
33
|
}
|
|
33
34
|
return seconds;
|
|
34
35
|
}
|
|
36
|
+
/** Frame rate of a video file, as the fraction ffprobe gives. Blocking too. */
|
|
37
|
+
export function probeFrameRate(path) {
|
|
38
|
+
const out = ffprobeSync([
|
|
39
|
+
"-v",
|
|
40
|
+
"error",
|
|
41
|
+
"-select_streams",
|
|
42
|
+
"v:0",
|
|
43
|
+
"-show_entries",
|
|
44
|
+
"stream=r_frame_rate",
|
|
45
|
+
"-of",
|
|
46
|
+
"default=nw=1:nk=1",
|
|
47
|
+
path,
|
|
48
|
+
]).trim();
|
|
49
|
+
const rate = rateOf(out);
|
|
50
|
+
if (!Number.isFinite(rate) || rate <= 0) {
|
|
51
|
+
throw new Error(`Could not read a frame rate from ${path}`);
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/** A fraction as ffprobe prints one, `30000/1001`, as a number. */
|
|
56
|
+
function rateOf(fraction) {
|
|
57
|
+
const [num, den = "1"] = fraction.split("/");
|
|
58
|
+
return Number(num) / Number(den);
|
|
59
|
+
}
|
|
35
60
|
/**
|
|
36
61
|
* The `xfade` chain. Each transition's `offset` is measured from the start of
|
|
37
62
|
* everything accumulated so far, and every crossfade shortens the total by its
|
|
38
63
|
* own duration — which is the part that is easy to get wrong and shows up as
|
|
39
64
|
* a clip that starts before the previous one has finished.
|
|
65
|
+
*
|
|
66
|
+
* `xfade` joins streams of one frame rate and one timebase only, and clips
|
|
67
|
+
* need not share a rate: a 15 fps draft among 60 fps recordings, or a scene
|
|
68
|
+
* or a clip with an `fps` of its own. When the rates differ, every clip goes
|
|
69
|
+
* through `fps` at the highest of them first. The highest, so that no clip
|
|
70
|
+
* loses a frame: a slower clip's frames are each held as long as they were.
|
|
71
|
+
* Every clip, the fastest included, because `fps` sets the timebase as well,
|
|
72
|
+
* and a clip left alone would keep its own. When the rates agree, the filter
|
|
73
|
+
* is the one it always was.
|
|
40
74
|
*/
|
|
41
75
|
export function buildFilter(inputs) {
|
|
42
76
|
if (inputs.length === 1)
|
|
43
77
|
return { filter: "", label: "0:v", total: inputs[0].duration };
|
|
44
78
|
const parts = [];
|
|
45
|
-
|
|
79
|
+
const rates = inputs.map((input) => rateOf(input.frameRate));
|
|
80
|
+
const mixed = new Set(rates).size > 1;
|
|
81
|
+
if (mixed) {
|
|
82
|
+
const highest = inputs[rates.indexOf(Math.max(...rates))].frameRate;
|
|
83
|
+
inputs.forEach((_, i) => parts.push(`[${i}:v]fps=${highest}[f${i}]`));
|
|
84
|
+
}
|
|
85
|
+
const stream = (i) => (mixed ? `f${i}` : `${i}:v`);
|
|
86
|
+
let current = stream(0);
|
|
46
87
|
let accumulated = inputs[0].duration;
|
|
47
88
|
for (let i = 1; i < inputs.length; i += 1) {
|
|
48
89
|
const offset = accumulated - TRANSITION_S;
|
|
49
90
|
const label = i === inputs.length - 1 ? "out" : `x${i}`;
|
|
50
|
-
parts.push(`[${current}][${i}
|
|
91
|
+
parts.push(`[${current}][${stream(i)}]xfade=transition=fade:duration=${TRANSITION_S}:offset=${offset.toFixed(3)}[${label}]`);
|
|
51
92
|
current = label;
|
|
52
93
|
accumulated += inputs[i].duration - TRANSITION_S;
|
|
53
94
|
}
|
|
54
95
|
return { filter: parts.join(";"), label: current, total: accumulated };
|
|
55
96
|
}
|
|
56
|
-
export async function buildSequence(ids, outDir) {
|
|
97
|
+
export async function buildSequence(ids, outDir, options = {}) {
|
|
57
98
|
const missing = [];
|
|
58
99
|
const inputs = [];
|
|
59
100
|
for (const id of ids) {
|
|
@@ -62,14 +103,25 @@ export async function buildSequence(ids, outDir) {
|
|
|
62
103
|
missing.push(id);
|
|
63
104
|
continue;
|
|
64
105
|
}
|
|
65
|
-
inputs.push({
|
|
106
|
+
inputs.push({
|
|
107
|
+
id,
|
|
108
|
+
path,
|
|
109
|
+
duration: probeDuration(path),
|
|
110
|
+
frameRate: probeFrameRate(path),
|
|
111
|
+
});
|
|
66
112
|
}
|
|
67
113
|
if (inputs.length < 2) {
|
|
68
114
|
throw new Error(`Need at least two rendered clips to build a sequence; have ${inputs.length}.`);
|
|
69
115
|
}
|
|
70
116
|
const { filter, label, total } = buildFilter(inputs);
|
|
71
117
|
const out = join(outDir, "sequence.mp4");
|
|
72
|
-
|
|
118
|
+
// Made beside the film and moved over it once ffmpeg has finished. ffmpeg
|
|
119
|
+
// opens its output before it finds out whether it can join the clips, and
|
|
120
|
+
// a sequence written straight to sequence.mp4 that failed left it empty,
|
|
121
|
+
// whatever film had been there. `.mp4` last: ffmpeg picks the muxer by it.
|
|
122
|
+
const partial = join(outDir, "sequence.partial.mp4");
|
|
123
|
+
let stderr = "";
|
|
124
|
+
const code = await new Promise((resolve) => {
|
|
73
125
|
const child = spawn(ffmpegPath(), [
|
|
74
126
|
"-y",
|
|
75
127
|
...inputs.flatMap((input) => ["-i", input.path]),
|
|
@@ -87,19 +139,24 @@ export async function buildSequence(ids, outDir) {
|
|
|
87
139
|
"yuv420p",
|
|
88
140
|
"-movflags",
|
|
89
141
|
"+faststart",
|
|
90
|
-
|
|
142
|
+
...REPRODUCIBLE,
|
|
143
|
+
...threadArgs(options.threads),
|
|
144
|
+
partial,
|
|
91
145
|
], { stdio: ["ignore", "ignore", "pipe"] });
|
|
92
|
-
let stderr = "";
|
|
93
146
|
child.stderr.on("data", (c) => {
|
|
94
147
|
stderr += c.toString();
|
|
95
148
|
});
|
|
96
|
-
child.on("close",
|
|
97
|
-
if (code === 0)
|
|
98
|
-
resolve();
|
|
99
|
-
else
|
|
100
|
-
reject(new Error(`sequence failed:\n${stderr.slice(-1200)}`));
|
|
101
|
-
});
|
|
149
|
+
child.on("close", resolve);
|
|
102
150
|
});
|
|
151
|
+
if (code !== 0) {
|
|
152
|
+
rmSync(partial, { force: true });
|
|
153
|
+
// The film still there is not this sequence, and could pass for it.
|
|
154
|
+
const kept = existsSync(out)
|
|
155
|
+
? `\n${out} is from an earlier run, left as it was.`
|
|
156
|
+
: "";
|
|
157
|
+
throw new Error(`sequence failed:\n${stderr.slice(-1200)}${kept}`);
|
|
158
|
+
}
|
|
159
|
+
renameSync(partial, out);
|
|
103
160
|
return { path: out, total, used: inputs.map((i) => i.id), missing };
|
|
104
161
|
}
|
|
105
162
|
//# sourceMappingURL=sequence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../src/render/sequence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../src/render/sequence.ts"],"names":[],"mappings":"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"}
|