@bitmagic/cli 0.1.69 → 0.1.70-dev.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 (96) hide show
  1. package/dist/bin.js +5 -4
  2. package/dist/bin.js.map +1 -1
  3. package/dist/cli.js +6 -5
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/trailer.js +6 -10
  6. package/dist/commands/trailer.js.map +1 -1
  7. package/dist/editor/recording-sink.d.ts +2 -9
  8. package/dist/editor/recording-sink.js +3 -15
  9. package/dist/editor/recording-sink.js.map +1 -1
  10. package/dist/editor/recording-stream.d.ts +3 -2
  11. package/dist/editor/recording-stream.js +14 -48
  12. package/dist/editor/recording-stream.js.map +1 -1
  13. package/dist/editor/shell-page.js +1 -1
  14. package/dist/editor/shell-page.js.map +1 -1
  15. package/dist/errors.d.ts +8 -0
  16. package/dist/errors.js +16 -0
  17. package/dist/errors.js.map +1 -1
  18. package/dist/generate/video-review.js +1 -1
  19. package/dist/generate/video-review.js.map +1 -1
  20. package/dist/render/qr-png.d.ts +3 -6
  21. package/dist/render/qr-png.js +4 -33
  22. package/dist/render/qr-png.js.map +1 -1
  23. package/dist/scaffold/asset-pipeline-skill-files.d.ts +1 -1
  24. package/dist/scaffold/asset-pipeline-skill-files.js +3 -3
  25. package/dist/trailer/chrome-rasterizers.d.ts +7 -0
  26. package/dist/trailer/chrome-rasterizers.js +7 -0
  27. package/dist/trailer/chrome-rasterizers.js.map +1 -0
  28. package/dist/trailer/game-name.d.ts +2 -0
  29. package/dist/trailer/game-name.js +20 -0
  30. package/dist/trailer/game-name.js.map +1 -0
  31. package/dist/trailer/hud-raster.d.ts +1 -1
  32. package/dist/trailer/hud-raster.js +1 -1
  33. package/dist/trailer/hud-raster.js.map +1 -1
  34. package/dist/trailer/record-session.js +1 -2
  35. package/dist/trailer/record-session.js.map +1 -1
  36. package/dist/trailer/title-raster.d.ts +9 -2
  37. package/dist/trailer/title-raster.js +17 -3
  38. package/dist/trailer/title-raster.js.map +1 -1
  39. package/package.json +4 -4
  40. package/dist/editor/capture-file.d.ts +0 -70
  41. package/dist/editor/capture-file.js +0 -204
  42. package/dist/editor/capture-file.js.map +0 -1
  43. package/dist/trailer/analyze.d.ts +0 -23
  44. package/dist/trailer/analyze.js +0 -186
  45. package/dist/trailer/analyze.js.map +0 -1
  46. package/dist/trailer/auto-edl.d.ts +0 -50
  47. package/dist/trailer/auto-edl.js +0 -267
  48. package/dist/trailer/auto-edl.js.map +0 -1
  49. package/dist/trailer/beat-cut.d.ts +0 -57
  50. package/dist/trailer/beat-cut.js +0 -232
  51. package/dist/trailer/beat-cut.js.map +0 -1
  52. package/dist/trailer/edl-time.d.ts +0 -61
  53. package/dist/trailer/edl-time.js +0 -105
  54. package/dist/trailer/edl-time.js.map +0 -1
  55. package/dist/trailer/ffmpeg.d.ts +0 -18
  56. package/dist/trailer/ffmpeg.js +0 -100
  57. package/dist/trailer/ffmpeg.js.map +0 -1
  58. package/dist/trailer/hud-state.d.ts +0 -181
  59. package/dist/trailer/hud-state.js +0 -525
  60. package/dist/trailer/hud-state.js.map +0 -1
  61. package/dist/trailer/io.d.ts +0 -22
  62. package/dist/trailer/io.js +0 -20
  63. package/dist/trailer/io.js.map +0 -1
  64. package/dist/trailer/link.d.ts +0 -1
  65. package/dist/trailer/link.js +0 -15
  66. package/dist/trailer/link.js.map +0 -1
  67. package/dist/trailer/make.d.ts +0 -56
  68. package/dist/trailer/make.js +0 -212
  69. package/dist/trailer/make.js.map +0 -1
  70. package/dist/trailer/merge.d.ts +0 -7
  71. package/dist/trailer/merge.js +0 -165
  72. package/dist/trailer/merge.js.map +0 -1
  73. package/dist/trailer/music-beats.d.ts +0 -123
  74. package/dist/trailer/music-beats.js +0 -672
  75. package/dist/trailer/music-beats.js.map +0 -1
  76. package/dist/trailer/paths.d.ts +0 -28
  77. package/dist/trailer/paths.js +0 -101
  78. package/dist/trailer/paths.js.map +0 -1
  79. package/dist/trailer/render.d.ts +0 -59
  80. package/dist/trailer/render.js +0 -521
  81. package/dist/trailer/render.js.map +0 -1
  82. package/dist/trailer/revision.d.ts +0 -8
  83. package/dist/trailer/revision.js +0 -31
  84. package/dist/trailer/revision.js.map +0 -1
  85. package/dist/trailer/synth.d.ts +0 -9
  86. package/dist/trailer/synth.js +0 -120
  87. package/dist/trailer/synth.js.map +0 -1
  88. package/dist/trailer/timeline-types.d.ts +0 -195
  89. package/dist/trailer/timeline-types.js +0 -419
  90. package/dist/trailer/timeline-types.js.map +0 -1
  91. package/dist/trailer/titles.d.ts +0 -44
  92. package/dist/trailer/titles.js +0 -124
  93. package/dist/trailer/titles.js.map +0 -1
  94. package/dist/trailer/video-chain.d.ts +0 -129
  95. package/dist/trailer/video-chain.js +0 -261
  96. package/dist/trailer/video-chain.js.map +0 -1
