@anvpx/motion-cli 0.0.0-stage → 0.1.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.
Files changed (197) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +121 -2
  3. package/dist/analyze/command.d.ts +2 -0
  4. package/dist/analyze/command.js +190 -0
  5. package/dist/approval/approval.d.ts +32 -0
  6. package/dist/approval/approval.js +141 -0
  7. package/dist/approval/command.d.ts +2 -0
  8. package/dist/approval/command.js +255 -0
  9. package/dist/approval/gate.d.ts +7 -0
  10. package/dist/approval/gate.js +23 -0
  11. package/dist/approval/hash.d.ts +71 -0
  12. package/dist/approval/hash.js +464 -0
  13. package/dist/args.d.ts +30 -0
  14. package/dist/args.js +53 -0
  15. package/dist/assets/command.d.ts +2 -0
  16. package/dist/assets/command.js +165 -0
  17. package/dist/captions/command.d.ts +2 -0
  18. package/dist/captions/command.js +341 -0
  19. package/dist/captions/cues.d.ts +10 -0
  20. package/dist/captions/cues.js +61 -0
  21. package/dist/catalog/command.d.ts +2 -0
  22. package/dist/catalog/command.js +60 -0
  23. package/dist/catalog/format.d.ts +13 -0
  24. package/dist/catalog/format.js +54 -0
  25. package/dist/cli.d.ts +3 -0
  26. package/dist/cli.js +35 -0
  27. package/dist/commands.d.ts +3 -0
  28. package/dist/commands.js +59 -0
  29. package/dist/compare/command.d.ts +4 -0
  30. package/dist/compare/command.js +144 -0
  31. package/dist/contact/argv.d.ts +24 -0
  32. package/dist/contact/argv.js +42 -0
  33. package/dist/contact/command.d.ts +2 -0
  34. package/dist/contact/command.js +79 -0
  35. package/dist/doctor/checks.d.ts +25 -0
  36. package/dist/doctor/checks.js +571 -0
  37. package/dist/doctor/command.d.ts +4 -0
  38. package/dist/doctor/command.js +88 -0
  39. package/dist/doctor/format.d.ts +7 -0
  40. package/dist/doctor/format.js +41 -0
  41. package/dist/doctor/heal.d.ts +14 -0
  42. package/dist/doctor/heal.js +71 -0
  43. package/dist/doctor/pins.d.ts +8 -0
  44. package/dist/doctor/pins.js +28 -0
  45. package/dist/doctor/skills.d.ts +15 -0
  46. package/dist/doctor/skills.js +58 -0
  47. package/dist/doctor/types.d.ts +36 -0
  48. package/dist/doctor/types.js +1 -0
  49. package/dist/doctor/vendored.d.ts +15 -0
  50. package/dist/doctor/vendored.js +90 -0
  51. package/dist/doctor/version.d.ts +8 -0
  52. package/dist/doctor/version.js +11 -0
  53. package/dist/exit-codes.d.ts +16 -0
  54. package/dist/exit-codes.js +15 -0
  55. package/dist/fit/command.d.ts +5 -0
  56. package/dist/fit/command.js +154 -0
  57. package/dist/fit/solve.d.ts +21 -0
  58. package/dist/fit/solve.js +80 -0
  59. package/dist/fit/target.d.ts +18 -0
  60. package/dist/fit/target.js +47 -0
  61. package/dist/generate3d/command.d.ts +3 -0
  62. package/dist/generate3d/command.js +38 -0
  63. package/dist/generate3d/run.d.ts +39 -0
  64. package/dist/generate3d/run.js +77 -0
  65. package/dist/icon/command.d.ts +2 -0
  66. package/dist/icon/command.js +113 -0
  67. package/dist/index.d.ts +18 -0
  68. package/dist/index.js +16 -0
  69. package/dist/install-mk.d.ts +31 -0
  70. package/dist/install-mk.js +168 -0
  71. package/dist/integration/preview.integration.d.ts +1 -0
  72. package/dist/integration/preview.integration.js +53 -0
  73. package/dist/integration/smoke.integration.d.ts +1 -0
  74. package/dist/integration/smoke.integration.js +91 -0
  75. package/dist/main.d.ts +2 -0
  76. package/dist/main.js +4 -0
  77. package/dist/node-io.d.ts +14 -0
  78. package/dist/node-io.js +152 -0
  79. package/dist/optimize/command.d.ts +12 -0
  80. package/dist/optimize/command.js +110 -0
  81. package/dist/packs/command.d.ts +2 -0
  82. package/dist/packs/command.js +109 -0
  83. package/dist/patch/apply.d.ts +36 -0
  84. package/dist/patch/apply.js +186 -0
  85. package/dist/patch/command.d.ts +2 -0
  86. package/dist/patch/command.js +92 -0
  87. package/dist/plugin/install.d.ts +40 -0
  88. package/dist/plugin/install.js +170 -0
  89. package/dist/preview/command.d.ts +10 -0
  90. package/dist/preview/command.js +764 -0
  91. package/dist/preview/manifest.d.ts +94 -0
  92. package/dist/preview/manifest.js +19 -0
  93. package/dist/preview/pack.d.ts +24 -0
  94. package/dist/preview/pack.js +53 -0
  95. package/dist/preview/plan.d.ts +58 -0
  96. package/dist/preview/plan.js +160 -0
  97. package/dist/preview/provenance.d.ts +23 -0
  98. package/dist/preview/provenance.js +38 -0
  99. package/dist/publish/command.d.ts +2 -0
  100. package/dist/publish/command.js +70 -0
  101. package/dist/publish/player.d.ts +25 -0
  102. package/dist/publish/player.js +108 -0
  103. package/dist/publish/static.d.ts +16 -0
  104. package/dist/publish/static.js +78 -0
  105. package/dist/qc.d.ts +2 -0
  106. package/dist/qc.js +192 -0
  107. package/dist/scene/author.d.ts +16 -0
  108. package/dist/scene/author.js +279 -0
  109. package/dist/scene/command.d.ts +2 -0
  110. package/dist/scene/command.js +110 -0
  111. package/dist/scene/ops.d.ts +23 -0
  112. package/dist/scene/ops.js +151 -0
  113. package/dist/state/command.d.ts +2 -0
  114. package/dist/state/command.js +128 -0
  115. package/dist/state/evidence.d.ts +71 -0
  116. package/dist/state/evidence.js +243 -0
  117. package/dist/storyboard/check.d.ts +21 -0
  118. package/dist/storyboard/check.js +39 -0
  119. package/dist/storyboard/containment.d.ts +24 -0
  120. package/dist/storyboard/containment.js +43 -0
  121. package/dist/storyboard/custom.d.ts +15 -0
  122. package/dist/storyboard/custom.js +133 -0
  123. package/dist/storyboard/edit.d.ts +19 -0
  124. package/dist/storyboard/edit.js +39 -0
  125. package/dist/storyboard/load.d.ts +11 -0
  126. package/dist/storyboard/load.js +52 -0
  127. package/dist/storyboard/report.d.ts +5 -0
  128. package/dist/storyboard/report.js +8 -0
  129. package/dist/template/coerce.d.ts +6 -0
  130. package/dist/template/coerce.js +44 -0
  131. package/dist/template/command.d.ts +5 -0
  132. package/dist/template/command.js +163 -0
  133. package/dist/template/env.d.ts +34 -0
  134. package/dist/template/env.js +38 -0
  135. package/dist/template/fork.d.ts +8 -0
  136. package/dist/template/fork.js +156 -0
  137. package/dist/template/format.d.ts +21 -0
  138. package/dist/template/format.js +161 -0
  139. package/dist/template/list.d.ts +15 -0
  140. package/dist/template/list.js +116 -0
  141. package/dist/template/new.d.ts +6 -0
  142. package/dist/template/new.js +302 -0
  143. package/dist/testing/env.d.ts +8 -0
  144. package/dist/testing/env.js +19 -0
  145. package/dist/testing/fakes.d.ts +33 -0
  146. package/dist/testing/fakes.js +95 -0
  147. package/dist/testing/fixtures.d.ts +8 -0
  148. package/dist/testing/fixtures.js +6 -0
  149. package/dist/testing/probe.d.ts +15 -0
  150. package/dist/testing/probe.js +20 -0
  151. package/dist/testing/project.d.ts +22 -0
  152. package/dist/testing/project.js +26 -0
  153. package/dist/tooling/session.d.ts +40 -0
  154. package/dist/tooling/session.js +106 -0
  155. package/dist/types.d.ts +59 -0
  156. package/dist/types.js +1 -0
  157. package/dist/verify/audio-loudness.d.ts +46 -0
  158. package/dist/verify/audio-loudness.js +186 -0
  159. package/dist/verify/command.d.ts +2 -0
  160. package/dist/verify/command.js +161 -0
  161. package/dist/verify/determinism.d.ts +30 -0
  162. package/dist/verify/determinism.js +59 -0
  163. package/dist/verify/expectation.d.ts +15 -0
  164. package/dist/verify/expectation.js +19 -0
  165. package/dist/verify/media-events.d.ts +61 -0
  166. package/dist/verify/media-events.js +174 -0
  167. package/dist/verify/platform.d.ts +33 -0
  168. package/dist/verify/platform.js +59 -0
  169. package/dist/verify/probe.d.ts +14 -0
  170. package/dist/verify/probe.js +23 -0
  171. package/dist/verify/report.d.ts +15 -0
  172. package/dist/verify/report.js +45 -0
  173. package/dist/verify/run.d.ts +27 -0
  174. package/dist/verify/run.js +53 -0
  175. package/dist/voice/command.d.ts +3 -0
  176. package/dist/voice/command.js +49 -0
  177. package/dist/voice/manifest.d.ts +33 -0
  178. package/dist/voice/manifest.js +69 -0
  179. package/dist/voice/run.d.ts +27 -0
  180. package/dist/voice/run.js +190 -0
  181. package/dist/workflow/build.d.ts +2 -0
  182. package/dist/workflow/build.js +25 -0
  183. package/dist/workflow/draft.d.ts +9 -0
  184. package/dist/workflow/draft.js +215 -0
  185. package/dist/workflow/finish.d.ts +23 -0
  186. package/dist/workflow/finish.js +28 -0
  187. package/dist/workflow/project.d.ts +73 -0
  188. package/dist/workflow/project.js +198 -0
  189. package/dist/workflow/provenance.d.ts +18 -0
  190. package/dist/workflow/provenance.js +36 -0
  191. package/dist/workflow/render.d.ts +31 -0
  192. package/dist/workflow/render.js +721 -0
  193. package/dist/workflow/still.d.ts +5 -0
  194. package/dist/workflow/still.js +62 -0
  195. package/dist/workflow/validate.d.ts +2 -0
  196. package/dist/workflow/validate.js +49 -0
  197. package/package.json +38 -3
