versioncam 0.1.2 → 0.2.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 (88) hide show
  1. package/CHANGELOG.md +196 -46
  2. package/README.md +486 -243
  3. package/bin/versioncam.js +1 -1
  4. package/dist/app-server.js +2 -2
  5. package/dist/app-server.js.map +1 -1
  6. package/dist/cli/commands/doctor.js +41 -4
  7. package/dist/cli/commands/doctor.js.map +1 -1
  8. package/dist/cli/commands/init.js +26 -1
  9. package/dist/cli/commands/init.js.map +1 -1
  10. package/dist/cli/commands/preview.js +10 -1
  11. package/dist/cli/commands/preview.js.map +1 -1
  12. package/dist/cli/commands/record.js +3 -2
  13. package/dist/cli/commands/record.js.map +1 -1
  14. package/dist/cli/commands/render.d.ts +17 -0
  15. package/dist/cli/commands/render.js +79 -22
  16. package/dist/cli/commands/render.js.map +1 -1
  17. package/dist/cli/commands/stability.js +4 -4
  18. package/dist/cli/commands/stability.js.map +1 -1
  19. package/dist/cli/cwd.d.ts +46 -0
  20. package/dist/cli/cwd.js +102 -0
  21. package/dist/cli/cwd.js.map +1 -0
  22. package/dist/cli/main.js +11 -2
  23. package/dist/cli/main.js.map +1 -1
  24. package/dist/cli/usage.d.ts +10 -5
  25. package/dist/cli/usage.js +42 -24
  26. package/dist/cli/usage.js.map +1 -1
  27. package/dist/config.d.ts +24 -0
  28. package/dist/config.js +25 -0
  29. package/dist/config.js.map +1 -1
  30. package/dist/core/camera-track.d.ts +63 -0
  31. package/dist/core/camera-track.js +230 -0
  32. package/dist/core/camera-track.js.map +1 -0
  33. package/dist/core/camera.d.ts +14 -1
  34. package/dist/core/camera.js +18 -2
  35. package/dist/core/camera.js.map +1 -1
  36. package/dist/core/follow.d.ts +129 -0
  37. package/dist/core/follow.js +151 -0
  38. package/dist/core/follow.js.map +1 -0
  39. package/dist/core/motion-defaults.d.ts +29 -0
  40. package/dist/core/motion-defaults.js +29 -0
  41. package/dist/core/motion-defaults.js.map +1 -1
  42. package/dist/core/timeline.d.ts +32 -2
  43. package/dist/core/timeline.js +10 -0
  44. package/dist/core/timeline.js.map +1 -1
  45. package/dist/driver/clip.d.ts +4 -1
  46. package/dist/driver/clip.js +9 -1
  47. package/dist/driver/clip.js.map +1 -1
  48. package/dist/driver/session.d.ts +35 -1
  49. package/dist/driver/session.js +81 -12
  50. package/dist/driver/session.js.map +1 -1
  51. package/dist/driver/settle.js +2 -2
  52. package/dist/driver/settle.js.map +1 -1
  53. package/dist/index.d.ts +2 -2
  54. package/dist/index.js +1 -1
  55. package/dist/index.js.map +1 -1
  56. package/dist/inspect/inspect.js +1 -1
  57. package/dist/loader.d.ts +7 -1
  58. package/dist/loader.js +23 -8
  59. package/dist/loader.js.map +1 -1
  60. package/dist/page/assets/index-fZtacWyp.js +2 -0
  61. package/dist/page/index.html +2 -2
  62. package/dist/render/encode.d.ts +12 -1
  63. package/dist/render/encode.js +94 -35
  64. package/dist/render/encode.js.map +1 -1
  65. package/dist/render/presentation.d.ts +12 -0
  66. package/dist/render/presentation.js +15 -0
  67. package/dist/render/presentation.js.map +1 -1
  68. package/dist/render/render.js +19 -2
  69. package/dist/render/render.js.map +1 -1
  70. package/dist/render/sampling.d.ts +13 -0
  71. package/dist/render/sampling.js +48 -20
  72. package/dist/render/sampling.js.map +1 -1
  73. package/dist/render/scenes.d.ts +16 -0
  74. package/dist/render/scenes.js +108 -0
  75. package/dist/render/scenes.js.map +1 -0
  76. package/dist/render/sequence.d.ts +18 -0
  77. package/dist/render/sequence.js +67 -13
  78. package/dist/render/sequence.js.map +1 -1
  79. package/dist/review/review.js +48 -23
  80. package/dist/review/review.js.map +1 -1
  81. package/dsl.md +267 -92
  82. package/package.json +2 -2
  83. package/plugin/README.md +58 -47
  84. package/plugin/agents/versioncam-reviewer.md +3 -2
  85. package/plugin/skills/versioncam/SKILL.md +60 -14
  86. package/plugin/skills/versioncam/authoring.md +6 -1
  87. package/plugin/skills/versioncam/onboarding.md +17 -17
  88. package/dist/page/assets/index-DUom5amc.js +0 -1