@@ -1,525 +0,0 @@
1
- import { exclusiveOutputEnd, sourceFrameToOutputSec } from './edl-time.js';
2
- import { warn } from './io.js';
3
- /**
4
- * Engine-owned chrome that lives in the HUD element registry but must never
5
- * reach a trailer: interactive controls the viewer can't click in a video.
6
- * `mute-button` is `MuteControl`'s custom element (engine/ui/MuteControl.ts).
7
- */
8
- export const CHROME_ELEMENT_IDS = new Set(['mute-button', 'pause-button']);
9
- /**
10
- * Where to lay the HUD out for rasterization.
11
- *
12
- * During capture only the CANVAS is resized to the recording resolution — the
13
- * DOM HUD keeps laying out against the player's window. Rastering at the
14
- * recording size therefore renders every fixed-pixel HUD metric too small
15
- * relative to the footage (and flips vw-clamps and media queries). With the
16
- * recorded window known, raster at an ASPECT-CORRECTED viewport: the window's
17
- * height (so element size relative to screen height matches what the player
18
- * saw) at the recording's aspect (raw window dimensions would stretch glyphs
19
- * non-uniformly under the final scale whenever the aspects differ). The
20
- * deviceScaleFactor keeps the PNG at or above the recording resolution so
21
- * ffmpeg only ever downscales.
22
- *
23
- * No recorded window → the recording resolution at 1x, bit-for-bit the old
24
- * behavior.
25
- */
26
- export function computeRasterGeometry(recordingWidth, recordingHeight, window) {
27
- if (window === undefined) {
28
- return { viewportWidth: recordingWidth, viewportHeight: recordingHeight, deviceScaleFactor: 1 };
29
- }
30
- const viewportHeight = Math.max(1, Math.round(window.innerHeight));
31
- const viewportWidth = Math.max(1, Math.round(viewportHeight * (recordingWidth / recordingHeight)));
32
- const deviceScaleFactor = Math.max(1, recordingHeight / viewportHeight);
33
- return { viewportWidth, viewportHeight, deviceScaleFactor };
34
- }
35
- // ---------------------------------------------------------------------------
36
- // Defaults
37
- // ---------------------------------------------------------------------------
38
- /** The engine records `frame` on a 60fps source clock. */
39
- export const DEFAULT_HUD_FPS = 60;
40
- /** IGameHUD.showToast's default duration. */
41
- export const DEFAULT_TOAST_MS = 2500;
42
- /** IGameHUD's per-kind default anchor, used when a create op omits one. */
43
- const DEFAULT_ANCHOR = {
44
- progress: 'top-left',
45
- counter: 'top-right',
46
- 'icon-text': 'bottom-left',
47
- timer: 'top-center',
48
- custom: 'top-left'
49
- };
50
- /** Derived timer seconds are rounded to this many decimals for a stable key. */
51
- const SECONDS_DECIMALS = 3;
52
- // ---------------------------------------------------------------------------
53
- // Reduction
54
- // ---------------------------------------------------------------------------
55
- function readString(params, key) {
56
- const value = params[key];
57
- return typeof value === 'string' ? value : undefined;
58
- }
59
- function readNumber(params, key) {
60
- const value = params[key];
61
- return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
62
- }
63
- function readBoolean(params, key) {
64
- const value = params[key];
65
- return typeof value === 'boolean' ? value : undefined;
66
- }
67
- function round(value) {
68
- const factor = 10 ** SECONDS_DECIMALS;
69
- return Math.round(value * factor) / factor;
70
- }
71
- /**
72
- * Incremental reducer over a frame-sorted op stream. Public callers go through
73
- * `reduceHudState`; `collectUiKeyframes` drives one instance forward across a
74
- * clip so a frame-by-frame walk stays linear in the op count.
75
- */
76
- /**
77
- * Whether a container's recorded cssText hides it outright.
78
- *
79
- * Visibility has two records: the show/hide ops, and the `display` inside the
80
- * cssText snapshot the recorder takes on create and on every update (a game
81
- * that toggles `container.style.display` itself, as the docs' Weapon Wheel
82
- * does, never logs a hide op). Neither is authoritative alone — the most
83
- * recent one in frame order is, and only the reducer sees that order — so a
84
- * css snapshot sets `visible` here and later show/hide ops override it.
85
- */
86
- function cssHidesElement(css) {
87
- return /(^|;)\s*display\s*:\s*none\b/i.test(css);
88
- }
89
- class HudReducer {
90
- ops;
91
- fps;
92
- cursor = 0;
93
- hudVisible = true;
94
- health = null;
95
- theme = null;
96
- elements = [];
97
- toasts = [];
98
- /** Insertion-ordered; a re-logged id updates in place (last write wins). */
99
- stylesheets = new Map();
100
- /** The emitted stylesheet array, rebuilt only when a sheet actually changes. */
101
- stylesheetsEmitted = [];
102
- /** Bumped with every real change to the set above; `stateKey` identifies the set by it. */
103
- stylesheetsVersion = 0;
104
- constructor(ops, fps) {
105
- // Stable sort: entries recorded on the same frame keep emission order,
106
- // which IS the stacking order within an anchor.
107
- this.ops = [...ops].sort((a, b) => a.frame - b.frame);
108
- this.fps = fps;
109
- }
110
- /** Apply every op at or before `frame`. Frames must not go backwards. */
111
- advanceTo(frame) {
112
- while (this.cursor < this.ops.length && this.ops[this.cursor].frame <= frame) {
113
- this.apply(this.ops[this.cursor]);
114
- this.cursor++;
115
- }
116
- }
117
- find(id) {
118
- return this.elements.find((el) => el.id === id);
119
- }
120
- apply(op) {
121
- // Engine chrome is part of the HUD but never part of a trailer. A
122
- // stylesheet op's `id` is a head <style> element's id, a different
123
- // namespace from HUD element ids, so it must not be filtered here — a game
124
- // sheet named after a chrome element would otherwise vanish silently.
125
- if (op.op !== 'stylesheet' && 'id' in op && CHROME_ELEMENT_IDS.has(op.id))
126
- return;
127
- switch (op.op) {
128
- case 'create':
129
- this.applyCreate(op.frame, op.id, op.elType, op.params);
130
- break;
131
- case 'update':
132
- this.applyUpdate(op.id, op.text, op.icon, op.percent);
133
- break;
134
- case 'custom-html': {
135
- const el = this.find(op.id);
136
- if (el !== undefined) {
137
- el.html = op.html;
138
- // The container's own cssText rides updates too (onUpdate mutates it
139
- // as freely as the markup); absent on older recordings. Its display
140
- // is a visibility verdict of its own — see cssHidesElement.
141
- if (op.css !== undefined) {
142
- el.css = op.css;
143
- el.visible = !cssHidesElement(op.css);
144
- }
145
- }
146
- break;
147
- }
148
- case 'timer':
149
- this.applyTimer(op.frame, op.id, op.action, op.seconds);
150
- break;
151
- case 'show':
152
- case 'hide': {
153
- const el = this.find(op.id);
154
- if (el !== undefined)
155
- el.visible = op.op === 'show';
156
- break;
157
- }
158
- case 'remove': {
159
- const index = this.elements.findIndex((el) => el.id === op.id);
160
- if (index >= 0)
161
- this.elements.splice(index, 1);
162
- break;
163
- }
164
- case 'health': {
165
- const width = this.health?.width;
166
- this.health = { current: op.current, max: op.max, visible: this.health?.visible ?? false };
167
- if (width !== undefined)
168
- this.health.width = width;
169
- break;
170
- }
171
- case 'health-visible': {
172
- const width = op.width ?? this.health?.width;
173
- this.health = {
174
- current: this.health?.current ?? 0,
175
- max: this.health?.max ?? 100,
176
- visible: op.visible
177
- };
178
- if (width !== undefined)
179
- this.health.width = width;
180
- break;
181
- }
182
- case 'toast': {
183
- const durationMs = op.durationMs ?? DEFAULT_TOAST_MS;
184
- const toast = {
185
- message: op.message,
186
- startFrame: op.frame,
187
- endFrame: op.frame + (durationMs / 1000) * this.fps
188
- };
189
- if (op.variant !== undefined)
190
- toast.variant = op.variant;
191
- if (op.anchor !== undefined)
192
- toast.anchor = op.anchor;
193
- this.toasts.push(toast);
194
- break;
195
- }
196
- case 'hud-visible':
197
- this.hudVisible = op.visible;
198
- break;
199
- case 'theme':
200
- this.theme = op.theme;
201
- break;
202
- case 'stylesheet': {
203
- // An empty css body is a tombstone: the recorder logs it when a sheet
204
- // it had captured disappears from the head, so a skin swapped by
205
- // removal does not replay with both skins applied at once.
206
- const removed = op.css === '';
207
- if (removed ? !this.stylesheets.delete(op.id) : this.stylesheets.get(op.id) === op.css)
208
- break;
209
- if (!removed)
210
- this.stylesheets.set(op.id, op.css);
211
- this.stylesheetsEmitted = [...this.stylesheets].map(([id, css]) => ({ id, css }));
212
- this.stylesheetsVersion++;
213
- break;
214
- }
215
- default:
216
- // Forward compatibility: a newer engine may log ops we predate.
217
- break;
218
- }
219
- }
220
- applyCreate(frame, id, elType, params) {
221
- // Re-creating an id replaces the old element and re-appends it, matching
222
- // the DOM's append-on-create stacking.
223
- const existing = this.elements.findIndex((el) => el.id === id);
224
- if (existing >= 0)
225
- this.elements.splice(existing, 1);
226
- const css = readString(params, 'css');
227
- const el = {
228
- id,
229
- type: elType,
230
- anchor: readString(params, 'anchor') ?? DEFAULT_ANCHOR[elType] ?? 'top-left',
231
- visible: css === undefined || !cssHidesElement(css)
232
- };
233
- const label = readString(params, 'label');
234
- const color = readString(params, 'color');
235
- const width = readNumber(params, 'width');
236
- const showText = readBoolean(params, 'showText');
237
- const percent = readNumber(params, 'percent');
238
- const icon = readString(params, 'icon');
239
- const text = readString(params, 'text');
240
- const iconSize = readNumber(params, 'iconSize');
241
- const countDown = readBoolean(params, 'countDown');
242
- const format = readString(params, 'format');
243
- const html = readString(params, 'html');
244
- if (label !== undefined)
245
- el.label = label;
246
- if (color !== undefined)
247
- el.color = color;
248
- if (width !== undefined)
249
- el.width = width;
250
- if (showText !== undefined)
251
- el.showText = showText;
252
- if (percent !== undefined)
253
- el.percent = percent;
254
- if (icon !== undefined)
255
- el.icon = icon;
256
- if (text !== undefined)
257
- el.text = text;
258
- if (iconSize !== undefined)
259
- el.iconSize = iconSize;
260
- if (countDown !== undefined)
261
- el.countDown = countDown;
262
- if (format !== undefined)
263
- el.format = format;
264
- if (html !== undefined)
265
- el.html = html;
266
- if (css !== undefined)
267
- el.css = css;
268
- if (elType === 'timer') {
269
- const seconds = readNumber(params, 'seconds') ?? 0;
270
- el.timer = { anchorSeconds: seconds, anchorFrame: frame, running: false, createSeconds: seconds };
271
- }
272
- this.elements.push(el);
273
- }
274
- applyUpdate(id, text, icon, percent) {
275
- const el = this.find(id);
276
- if (el === undefined)
277
- return; // updates can trail a remove
278
- if (text !== undefined)
279
- el.text = text;
280
- if (icon !== undefined)
281
- el.icon = icon;
282
- if (percent !== undefined)
283
- el.percent = percent;
284
- }
285
- applyTimer(frame, id, action, seconds) {
286
- const el = this.find(id);
287
- const timer = el?.timer;
288
- if (el === undefined || timer === undefined)
289
- return;
290
- switch (action) {
291
- case 'start':
292
- timer.anchorSeconds = seconds ?? derivedSeconds(timer, frame, el.countDown ?? false, this.fps);
293
- timer.anchorFrame = frame;
294
- timer.running = true;
295
- break;
296
- case 'pause':
297
- timer.anchorSeconds = derivedSeconds(timer, frame, el.countDown ?? false, this.fps);
298
- timer.anchorFrame = frame;
299
- timer.running = false;
300
- break;
301
- case 'reset':
302
- timer.anchorSeconds = seconds ?? timer.createSeconds;
303
- timer.anchorFrame = frame;
304
- timer.running = false;
305
- break;
306
- }
307
- }
308
- /** The replay state as of `frame`. Requires `advanceTo(frame)` first. */
309
- snapshot(frame) {
310
- this.toasts = this.toasts.filter((t) => t.endFrame > frame);
311
- return {
312
- version: 1,
313
- hudVisible: this.hudVisible,
314
- health: this.health === null ? null : { ...this.health },
315
- theme: this.theme,
316
- elements: this.elements.map((el) => emitElement(el, frame, this.fps)),
317
- toasts: this.toasts
318
- .filter((t) => t.startFrame <= frame)
319
- .map((t) => {
320
- const toast = { message: t.message };
321
- if (t.variant !== undefined)
322
- toast.variant = t.variant;
323
- if (t.anchor !== undefined)
324
- toast.anchor = t.anchor;
325
- return toast;
326
- }),
327
- stylesheets: this.stylesheetsEmitted
328
- };
329
- }
330
- }
331
- function derivedSeconds(timer, frame, countDown, fps) {
332
- if (!timer.running)
333
- return timer.anchorSeconds;
334
- const elapsed = Math.max(0, frame - timer.anchorFrame) / fps;
335
- return countDown ? Math.max(0, timer.anchorSeconds - elapsed) : timer.anchorSeconds + elapsed;
336
- }
337
- /** Build the emitted element, in a fixed key order, omitting unset optionals. */
338
- function emitElement(el, frame, fps) {
339
- const state = { id: el.id, type: el.type, anchor: el.anchor, visible: el.visible };
340
- if (el.label !== undefined)
341
- state.label = el.label;
342
- if (el.color !== undefined)
343
- state.color = el.color;
344
- if (el.width !== undefined)
345
- state.width = el.width;
346
- if (el.showText !== undefined)
347
- state.showText = el.showText;
348
- if (el.percent !== undefined)
349
- state.percent = el.percent;
350
- if (el.icon !== undefined)
351
- state.icon = el.icon;
352
- if (el.text !== undefined)
353
- state.text = el.text;
354
- if (el.iconSize !== undefined)
355
- state.iconSize = el.iconSize;
356
- if (el.timer !== undefined)
357
- state.seconds = round(derivedSeconds(el.timer, frame, el.countDown ?? false, fps));
358
- if (el.countDown !== undefined)
359
- state.countDown = el.countDown;
360
- if (el.format !== undefined)
361
- state.format = el.format;
362
- if (el.html !== undefined)
363
- state.html = el.html;
364
- if (el.css !== undefined)
365
- state.css = el.css;
366
- return state;
367
- }
368
- /**
369
- * The complete HUD state at `frame`. Ops after `frame` are ignored; unknown
370
- * op names are skipped rather than throwing.
371
- */
372
- export function reduceHudState(ops, frame, fps = DEFAULT_HUD_FPS) {
373
- const reducer = new HudReducer(ops, fps);
374
- reducer.advanceTo(frame);
375
- return reducer.snapshot(frame);
376
- }
377
- /** True when a state would rasterize to a fully transparent frame. */
378
- export function isBlankHudState(state) {
379
- if (!state.hudVisible)
380
- return true;
381
- if (state.toasts.length > 0)
382
- return false;
383
- if (state.health !== null && state.health.visible)
384
- return false;
385
- return !state.elements.some((el) => el.visible);
386
- }
387
- /**
388
- * 30, not 15: measured on a real cut, the selected footage held 227 distinct
389
- * HUD states across 15.3 s of output (14.8/s average, four of seven clips over
390
- * 15/s), so a 15/s ceiling was discarding roughly 45% of the HUD motion the
391
- * game actually rendered.
392
- *
393
- * ffmpeg used to be the reason for a low ceiling — one PNG input plus one
394
- * serial overlay node per keyframe cost ~23 MB of RSS each and corrupted the
395
- * render above ~400. The overlays now ride one densified image2 sequence whose
396
- * cost is flat in keyframe count (measured 2.83 s / 0.94 GB at both 126 and
397
- * 902 distinct rasters), so the remaining cost is ~25 ms of Playwright per
398
- * keyframe plus its PNG on disk. 0 disables the limit entirely.
399
- */
400
- export const DEFAULT_MAX_KEYFRAMES_PER_SECOND = 30;
401
- /**
402
- * Sole per-clip ceiling, a backstop for `--ui-keyframe-rate 0`: at any real
403
- * rate the limiter below admits at most rate·duration+1 keyframes per clip on
404
- * its own, so nothing else can bind. A fixed 240 used to freeze the overlay
405
- * after 16 s of any clip busy enough to sustain the default rate — exactly the
406
- * clip a trailer is cut from. 60 s of output at 60/s.
407
- */
408
- export const MAX_KEYFRAMES_PER_CLIP_CEILING = 3600;
409
- /**
410
- * Frame times are exact ratios that land just under a spacing boundary in
411
- * binary (frame 18 at 60fps is 0.09999999999999998s after frame 12), which
412
- * would otherwise push every subsequent keyframe a frame later.
413
- */
414
- const SPACING_EPSILON = 1e-9;
415
- /**
416
- * Structural identity of a state. Timer seconds collapse to whole displayed
417
- * seconds (floor — where both floor- and ceil-based formatters change), so a
418
- * ticking clock yields ~1 keyframe per second instead of one per frame.
419
- *
420
- * Stylesheets are keyed by the reducer's change counter, not their bytes: the
421
- * payload can run to the recorder's 128 KB budget and would otherwise be
422
- * re-serialized once per source frame. Keys are only ever compared within one
423
- * reducer's clip, so a per-reducer counter is exact — a set that changes and
424
- * changes back emits one extra byte-identical keyframe, which is harmless.
425
- */
426
- function stateKey(state, stylesheetsVersion) {
427
- const { stylesheets, ...rest } = state;
428
- return (JSON.stringify({
429
- ...rest,
430
- elements: state.elements.map((el) => el.seconds === undefined ? el : { ...el, seconds: Math.floor(el.seconds) })
431
- }) + (stylesheets.length === 0 ? '|none' : `|s${stylesheetsVersion}`));
432
- }
433
- /**
434
- * Walk every enabled clip's source range and emit a keyframe wherever the
435
- * reduced HUD state changes.
436
- *
437
- * A clip's overlays stop at `exclusiveOutputEnd`, so during a crossfade the
438
- * incoming clip's UI takes over at the fade start and exactly one overlay is
439
- * ever active — two stacked HUDs would double-draw every element.
440
- */
441
- export function collectUiKeyframes(ops, clips, opts = {}) {
442
- const fps = opts.fps ?? DEFAULT_HUD_FPS;
443
- const maxPerSecond = opts.maxPerSecond ?? DEFAULT_MAX_KEYFRAMES_PER_SECOND;
444
- const clipEnabled = opts.clipEnabled ?? (() => true);
445
- const log = opts.log ?? warn;
446
- const minSpacingSec = maxPerSecond > 0 ? 1 / maxPerSecond : 0;
447
- const keyframes = [];
448
- for (let index = 0; index < clips.length; index++) {
449
- if (!clipEnabled(index))
450
- continue;
451
- const timing = clips[index];
452
- const windowEnd = exclusiveOutputEnd(clips, index);
453
- const reducer = new HudReducer(ops, fps);
454
- const maxPerClip = opts.maxPerClip ?? MAX_KEYFRAMES_PER_CLIP_CEILING;
455
- const clipFrames = [];
456
- let lastEmittedKey = null;
457
- let lastEmittedSec = Number.NEGATIVE_INFINITY;
458
- // The newest state still waiting for a slot; superseding it loses it.
459
- let pendingKey = null;
460
- let coalesced = 0;
461
- let droppedByCap = 0;
462
- let capped = false;
463
- let firstDroppedFrame = -1;
464
- for (let frame = timing.in; frame < timing.out; frame++) {
465
- const outputSec = sourceFrameToOutputSec(timing, frame, fps);
466
- if (outputSec >= windowEnd)
467
- break;
468
- reducer.advanceTo(frame);
469
- const state = reducer.snapshot(frame);
470
- const key = stateKey(state, reducer.stylesheetsVersion);
471
- if (key === lastEmittedKey)
472
- continue;
473
- if (clipFrames.length >= maxPerClip) {
474
- if (pendingKey !== null && pendingKey !== key)
475
- droppedByCap++;
476
- if (!capped)
477
- firstDroppedFrame = frame;
478
- capped = true;
479
- pendingKey = key;
480
- continue;
481
- }
482
- if (outputSec - lastEmittedSec < minSpacingSec - SPACING_EPSILON) {
483
- // Rate limited: hold, and emit the newest state once spacing allows.
484
- if (pendingKey !== null && pendingKey !== key)
485
- coalesced++;
486
- pendingKey = key;
487
- continue;
488
- }
489
- if (pendingKey !== null && pendingKey !== key)
490
- coalesced++;
491
- clipFrames.push({
492
- sourceFrame: frame,
493
- frameTimeMs: (frame / fps) * 1000,
494
- clipIndex: index,
495
- outputStartSec: outputSec,
496
- outputEndSec: windowEnd,
497
- state
498
- });
499
- lastEmittedKey = key;
500
- lastEmittedSec = outputSec;
501
- pendingKey = null;
502
- }
503
- // Whatever is still pending when the clip ends is never rendered either.
504
- if (pendingKey !== null) {
505
- if (capped)
506
- droppedByCap++;
507
- else
508
- coalesced++;
509
- }
510
- for (let i = 0; i < clipFrames.length - 1; i++) {
511
- clipFrames[i].outputEndSec = clipFrames[i + 1].outputStartSec;
512
- }
513
- keyframes.push(...clipFrames);
514
- if (coalesced > 0) {
515
- log(`ui: clip ${index} rate-limited to ${maxPerSecond} keyframe(s)/s of output time — ` +
516
- `${coalesced} intermediate HUD state(s) never rendered`);
517
- }
518
- if (droppedByCap > 0) {
519
- log(`ui: clip ${index} hit the ${maxPerClip}-keyframe cap at source frame ${firstDroppedFrame} — ` +
520
- `${droppedByCap} later HUD state(s) dropped; the overlay holds its last state`);
521
- }
522
- }
523
- return keyframes;
524
- }
525
- //# sourceMappingURL=hud-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hud-state.js","sourceRoot":"","sources":["../../src/trailer/hud-state.ts"],"names":[],"mappings":"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"}
@@ -1,22 +0,0 @@
1
- /**
2
- * Where the compositor's words go.
3
- *
4
- * The trailer modules narrate as they work — windows scored, overlays rasterized, the render
5
- * summary — and under `--json` every one of those lines must land on stderr, because stdout is
6
- * reserved for the single result document (`output.ts`). The modules cannot know which mode the
7
- * command runs in, so the command binds the Output seam here first and everything below it
8
- * writes through `out`/`warn` without caring.
9
- *
10
- * Unbound (a test, or a module used as a library) both go to stderr: never stdout, so nothing here
11
- * can corrupt a result by accident.
12
- */
13
- export interface TrailerLog {
14
- info(line: string): void;
15
- warn(line: string): void;
16
- }
17
- /** The command layer calls this once with `createOutput(json)` before running any pipeline step. */
18
- export declare function bindTrailerLog(log: TrailerLog): void;
19
- /** Back to stderr — for tests that bound a capturing log. */
20
- export declare function resetTrailerLog(): void;
21
- export declare function out(line: string): void;
22
- export declare function warn(line: string): void;
@@ -1,20 +0,0 @@
1
- const STDERR_LOG = {
2
- info: (line) => process.stderr.write(`${line}\n`),
3
- warn: (line) => process.stderr.write(`${line}\n`),
4
- };
5
- let bound = STDERR_LOG;
6
- /** The command layer calls this once with `createOutput(json)` before running any pipeline step. */
7
- export function bindTrailerLog(log) {
8
- bound = log;
9
- }
10
- /** Back to stderr — for tests that bound a capturing log. */
11
- export function resetTrailerLog() {
12
- bound = STDERR_LOG;
13
- }
14
- export function out(line) {
15
- bound.info(line);
16
- }
17
- export function warn(line) {
18
- bound.warn(line);
19
- }
20
- //# sourceMappingURL=io.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"io.js","sourceRoot":"","sources":["../../src/trailer/io.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,GAAe;IAC7B,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;IACjD,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;CAClD,CAAC;AAEF,IAAI,KAAK,GAAe,UAAU,CAAC;AAEnC,oGAAoG;AACpG,MAAM,UAAU,cAAc,CAAC,GAAe;IAC5C,KAAK,GAAG,GAAG,CAAC;AACd,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,eAAe;IAC7B,KAAK,GAAG,UAAU,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,GAAG,CAAC,IAAY;IAC9B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,IAAY;IAC/B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC"}
@@ -1 +0,0 @@
1
- export declare function linkOrCopy(from: string, to: string): void;
@@ -1,15 +0,0 @@
1
- /**
2
- * Hard-link when possible, copy otherwise — the cross-filesystem (and link-count / no-link
3
- * filesystem) fallback both frame-sequence builders share: `merge` renumbering a session's frames,
4
- * and the render's densified HUD overlay sequence.
5
- */
6
- import * as fs from 'fs';
7
- export function linkOrCopy(from, to) {
8
- try {
9
- fs.linkSync(from, to);
10
- }
11
- catch {
12
- fs.copyFileSync(from, to);
13
- }
14
- }
15
- //# sourceMappingURL=link.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/trailer/link.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,EAAU;IACjD,IAAI,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC"}