@@ -0,0 +1,198 @@
1
+ import { createHash } from "node:crypto";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { buildProject, clearCache, resolveTimeline, validateStoryboardFull, } from "@anvpx/motion-build";
4
+ import { AssetLedgerSchema, toJsonPointer, } from "@anvpx/motion-schema";
5
+ import { parseFlags, requireStoryboard, textFlag, usageError, } from "../args.js";
6
+ import { EXIT } from "../exit-codes.js";
7
+ import { checkStoryboard, rootError } from "../storyboard/check.js";
8
+ import { hasCustomScenes, readCustomScenes } from "../storyboard/custom.js";
9
+ import { readJsonFile } from "../storyboard/load.js";
10
+ import { formatFindings } from "../storyboard/report.js";
11
+ import { platformLookup } from "../verify/platform.js";
12
+ /** Per-scene build cache, next to the storyboard. */
13
+ const CACHE_DIR = ".mk-cache";
14
+ export const PROJECT_FLAGS = {
15
+ out: { type: "string" },
16
+ assets: { type: "string" },
17
+ ledger: { type: "string" },
18
+ incremental: { type: "boolean" },
19
+ "no-incremental": { type: "boolean" },
20
+ "clean-cache": { type: "boolean" },
21
+ "shared-cache-dir": { type: "string" },
22
+ "no-custom": { type: "boolean" },
23
+ };
24
+ /** Parses `<storyboard.json>` plus the shared build flags and whatever `extra` flags a command adds. */
25
+ export function parseBuildArgs(name, usage, args, extra, io) {
26
+ const parsed = parseFlags(name, usage, args, { ...PROJECT_FLAGS, ...extra }, io);
27
+ if (parsed.kind === "exit")
28
+ return parsed;
29
+ const storyboard = requireStoryboard(name, usage, parsed.positionals, io);
30
+ if (typeof storyboard !== "string")
31
+ return storyboard;
32
+ if (parsed.flags.incremental === true && parsed.flags["no-incremental"] === true) {
33
+ return usageError(name, usage, "--incremental and --no-incremental conflict", io);
34
+ }
35
+ const assetsDir = textFlag(parsed.flags, "assets");
36
+ const ledger = textFlag(parsed.flags, "ledger");
37
+ const sharedCacheDir = textFlag(parsed.flags, "shared-cache-dir");
38
+ const outDir = resolve(textFlag(parsed.flags, "out") ?? join(dirname(resolve(storyboard)), "out", "project"));
39
+ return {
40
+ kind: "run",
41
+ flags: parsed.flags,
42
+ request: {
43
+ storyboard,
44
+ outDir,
45
+ ...(assetsDir === undefined ? {} : { assetsDir: resolve(assetsDir) }),
46
+ ...(ledger === undefined ? {} : { ledger }),
47
+ ...(sharedCacheDir === undefined ? {} : { sharedCacheDir: resolve(sharedCacheDir) }),
48
+ incremental: parsed.flags.incremental === true,
49
+ cleanCache: parsed.flags["clean-cache"] === true,
50
+ cacheDir: join(dirname(resolve(storyboard)), CACHE_DIR),
51
+ ...(parsed.flags["no-custom"] === true ? { noCustom: true } : {}),
52
+ },
53
+ };
54
+ }
55
+ const fail = (io, findings) => {
56
+ io.stderr(formatFindings(findings));
57
+ return { ok: false, code: EXIT.USAGE };
58
+ };
59
+ async function loadLedger(path, io) {
60
+ const loaded = await readJsonFile(path, io.host);
61
+ if (!loaded.ok && loaded.kind === "io") {
62
+ io.stderr(`mk: ${loaded.message}\n`);
63
+ return { ok: false, code: EXIT.USAGE };
64
+ }
65
+ if (!loaded.ok)
66
+ return fail(io, [rootError(`${path}: ${loaded.message}`)]);
67
+ const parsed = AssetLedgerSchema.safeParse(loaded.value);
68
+ if (parsed.success)
69
+ return { ok: true, value: parsed.data };
70
+ return fail(io, parsed.error.issues.map((issue) => ({
71
+ severity: "error",
72
+ path: toJsonPointer(issue.path),
73
+ message: `${path}: ${issue.message}`,
74
+ })));
75
+ }
76
+ async function loadStoryboard(path, io, lint) {
77
+ const loaded = await readJsonFile(path, io.host);
78
+ if (!loaded.ok && loaded.kind === "io") {
79
+ io.stderr(`mk: ${loaded.message}\n`);
80
+ return { ok: false, code: EXIT.USAGE };
81
+ }
82
+ if (!loaded.ok)
83
+ return fail(io, [rootError(loaded.message)]);
84
+ const report = checkStoryboard(loaded.value, { lint });
85
+ if (report.errors.length > 0 || report.total === undefined || report.meta === undefined) {
86
+ return fail(io, report.errors);
87
+ }
88
+ return { ok: true, value: { json: loaded.value, total: report.total, meta: report.meta } };
89
+ }
90
+ /** Project themes: every `themes/<name>.json` next to the storyboard, keyed by file name. */
91
+ async function loadProjectThemes(storyboard, io) {
92
+ const dir = join(dirname(resolve(storyboard)), "themes");
93
+ const names = (await io.host.listDir(dir).catch(() => [])).filter((name) => name.endsWith(".json"));
94
+ const docs = {};
95
+ for (const name of names.sort()) {
96
+ const loaded = await readJsonFile(join(dir, name), io.host);
97
+ if (!loaded.ok && loaded.kind === "io") {
98
+ io.stderr(`mk: ${loaded.message}\n`);
99
+ return { ok: false, code: EXIT.USAGE };
100
+ }
101
+ if (!loaded.ok)
102
+ return fail(io, [rootError(`${join(dir, name)}: ${loaded.message}`)]);
103
+ docs[name.slice(0, -".json".length)] = loaded.value;
104
+ }
105
+ return { ok: true, value: docs };
106
+ }
107
+ /** `sha256` of the manifest.json that the build just wrote. */
108
+ async function manifestHash(outDir, io) {
109
+ const text = await io.host.readText(join(outDir, "manifest.json"));
110
+ return createHash("sha256").update(text).digest("hex");
111
+ }
112
+ const cacheNote = (cache) => cache ? `, cache: ${cache.hits} hit / ${cache.misses} miss` : "";
113
+ /** Everything a build reads from disk: storyboard, optional ledger, project themes. */
114
+ async function loadInputs(request, io) {
115
+ const board = await loadStoryboard(request.storyboard, io, request.lint !== false);
116
+ if (!board.ok)
117
+ return board;
118
+ const ledger = request.ledger === undefined ? undefined : await loadLedger(request.ledger, io);
119
+ if (ledger && !ledger.ok)
120
+ return ledger;
121
+ const themes = await loadProjectThemes(request.storyboard, io);
122
+ if (!themes.ok)
123
+ return themes;
124
+ const inputs = { board: board.value, themes: themes.value };
125
+ return { ok: true, value: ledger ? { ...inputs, ledger: ledger.value } : inputs };
126
+ }
127
+ /** Voice total for the board, or a Failure when the timing override cannot resolve. */
128
+ async function resolveVoiceTotal(boardJson, timing, io) {
129
+ const valid = validateStoryboardFull(boardJson);
130
+ if (!valid.ok)
131
+ return fail(io, valid.errors.map((e) => ({ severity: "error", ...e })));
132
+ const timeline = resolveTimeline(valid.value, timing);
133
+ if (!timeline.ok)
134
+ return fail(io, timeline.errors.map((e) => ({ severity: "error", ...e })));
135
+ return { total: timeline.value.total };
136
+ }
137
+ /** Validates, builds the HyperFrames project and prints one summary line. */
138
+ export async function prepareProject(request, io) {
139
+ const inputs = await loadInputs(request, io);
140
+ if (!inputs.ok)
141
+ return inputs;
142
+ const { board, ledger, themes } = inputs.value;
143
+ // Voice override: resolve the narration total now so the printed line,
144
+ // the returned total (verify expectation), and the build all agree.
145
+ // Without timing this block is skipped: byte-identical to today.
146
+ let total = board.total;
147
+ if (request.timing !== undefined) {
148
+ const voice = await resolveVoiceTotal(board.json, request.timing, io);
149
+ if (!("total" in voice))
150
+ return voice;
151
+ total = voice.total;
152
+ }
153
+ try {
154
+ if (request.cleanCache)
155
+ clearCache(request.cacheDir);
156
+ if (request.noCustom === true && hasCustomScenes(board.json)) {
157
+ return fail(io, [
158
+ {
159
+ severity: "error",
160
+ path: "",
161
+ message: "storyboard uses authored scenes and --no-custom was given",
162
+ suggestion: "drop --no-custom, or replace the custom scenes with catalog types",
163
+ },
164
+ ]);
165
+ }
166
+ const custom = await readCustomScenes(board.json, request.storyboard, io.host);
167
+ const customErrors = custom.findings.filter((finding) => finding.severity === "error");
168
+ if (customErrors.length > 0)
169
+ return fail(io, customErrors);
170
+ const built = buildProject({
171
+ storyboard: board.json,
172
+ outDir: request.outDir,
173
+ ...(request.lint === false ? { lint: false } : {}),
174
+ themes,
175
+ platforms: await platformLookup(io.host),
176
+ ...(request.incremental ? { cacheDir: request.cacheDir } : {}),
177
+ ...(request.incremental && request.sharedCacheDir !== undefined
178
+ ? { sharedCacheDir: request.sharedCacheDir }
179
+ : {}),
180
+ ...(request.assetsDir === undefined ? {} : { assetsDir: request.assetsDir }),
181
+ ...(ledger ? { ledger } : {}),
182
+ ...(request.timing === undefined ? {} : { timing: request.timing }),
183
+ ...(Object.keys(custom.sources).length === 0 ? {} : { customScenes: custom.sources }),
184
+ });
185
+ if (!built.ok)
186
+ return fail(io, built.errors.map((e) => ({ severity: "error", ...e })));
187
+ io.stderr(formatFindings(built.warnings));
188
+ const hash = await manifestHash(built.outDir, io);
189
+ const cache = cacheNote(built.cache);
190
+ io.stdout(`built ${built.files.length} files, ${total}s total, manifest sha256 ${hash}${cache} -> ${built.outDir}\n`);
191
+ const { meta } = board;
192
+ return { ok: true, outDir: built.outDir, total, meta };
193
+ }
194
+ catch (error) {
195
+ io.stderr(`mk: build failed: ${error.message}\n`);
196
+ return { ok: false, code: EXIT.ERROR };
197
+ }
198
+ }
@@ -0,0 +1,18 @@
1
+ import { type RenderManifestInput } from "@anvpx/motion-build";
2
+ import type { Io } from "../types.ts";
3
+ export declare const RENDER_MANIFEST = "render-manifest.json";
4
+ export interface RenderRecord {
5
+ kind: RenderManifestInput["kind"];
6
+ /** The project directory that holds `manifest.json`. */
7
+ outDir: string;
8
+ /** Absolute path of the rendered mp4. */
9
+ file: string;
10
+ params: RenderManifestInput["params"];
11
+ verify: RenderManifestInput["verify"];
12
+ }
13
+ /**
14
+ * Writes `<outDir>/render-manifest.json`: the build manifest hash, render params, output hash,
15
+ * tool versions and verify status. Machine independent (basename only, no timestamps); the
16
+ * latest render overwrites it, `output.file` and `kind` say which one it describes.
17
+ */
18
+ export declare function writeRenderManifest(io: Io, record: RenderRecord): Promise<string>;
@@ -0,0 +1,36 @@
1
+ import { join } from "node:path";
2
+ import { createRenderManifest, renderRenderManifest, } from "@anvpx/motion-build";
3
+ import { readPins } from "../doctor/pins.js";
4
+ import { formatVersion, parseVersion } from "../doctor/version.js";
5
+ export const RENDER_MANIFEST = "render-manifest.json";
6
+ const BUILD_MANIFEST = "manifest.json";
7
+ const UNKNOWN = "unknown";
8
+ const UNAVAILABLE = "unavailable";
9
+ const FFMPEG_VERSION = /version\s+n?(\d+)\.(\d+)(?:\.(\d+))?/;
10
+ async function ffmpegVersion(io) {
11
+ const result = await io.run("ffmpeg", ["-version"]);
12
+ const version = result.code === 0 ? parseVersion(result.stdout, FFMPEG_VERSION) : undefined;
13
+ return version ? formatVersion(version) : UNKNOWN;
14
+ }
15
+ /**
16
+ * Writes `<outDir>/render-manifest.json`: the build manifest hash, render params, output hash,
17
+ * tool versions and verify status. Machine independent (basename only, no timestamps); the
18
+ * latest render overwrites it, `output.file` and `kind` say which one it describes.
19
+ */
20
+ export async function writeRenderManifest(io, record) {
21
+ const hyperframes = readPins(await io.host.readRootPackageJson()).hyperframes ?? UNKNOWN;
22
+ const manifest = createRenderManifest({
23
+ kind: record.kind,
24
+ manifestSha256: (await io.host.sha256File(join(record.outDir, BUILD_MANIFEST))) ?? UNAVAILABLE,
25
+ output: {
26
+ file: record.file.split(/[\\/]/).pop() ?? record.file,
27
+ sha256: (await io.host.sha256File(record.file)) ?? UNAVAILABLE,
28
+ },
29
+ params: record.params,
30
+ tools: { ffmpeg: await ffmpegVersion(io), hyperframes, node: io.host.nodeVersion },
31
+ verify: record.verify,
32
+ });
33
+ const path = join(record.outDir, RENDER_MANIFEST);
34
+ await io.host.writeText(path, renderRenderManifest(manifest));
35
+ return path;
36
+ }
@@ -0,0 +1,31 @@
1
+ import type { Command, Io } from "../types.ts";
2
+ /** Delivery containers the command can write (the master is always final.mp4). */
3
+ export declare const DELIVERY_FORMATS: readonly ["mp4", "webm", "mov", "gif", "png-sequence"];
4
+ export type DeliveryFormat = (typeof DELIVERY_FORMATS)[number];
5
+ export declare const RESOLUTIONS: readonly ["1080p", "4k"];
6
+ export type Resolution = (typeof RESOLUTIONS)[number];
7
+ /** `4k` maps to the hyperframes preset that matches the storyboard's aspect. */
8
+ export declare const resolutionPreset: (width: number, height: number) => string;
9
+ /** Output of a non-mp4 format: `final.<ext>`, or the `final.frames` directory for a PNG sequence. */
10
+ export declare const exportFile: (outDir: string, format: Exclude<DeliveryFormat, "mp4">) => string;
11
+ /** ffmpeg argv for the delivery conversion; the master mp4 is the source of truth. */
12
+ export declare const exportArgs: (master: string, format: Exclude<DeliveryFormat, "mp4">, outDir: string) => {
13
+ args: string[];
14
+ file: string;
15
+ };
16
+ /** Converts the published master into the requested delivery format. */
17
+ export declare function exportArtifact(io: Io, outDir: string, format: Exclude<DeliveryFormat, "mp4">): Promise<{
18
+ readonly ok: true;
19
+ readonly file: string;
20
+ } | {
21
+ readonly ok: false;
22
+ readonly code: number;
23
+ }>;
24
+ /**
25
+ * ADR-0008 D3: the problems to report for a typed failed delivery. A failure
26
+ * with an empty list is still a failure, never a silent success.
27
+ */
28
+ export declare const deliveryFailureProblems: (delivery: {
29
+ problems: readonly string[];
30
+ }) => string[];
31
+ export declare const renderCommand: Command;