@@ -0,0 +1,102 @@
1
+ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
2
+ import { dirname, join, relative, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ /**
5
+ * `--cwd <dir>`: run a command as if from `<dir>`.
6
+ *
7
+ * Every command works in the directory that holds `versioncam.config.ts`:
8
+ * the config, `.env.recording` and `.env`, `.versioncam/`, and any relative
9
+ * path a command is given or prints are that directory's. In a monorepo the
10
+ * app is one directory among many, and whatever runs versioncam may be
11
+ * somewhere else: a script at the repository root, or an agent whose session
12
+ * started inside the app, below its config, and which may not `cd` out of
13
+ * the directory it started in.
14
+ *
15
+ * Its own module so a test can reach it without running the CLI.
16
+ */
17
+ /**
18
+ * `--cwd <dir>` or `--cwd=<dir>`, taken out of the arguments, from anywhere
19
+ * among them. If it is given twice, the last one counts.
20
+ *
21
+ * Anywhere, not only before the command's name, because what an agent may
22
+ * run is a prefix: the reviewer is allowed `npx versioncam frame *` and
23
+ * nothing else, so its flag has to be able to come after `frame`.
24
+ */
25
+ export function takeCwd(argv) {
26
+ let cwd;
27
+ const rest = [];
28
+ for (let i = 0; i < argv.length; i++) {
29
+ const arg = argv[i];
30
+ if (arg !== "--cwd" && !arg.startsWith("--cwd=")) {
31
+ rest.push(arg);
32
+ continue;
33
+ }
34
+ const value = arg === "--cwd" ? argv[++i] : arg.slice("--cwd=".length);
35
+ // A flag where the directory should be is a directory left out, not a
36
+ // directory called `--draft`.
37
+ if (!value || value.startsWith("-")) {
38
+ throw new Error("`--cwd` needs a directory: versioncam <command> --cwd <dir>");
39
+ }
40
+ cwd = value;
41
+ }
42
+ return { cwd, rest };
43
+ }
44
+ /**
45
+ * The versioncam a config in `dir` imports: the first `node_modules/versioncam`
46
+ * from `dir` up, which is where Node looks for a bare `import "versioncam"`.
47
+ * Null where there is none.
48
+ *
49
+ * Resolved through symlinks, so an `npm link` or a pnpm store compares as
50
+ * the directory it really is.
51
+ */
52
+ export function versioncamFrom(dir) {
53
+ for (let at = resolve(dir);; at = dirname(at)) {
54
+ const candidate = join(at, "node_modules", "versioncam");
55
+ if (existsSync(join(candidate, "package.json"))) {
56
+ return realpathSync(candidate);
57
+ }
58
+ if (dirname(at) === at)
59
+ return null;
60
+ }
61
+ }
62
+ /** This package, where it really is: two levels above this file. */
63
+ const RUNNING = realpathSync(resolve(dirname(fileURLToPath(import.meta.url)), "..", ".."));
64
+ /** "versioncam 0.1.3 in <dir>", without the version if it cannot be read. */
65
+ function nameOf(pkg) {
66
+ try {
67
+ const { version } = JSON.parse(readFileSync(join(pkg, "package.json"), "utf8"));
68
+ if (version)
69
+ return `versioncam ${version} in ${pkg}`;
70
+ }
71
+ catch {
72
+ // Named by its directory alone, which is the part that matters.
73
+ }
74
+ return `versioncam in ${pkg}`;
75
+ }
76
+ /**
77
+ * Move into `dir` for the rest of the command, or say why not.
78
+ *
79
+ * Only the directory moves, though, and not the versioncam running: `npx`
80
+ * finds the binary in the directory it runs in and in those above it, never
81
+ * below. Run from above an app that has versioncam in its own
82
+ * `node_modules`, it runs another copy, or downloads the latest one, and that
83
+ * copy would record with a Chromium the app never pinned, beside a config
84
+ * that imports the app's own. So a directory whose own versioncam is not the
85
+ * one running is refused, with how to run its own.
86
+ */
87
+ export function enterCwd(dir) {
88
+ const target = resolve(dir);
89
+ if (!existsSync(target) || !statSync(target).isDirectory()) {
90
+ throw new Error(`\`--cwd ${dir}\`: there is no directory ${target}.`);
91
+ }
92
+ const theirs = versioncamFrom(target);
93
+ if (theirs !== null && theirs !== RUNNING) {
94
+ const shown = relative(process.cwd(), target) || ".";
95
+ throw new Error(`\`--cwd ${dir}\`: that directory has its own ${nameOf(theirs)}, ` +
96
+ `and this is ${nameOf(RUNNING)}.\n` +
97
+ "npx looks for versioncam in the directory it runs in and in those above it, never below.\n" +
98
+ `Run the directory's own instead: cd ${shown}, then the same command without --cwd.`);
99
+ }
100
+ process.chdir(target);
101
+ }
102
+ //# sourceMappingURL=cwd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cwd.js","sourceRoot":"","sources":["../../src/cli/cwd.ts"],"names":[],"mappings":"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"}
package/dist/cli/main.js CHANGED
@@ -16,6 +16,7 @@ import { review } from "./commands/review.js";
16
16
  import { sheet } from "./commands/sheet.js";
17
17
  import { stability } from "./commands/stability.js";
18
18
  import { loadEnvFiles } from "../env.js";
19
+ import { enterCwd, takeCwd } from "./cwd.js";
19
20
  import { USAGE } from "./usage.js";
20
21
  const COMMANDS = {
21
22
  record,
@@ -35,7 +36,9 @@ const COMMANDS = {
35
36
  init,
36
37
  };
37
38
  async function main() {
38
- const argv = process.argv.slice(2);
39
+ // `--cwd` comes out first: it takes a value, which the parsing below would
40
+ // otherwise read as the command's name.
41
+ const { cwd, rest: argv } = takeCwd(process.argv.slice(2));
39
42
  // `--help` is a flag, not a positional, so it never reaches `positionals`.
40
43
  // Asking for help is a success; being given nothing is not.
41
44
  if (argv.some((a) => a === "--help" || a === "-h" || a === "help")) {
@@ -57,8 +60,14 @@ async function main() {
57
60
  process.stderr.write(`Unknown command "${name}".\n\n${USAGE}`);
58
61
  return 1;
59
62
  }
63
+ // Before the environment files, which are that directory's too.
64
+ if (cwd !== undefined)
65
+ enterCwd(cwd);
60
66
  loadEnvFiles(process.cwd());
61
- return command(process.argv.slice(3));
67
+ // The command's own arguments: everything but its name, wherever the name
68
+ // was, which is first unless a flag came before it.
69
+ const at = argv.indexOf(name);
70
+ return command([...argv.slice(0, at), ...argv.slice(at + 1)]);
62
71
  }
63
72
  main().then((code) => {
64
73
  process.exitCode = code;
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,15 @@
1
1
  /**
2
- * What `versioncam --help` prints, and the README's *Commands* block,
3
- * line for line.
2
+ * What `versioncam --help` prints, and the README's *Commands* section,
3
+ * group for group and line for line.
4
4
  *
5
5
  * Its own module so a test can read it without running the CLI: the README
6
6
  * is also the website's documentation, and a test holds the two to the same
7
- * list — the DSL reference learned why, promising an `s.drag` for months that
8
- * did not exist.
7
+ * list. The DSL reference learned why, by promising an `s.drag` for months
8
+ * that did not exist.
9
+ *
10
+ * Grouped by the stage of the work each command belongs to, in the order a
11
+ * repository meets them. A flat list of seventeen commands left a newcomer to
12
+ * work out that `inspect` comes before `record` and `sheet` after it. The
13
+ * last group is not a stage but a way to run any of them.
9
14
  */
10
- export declare const USAGE = "versioncam \u2014 record and render demo clips of a real app\n\n versioncam record [id\u2026] drive the app and capture frames\n --draft 15fps at CSS scale: cheap, for writing clips\n versioncam render [id\u2026] composite and encode what has been recorded\n --scene <id> render a designed scene (repeatable)\n --sequence stitch the results into one piece\n versioncam check [id\u2026] record everything; non-zero if any clip breaks\n versioncam stability [id\u2026] record each clip twice the same way; stable or not\n --runs <n> how many times (default 2)\n --full at full quality rather than draft\n versioncam sheet <id> an eight-frame contact sheet\n --at-marks sample the beats instead of even spacing\n versioncam frame <id> <n> one frame at output size, to a png\n --t <seconds> pick the frame by time instead\n --at <label> or by the beat it shows\n versioncam preview <id> open the scrubber in a real browser\n --scene <id> preview a scene instead\n --frame <n> start at this frame\n versioncam review <id> the checks that need no eyes; PASS/FAIL, exit 0/1\n --beats <file> [{ label, expect }] the clip promised\n --min <s> --max <s> duration bounds (default 9\u201311)\n versioncam inspect <path> what a clip can click, and where each name came from\n --json machine-readable\n versioncam measure <path> <sel> where the matches of a selector are, and what they say\n versioncam dsl the clip DSL, every method, one line each\n versioncam login sign in once and save the browser session\n versioncam doctor check this machine can record, and that the app starts\n versioncam install the Chromium this version of versioncam records with\n --with-deps and its system libraries (Linux CI)\n versioncam init install the authoring skill into .claude/\n --into <dir> into <dir>/versioncam/ instead, for another host\n --force overwrite files that are already there\n\nRun from a directory containing versioncam.config.ts.\n";
15
+ export declare const USAGE = "versioncam: record and render demo clips of a real app\n\nSet up\n versioncam install the Chromium this version of versioncam records with\n --with-deps and its system libraries (Linux CI)\n versioncam init install the authoring skill into .claude/\n --into <dir> into <dir>/versioncam/ instead, for another host\n --force overwrite files that are already there\n versioncam doctor check this machine can record, and that the app starts\n versioncam login sign in once and save the browser session\n\nWrite\n versioncam inspect <path> what a clip can click, and where each name came from\n --json machine-readable\n versioncam measure <path> <sel> where a selector's matches are, and what they say\n versioncam dsl the clip DSL: every method, its options and defaults\n\nRecord\n versioncam record [id\u2026] drive the app and capture frames\n --draft 15fps at CSS scale: cheap, for writing clips\n versioncam check [id\u2026] record every clip; exit 1 if any breaks\n versioncam stability [id\u2026] record each clip twice the same way; stable or not\n --runs <n> how many times (default 2)\n --full at full quality rather than draft\n\nReview\n versioncam sheet <id> an eight-frame contact sheet\n --at-marks sample the beats instead of even spacing\n versioncam frame <id> <n> one frame at output size, to a png\n --t <seconds> pick the frame by time instead\n --at <label> or by the beat it shows\n versioncam review <id> the checks that need no eyes; PASS/FAIL, exit 0/1\n --beats <file> [{ label, expect }] the clip promised\n --min <s> --max <s> duration bounds (default 9 and 11)\n versioncam preview <id> open the scrubber in a real browser\n --scene <id> preview a scene instead\n --frame <n> start at this frame\n\nOutput\n versioncam render [id\u2026] composite and encode recordings and scenes\n no ids: every one, stale recordings included\n --scene <id> and this scene, whatever the ids say (repeatable)\n --sequence stitch the results into one piece\n\nFrom another directory\n versioncam <command> --cwd <dir> as if run in <dir>, which holds versioncam.config.ts\n\nRun from a directory containing versioncam.config.ts, or name it with --cwd.\n";
package/dist/cli/usage.js CHANGED
@@ -1,46 +1,64 @@
1
1
  /**
2
- * What `versioncam --help` prints, and the README's *Commands* block,
3
- * line for line.
2
+ * What `versioncam --help` prints, and the README's *Commands* section,
3
+ * group for group and line for line.
4
4
  *
5
5
  * Its own module so a test can read it without running the CLI: the README
6
6
  * is also the website's documentation, and a test holds the two to the same
7
- * list — the DSL reference learned why, promising an `s.drag` for months that
8
- * did not exist.
7
+ * list. The DSL reference learned why, by promising an `s.drag` for months
8
+ * that did not exist.
9
+ *
10
+ * Grouped by the stage of the work each command belongs to, in the order a
11
+ * repository meets them. A flat list of seventeen commands left a newcomer to
12
+ * work out that `inspect` comes before `record` and `sheet` after it. The
13
+ * last group is not a stage but a way to run any of them.
9
14
  */
10
- export const USAGE = `versioncam — record and render demo clips of a real app
15
+ export const USAGE = `versioncam: record and render demo clips of a real app
11
16
 
17
+ Set up
18
+ versioncam install the Chromium this version of versioncam records with
19
+ --with-deps and its system libraries (Linux CI)
20
+ versioncam init install the authoring skill into .claude/
21
+ --into <dir> into <dir>/versioncam/ instead, for another host
22
+ --force overwrite files that are already there
23
+ versioncam doctor check this machine can record, and that the app starts
24
+ versioncam login sign in once and save the browser session
25
+
26
+ Write
27
+ versioncam inspect <path> what a clip can click, and where each name came from
28
+ --json machine-readable
29
+ versioncam measure <path> <sel> where a selector's matches are, and what they say
30
+ versioncam dsl the clip DSL: every method, its options and defaults
31
+
32
+ Record
12
33
  versioncam record [id…] drive the app and capture frames
13
34
  --draft 15fps at CSS scale: cheap, for writing clips
14
- versioncam render [id…] composite and encode what has been recorded
15
- --scene <id> render a designed scene (repeatable)
16
- --sequence stitch the results into one piece
17
- versioncam check [id…] record everything; non-zero if any clip breaks
35
+ versioncam check [id…] record every clip; exit 1 if any breaks
18
36
  versioncam stability [id…] record each clip twice the same way; stable or not
19
37
  --runs <n> how many times (default 2)
20
38
  --full at full quality rather than draft
39
+
40
+ Review
21
41
  versioncam sheet <id> an eight-frame contact sheet
22
42
  --at-marks sample the beats instead of even spacing
23
43
  versioncam frame <id> <n> one frame at output size, to a png
24
44
  --t <seconds> pick the frame by time instead
25
45
  --at <label> or by the beat it shows
46
+ versioncam review <id> the checks that need no eyes; PASS/FAIL, exit 0/1
47
+ --beats <file> [{ label, expect }] the clip promised
48
+ --min <s> --max <s> duration bounds (default 9 and 11)
26
49
  versioncam preview <id> open the scrubber in a real browser
27
50
  --scene <id> preview a scene instead
28
51
  --frame <n> start at this frame
29
- versioncam review <id> the checks that need no eyes; PASS/FAIL, exit 0/1
30
- --beats <file> [{ label, expect }] the clip promised
31
- --min <s> --max <s> duration bounds (default 9–11)
32
- versioncam inspect <path> what a clip can click, and where each name came from
33
- --json machine-readable
34
- versioncam measure <path> <sel> where the matches of a selector are, and what they say
35
- versioncam dsl the clip DSL, every method, one line each
36
- versioncam login sign in once and save the browser session
37
- versioncam doctor check this machine can record, and that the app starts
38
- versioncam install the Chromium this version of versioncam records with
39
- --with-deps and its system libraries (Linux CI)
40
- versioncam init install the authoring skill into .claude/
41
- --into <dir> into <dir>/versioncam/ instead, for another host
42
- --force overwrite files that are already there
43
52
 
44
- Run from a directory containing versioncam.config.ts.
53
+ Output
54
+ versioncam render [id…] composite and encode recordings and scenes
55
+ no ids: every one, stale recordings included
56
+ --scene <id> and this scene, whatever the ids say (repeatable)
57
+ --sequence stitch the results into one piece
58
+
59
+ From another directory
60
+ versioncam <command> --cwd <dir> as if run in <dir>, which holds versioncam.config.ts
61
+
62
+ Run from a directory containing versioncam.config.ts, or name it with --cwd.
45
63
  `;
46
64
  //# sourceMappingURL=usage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/cli/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCpB,CAAC"}
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/cli/usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDpB,CAAC"}
package/dist/config.d.ts CHANGED
@@ -31,6 +31,25 @@ export type Presentation = {
31
31
  padding?: number;
32
32
  /** "auto" puts it below the app when padded, and over it when not. */
33
33
  caption?: "auto" | "below" | "overlay" | "none";
34
+ /**
35
+ * Where a caption over the app sits: `{ left: n }` or `{ right: n }`,
36
+ * pixels of the video in from that side, which also picks the bottom
37
+ * corner. Default `{ left: 40 }`.
38
+ *
39
+ * An app keeps its own controls in a corner as often as not (an account
40
+ * menu at the foot of a sidebar, a map's legend), and a caption fixed over
41
+ * one hides what a clip may be pointing at. Ignored when the caption sits
42
+ * below the app, where there is nothing of the app to cover.
43
+ */
44
+ captionInset?: CaptionInset;
45
+ };
46
+ /** One side and a distance from it, as CSS's `left` and `right` say it. */
47
+ export type CaptionInset = {
48
+ left: number;
49
+ right?: never;
50
+ } | {
51
+ right: number;
52
+ left?: never;
34
53
  };
35
54
  export type AuthConfig = {
36
55
  storageState: string;
@@ -246,5 +265,10 @@ export type RenderConfig = {
246
265
  presentation: Presentation | null;
247
266
  };
248
267
  motion: Motion;
268
+ /**
269
+ * The scenes module's path. The page is served a bundle of it, and names
270
+ * the file it came from when it cannot read the scenes out of it.
271
+ */
272
+ scenes: string | null;
249
273
  };
250
274
  export declare function renderConfigOf(config: ResolvedConfig): RenderConfig;
package/dist/config.js CHANGED
@@ -13,6 +13,27 @@ function positiveInt(value, field) {
13
13
  }
14
14
  return value;
15
15
  }
16
+ /**
17
+ * A caption inset names one side, and a distance that keeps the caption on
18
+ * the video.
19
+ *
20
+ * Checked because a caption placed off the video fails the way nothing in
21
+ * the presentation layer should: without an error, and without a caption.
22
+ */
23
+ function checkCaptionInset(inset, outputWidth) {
24
+ const field = "theme.presentation.captionInset";
25
+ const given = inset;
26
+ const sides = ["left", "right"].filter((side) => given?.[side] !== undefined);
27
+ if (given === null || sides.length !== 1) {
28
+ fail(field, "must be `{ left: n }` or `{ right: n }`, one side only");
29
+ }
30
+ const px = given[sides[0]];
31
+ if (typeof px !== "number" || !(px >= 0 && px < outputWidth)) {
32
+ // Quoted when it is a string, or `"40"` would read as the 40 it is not.
33
+ const got = typeof px === "string" ? JSON.stringify(px) : String(px);
34
+ fail(`${field}.${sides[0]}`, `must be pixels of the video, from 0 to under its width of ${outputWidth}, got ${got}`);
35
+ }
36
+ }
16
37
  /**
17
38
  * Output dimensions follow the viewport's aspect.
18
39
  *
@@ -90,6 +111,9 @@ export function resolveConfig(config, root) {
90
111
  const outputWidth = config.output?.width ?? 1920;
91
112
  positiveInt(outputWidth, "output.width");
92
113
  const baseUrl = config.baseUrl.replace(/\/+$/, "");
114
+ if (presentation?.captionInset !== undefined) {
115
+ checkCaptionInset(presentation.captionInset, outputWidth);
116
+ }
93
117
  return {
94
118
  root,
95
119
  baseUrl,
@@ -149,6 +173,7 @@ export function renderConfigOf(config) {
149
173
  output: config.output,
150
174
  theme: config.theme,
151
175
  motion: config.motion,
176
+ scenes: config.scenes,
152
177
  };
153
178
  }
154
179
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import type { Viewport } from "./camera.js";
2
+ import type { FollowSpec } from "./follow.js";
3
+ import type { CameraKey, CursorTrack, Rect, Vec2 } from "./timeline.js";
4
+ /**
5
+ * What a clip asked the camera to do, and when: one per `s.camera.*` call.
6
+ *
7
+ * The session keeps these rather than writing camera keys as it goes,
8
+ * because a camera that follows the cursor depends on where the cursor goes
9
+ * *after* the write, and that is only known once the clip has run. The
10
+ * driver never needs the camera while it records: it captures the whole
11
+ * viewport, and the camera is a crop drawn afterwards.
12
+ */
13
+ export type CameraWrite =
14
+ /** `zoom`, `to` and `reset`: glide to a framing and stay there. */
15
+ {
16
+ t: number;
17
+ kind: "frame";
18
+ rect: Rect;
19
+ durationMs: number;
20
+ }
21
+ /** Follow the cursor, until the next write. */
22
+ | {
23
+ t: number;
24
+ kind: "follow";
25
+ spec: FollowSpec;
26
+ durationMs: number;
27
+ }
28
+ /** Stop following, and come to rest on the framing the follow was heading for. */
29
+ | {
30
+ t: number;
31
+ kind: "release";
32
+ };
33
+ export type TrackContext = {
34
+ viewport: Viewport;
35
+ fps: number;
36
+ durationFrames: number;
37
+ cursor: CursorTrack;
38
+ /** Where the cursor rests before the track's first step. */
39
+ cursorStart: Vec2;
40
+ };
41
+ /**
42
+ * Turn a clip's camera writes into the keys the renderer interpolates.
43
+ *
44
+ * Every write starts from where the camera is, moving or not, and blends
45
+ * from there to where it is going:
46
+ *
47
+ * camera(t) = interpolateRect(before(t), destination(t), minjerk(u))
48
+ *
49
+ * where `before` is the camera as it would have gone on without this write,
50
+ * and `u` runs from 0 to 1 over the write's duration. Min-jerk has no slope
51
+ * at either end, so the camera's velocity is continuous where a blend starts
52
+ * and where it ends: entering a follow from a keyed zoom, leaving it for a
53
+ * reset, or a zoom written while another is still under way. That last one
54
+ * used to wait for the move before it to finish and then run short, because
55
+ * each glide set off from the previous glide's target.
56
+ *
57
+ * A clip that never follows and never writes a move while another is under
58
+ * way gets exactly the keys it always got: a hold where each write starts and
59
+ * a min-jerk key where it ends. Every other clip gets the camera sampled at
60
+ * each frame (the `"linear"` keys), since a blend between two moving framings
61
+ * is no longer a glide between two keys.
62
+ */
63
+ export declare function cameraTrack(writes: readonly CameraWrite[], context: TrackContext): CameraKey[];