@maravilla-labs/frames 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -30,6 +30,15 @@ export type VideoInstr = {
30
30
  seek?: number;
31
31
  /** CSS selector for the `<video>` element. */
32
32
  selector: string;
33
+ /**
34
+ * Storage key of a pre-extracted frame-set manifest for this clip (the
35
+ * `output_key` returned by `platform.env.TRANSFORMS.extractFrames`). When
36
+ * present, the headless renderer swaps the live `<video>` for the matching
37
+ * frame image per captured frame (required under begin-frame-control, which
38
+ * can't seek a live video). Optional — without it the renderer falls back to
39
+ * extracting frames at render time, and the screenshot path seeks live video.
40
+ */
41
+ frameset?: string;
33
42
  };
34
43
  /**
35
44
  * Drive a CSS-class-triggered animation (Animate.css, Magic, your own
@@ -59,12 +68,39 @@ export type TimelineSchema = {
59
68
  duration: number;
60
69
  instructions: Instr[];
61
70
  };
71
+ /** A `<video>` slot as exposed to the renderer engine (worker). The engine
72
+ * pre-extracts each clip to frames with ffmpeg and swaps the live `<video>`
73
+ * for the matching frame image per captured frame — so the live video is never
74
+ * seeked under begin-frame-control (which crashes headless Chromium). */
75
+ export type VideoSlotInfo = {
76
+ /** CSS selector for the `<video>`. */
77
+ selector: string;
78
+ /** Timeline start, ms. */
79
+ at: number;
80
+ /** How long the clip plays on the timeline, ms. */
81
+ duration: number;
82
+ /** Start offset within the clip, ms. */
83
+ seek: number;
84
+ /** Resolved clip URL (`currentSrc` || `src`). */
85
+ src: string;
86
+ /** Pre-extracted frame-set manifest storage key, if the app provided one. */
87
+ frameset?: string;
88
+ };
62
89
  declare global {
63
90
  interface Window {
64
91
  __mvFrames: {
65
92
  applyState(t: number): Promise<void>;
93
+ /** Video slots in this timeline — read by the renderer engine to
94
+ * swap video frames out-of-band. Empty when no video. */
95
+ videos: VideoSlotInfo[];
66
96
  };
97
+ /** Set true by the headless renderer when it captures (`__mvFramesRendererPresent`). */
67
98
  __mvFramesRendererPresent?: boolean;
99
+ /** Set true by the renderer ONLY on the begin-frame-control capture path,
100
+ * where the live `<video>` must not be seeked (the engine swaps in
101
+ * pre-extracted frame images instead). When unset — the screenshot capture
102
+ * path and the live editor/preview — `applyState` seeks the live video. */
103
+ __mvFramesNoVideoSeek?: boolean;
68
104
  }
69
105
  }
70
106
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,yDAAyD;IACzD,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,uDAAuD;IACvD,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,gCAAgC;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,mGAAmG;IACnG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,cAAc,GAAG,UAAU,GAAG,aAAa,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAEzE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,EAAE;YAAE,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;SAAE,CAAC;QACrD,yBAAyB,CAAC,EAAE,OAAO,CAAC;KACrC;CACF;AAaD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAW3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,cAAc,GAAG;IAC3B,yDAAyD;IACzD,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,mEAAmE;IACnE,EAAE,EAAE,MAAM,CAAC;IACX,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,uDAAuD;IACvD,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC;IACX,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,gCAAgC;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,kEAAkE;IAClE,EAAE,EAAE,MAAM,CAAC;IACX,mGAAmG;IACnG,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,cAAc,GAAG,UAAU,GAAG,aAAa,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,KAAK,EAAE,CAAA;CAAE,CAAC;AAEzE;;;yEAGyE;AACzE,MAAM,MAAM,aAAa,GAAG;IAC1B,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,UAAU,EAAE;YACV,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC;qEACyD;YACzD,MAAM,EAAE,aAAa,EAAE,CAAC;SACzB,CAAC;QACF,wFAAwF;QACxF,yBAAyB,CAAC,EAAE,OAAO,CAAC;QACpC;;;mFAG2E;QAC3E,qBAAqB,CAAC,EAAE,OAAO,CAAC;KACjC;CACF;AAsBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAW3D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BhD"}
package/dist/index.js CHANGED
@@ -60,6 +60,53 @@ export function stylesheetsReady() {
60
60
  })
61
61
  .then(() => (document.fonts ? document.fonts.ready.then(() => undefined) : undefined));
62
62
  }
63
+ /**
64
+ * Seek `el` to `targetSec` and resolve only once the seeked frame has
65
+ * actually decoded — so a subsequent capture grabs the right frame instead
66
+ * of racing an in-flight seek.
67
+ *
68
+ * Resolution waits for the `seeked` event, then for one decoded video frame
69
+ * via `requestVideoFrameCallback` where available (fallback: a microtask, so
70
+ * we still yield to the decode). A timeout guards against `seeked` never
71
+ * firing (e.g. seeking to the exact current position, or an unsupported
72
+ * codec) so `applyState` can't hang the whole render. Already-satisfied
73
+ * seeks (`readyState` high enough and time already at target) resolve fast.
74
+ */
75
+ function seekVideo(el, targetSec) {
76
+ const HAVE_CURRENT_DATA = 2;
77
+ // If we're already at (or within a frame of) the target with data ready,
78
+ // there's nothing to wait for — assigning currentTime won't fire `seeked`.
79
+ const alreadyThere = Math.abs(el.currentTime - targetSec) < 1e-3 && el.readyState >= HAVE_CURRENT_DATA;
80
+ el.currentTime = targetSec;
81
+ if (alreadyThere)
82
+ return Promise.resolve();
83
+ return new Promise((resolve) => {
84
+ let done = false;
85
+ const finish = () => {
86
+ if (done)
87
+ return;
88
+ done = true;
89
+ el.removeEventListener("seeked", onSeeked);
90
+ clearTimeout(timer);
91
+ resolve();
92
+ };
93
+ const afterSeeked = () => {
94
+ // Wait for one decoded frame to be presented when the API exists.
95
+ const rvfc = el.requestVideoFrameCallback;
96
+ if (typeof rvfc === "function") {
97
+ rvfc.call(el, () => finish());
98
+ }
99
+ else {
100
+ // No rVFC: yield a microtask so the decode can settle, then finish.
101
+ Promise.resolve().then(finish);
102
+ }
103
+ };
104
+ const onSeeked = () => afterSeeked();
105
+ el.addEventListener("seeked", onSeeked, { once: true });
106
+ // Guard: never let a missing `seeked` stall the render.
107
+ const timer = setTimeout(finish, 2000);
108
+ });
109
+ }
63
110
  function installTimeline(schema) {
64
111
  const rendererPresent = typeof window !== "undefined" && window.__mvFramesRendererPresent === true;
65
112
  const slots = schema.instructions.flatMap((i) => {
@@ -74,8 +121,25 @@ function installTimeline(schema) {
74
121
  const naturalMs = isFinite(el.duration) ? el.duration * 1000 : Infinity;
75
122
  const duration = i.duration ?? Math.min(naturalMs, schema.duration - i.at);
76
123
  el.pause();
77
- el.currentTime = seek / 1000;
78
- return [{ kind: "video", at: i.at, duration, seek, el }];
124
+ // In renderer mode the engine drives video by swapping in pre-extracted
125
+ // frame images; we must NOT seek the live <video> (seeking under
126
+ // begin-frame-control crashes headless Chromium). In browser preview the
127
+ // setTimeout scheduler below plays it normally.
128
+ if (!rendererPresent) {
129
+ el.currentTime = seek / 1000;
130
+ }
131
+ return [
132
+ {
133
+ kind: "video",
134
+ at: i.at,
135
+ duration,
136
+ seek,
137
+ el,
138
+ selector: i.selector,
139
+ src: el.currentSrc || el.src,
140
+ frameset: i.frameset,
141
+ },
142
+ ];
79
143
  }
80
144
  if (i.kind === "css") {
81
145
  if (!(el instanceof HTMLElement)) {
@@ -131,30 +195,47 @@ function installTimeline(schema) {
131
195
  anim.pause();
132
196
  return [{ kind: "animation", at: i.at, duration, anim }];
133
197
  });
198
+ // Metadata for the renderer engine: which `<video>`s to pre-extract + swap.
199
+ const videos = slots
200
+ .filter((s) => s.kind === "video")
201
+ .map((s) => ({
202
+ selector: s.selector,
203
+ at: s.at,
204
+ duration: s.duration,
205
+ seek: s.seek,
206
+ src: s.src,
207
+ frameset: s.frameset,
208
+ }));
134
209
  window.__mvFrames = {
210
+ videos,
135
211
  async applyState(t) {
136
212
  const videoWaits = [];
137
213
  for (const s of slots) {
138
214
  if (s.kind === "css-pending")
139
215
  continue; // only relevant in browser preview
140
- const local = clamp(t - s.at, 0, s.duration);
141
216
  if (s.kind === "video") {
142
- s.el.pause();
143
- const target = (s.seek + local) / 1000;
144
- // Seeking is async: the decoded frame for `target` is NOT ready the
145
- // instant we assign `currentTime`. The renderer captures each frame
146
- // with a synchronous CDP `beginFrame` right after `applyState`
147
- // resolves, so we MUST wait for the seek to land and the frame to
148
- // decode — otherwise we capture a stale/blank frame, or (under
149
- // deterministic `--enable-begin-frame-control`) race the media
150
- // pipeline and wedge/crash the headless tab.
151
- videoWaits.push(seekVideo(s.el, target));
152
- }
153
- else {
154
- s.anim.currentTime = local;
217
+ const local = clamp(t - s.at, 0, s.duration);
218
+ // Seek the live <video> EXCEPT on the renderer's begin-frame-control
219
+ // capture path (where seeking crashes the headless tab the engine
220
+ // swaps in pre-extracted frame images instead, flagged via
221
+ // `__mvFramesNoVideoSeek`). On every live-seek path (editor, live
222
+ // preview, AND the renderer's screenshot capture) we must AWAIT the
223
+ // seeked frame's decode before resolving — otherwise a capture races
224
+ // an in-flight seek and grabs a stale/blank frame (and the per-frame
225
+ // loop spins, hitting the render wall-clock budget). `seekVideo`
226
+ // guards with a timeout so a missing `seeked` can't hang the render.
227
+ if (!window.__mvFramesNoVideoSeek) {
228
+ videoWaits.push(seekVideo(s.el, (s.seek + local) / 1000));
229
+ }
230
+ continue;
155
231
  }
232
+ const local = clamp(t - s.at, 0, s.duration);
233
+ s.anim.currentTime = local;
156
234
  }
157
- await Promise.all([document.fonts.ready, ...videoWaits]);
235
+ await Promise.all([
236
+ document.fonts ? document.fonts.ready.then(() => undefined) : Promise.resolve(),
237
+ ...videoWaits,
238
+ ]);
158
239
  },
159
240
  };
160
241
  if (!rendererPresent) {
@@ -194,51 +275,4 @@ function installTimeline(schema) {
194
275
  function clamp(v, lo, hi) {
195
276
  return v < lo ? lo : v > hi ? hi : v;
196
277
  }
197
- /**
198
- * Seek `el` to `targetSec` and resolve only once the seeked frame has
199
- * actually decoded — so a subsequent capture grabs the right frame instead
200
- * of racing an in-flight seek.
201
- *
202
- * Resolution waits for the `seeked` event, then for one decoded video frame
203
- * via `requestVideoFrameCallback` where available (fallback: a microtask, so
204
- * we still yield to the decode). A timeout guards against `seeked` never
205
- * firing (e.g. seeking to the exact current position, or an unsupported
206
- * codec) so `applyState` can't hang the whole render. Already-satisfied
207
- * seeks (`readyState` high enough and time already at target) resolve fast.
208
- */
209
- function seekVideo(el, targetSec) {
210
- const HAVE_CURRENT_DATA = 2;
211
- // If we're already at (or within a frame of) the target with data ready,
212
- // there's nothing to wait for — assigning currentTime won't fire `seeked`.
213
- const alreadyThere = Math.abs(el.currentTime - targetSec) < 1e-3 && el.readyState >= HAVE_CURRENT_DATA;
214
- el.currentTime = targetSec;
215
- if (alreadyThere)
216
- return Promise.resolve();
217
- return new Promise((resolve) => {
218
- let done = false;
219
- const finish = () => {
220
- if (done)
221
- return;
222
- done = true;
223
- el.removeEventListener("seeked", onSeeked);
224
- clearTimeout(timer);
225
- resolve();
226
- };
227
- const afterSeeked = () => {
228
- // Wait for one decoded frame to be presented when the API exists.
229
- const rvfc = el.requestVideoFrameCallback;
230
- if (typeof rvfc === "function") {
231
- rvfc.call(el, () => finish());
232
- }
233
- else {
234
- // No rVFC: yield a microtask so the decode can settle, then finish.
235
- Promise.resolve().then(finish);
236
- }
237
- };
238
- const onSeeked = () => afterSeeked();
239
- el.addEventListener("seeked", onSeeked, { once: true });
240
- // Guard: never let a missing `seeked` stall the render.
241
- const timer = setTimeout(finish, 2000);
242
- });
243
- }
244
278
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maravilla-labs/frames",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Tiny vanilla helper for declaring Web Animations API timelines that the Maravilla runtime renderer drives frame-accurately.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/index.ts CHANGED
@@ -32,6 +32,15 @@ export type VideoInstr = {
32
32
  seek?: number;
33
33
  /** CSS selector for the `<video>` element. */
34
34
  selector: string;
35
+ /**
36
+ * Storage key of a pre-extracted frame-set manifest for this clip (the
37
+ * `output_key` returned by `platform.env.TRANSFORMS.extractFrames`). When
38
+ * present, the headless renderer swaps the live `<video>` for the matching
39
+ * frame image per captured frame (required under begin-frame-control, which
40
+ * can't seek a live video). Optional — without it the renderer falls back to
41
+ * extracting frames at render time, and the screenshot path seeks live video.
42
+ */
43
+ frameset?: string;
35
44
  };
36
45
 
37
46
  /**
@@ -61,15 +70,54 @@ export type CssClassInstr = {
61
70
  export type Instr = AnimationInstr | VideoInstr | CssClassInstr;
62
71
  export type TimelineSchema = { duration: number; instructions: Instr[] };
63
72
 
73
+ /** A `<video>` slot as exposed to the renderer engine (worker). The engine
74
+ * pre-extracts each clip to frames with ffmpeg and swaps the live `<video>`
75
+ * for the matching frame image per captured frame — so the live video is never
76
+ * seeked under begin-frame-control (which crashes headless Chromium). */
77
+ export type VideoSlotInfo = {
78
+ /** CSS selector for the `<video>`. */
79
+ selector: string;
80
+ /** Timeline start, ms. */
81
+ at: number;
82
+ /** How long the clip plays on the timeline, ms. */
83
+ duration: number;
84
+ /** Start offset within the clip, ms. */
85
+ seek: number;
86
+ /** Resolved clip URL (`currentSrc` || `src`). */
87
+ src: string;
88
+ /** Pre-extracted frame-set manifest storage key, if the app provided one. */
89
+ frameset?: string;
90
+ };
91
+
64
92
  declare global {
65
93
  interface Window {
66
- __mvFrames: { applyState(t: number): Promise<void> };
94
+ __mvFrames: {
95
+ applyState(t: number): Promise<void>;
96
+ /** Video slots in this timeline — read by the renderer engine to
97
+ * swap video frames out-of-band. Empty when no video. */
98
+ videos: VideoSlotInfo[];
99
+ };
100
+ /** Set true by the headless renderer when it captures (`__mvFramesRendererPresent`). */
67
101
  __mvFramesRendererPresent?: boolean;
102
+ /** Set true by the renderer ONLY on the begin-frame-control capture path,
103
+ * where the live `<video>` must not be seeked (the engine swaps in
104
+ * pre-extracted frame images instead). When unset — the screenshot capture
105
+ * path and the live editor/preview — `applyState` seeks the live video. */
106
+ __mvFramesNoVideoSeek?: boolean;
68
107
  }
69
108
  }
70
109
 
71
110
  type AnimSlot = { kind: "animation"; at: number; duration: number; anim: Animation };
72
- type VideoSlot = { kind: "video"; at: number; duration: number; seek: number; el: HTMLVideoElement };
111
+ type VideoSlot = {
112
+ kind: "video";
113
+ at: number;
114
+ duration: number;
115
+ seek: number;
116
+ el: HTMLVideoElement;
117
+ selector: string;
118
+ src: string;
119
+ frameset?: string;
120
+ };
73
121
  type CssPendingSlot = {
74
122
  kind: "css-pending";
75
123
  at: number;
@@ -141,6 +189,57 @@ export function stylesheetsReady(): Promise<void> {
141
189
  .then(() => (document.fonts ? document.fonts.ready.then(() => undefined) : undefined));
142
190
  }
143
191
 
192
+ /**
193
+ * Seek `el` to `targetSec` and resolve only once the seeked frame has
194
+ * actually decoded — so a subsequent capture grabs the right frame instead
195
+ * of racing an in-flight seek.
196
+ *
197
+ * Resolution waits for the `seeked` event, then for one decoded video frame
198
+ * via `requestVideoFrameCallback` where available (fallback: a microtask, so
199
+ * we still yield to the decode). A timeout guards against `seeked` never
200
+ * firing (e.g. seeking to the exact current position, or an unsupported
201
+ * codec) so `applyState` can't hang the whole render. Already-satisfied
202
+ * seeks (`readyState` high enough and time already at target) resolve fast.
203
+ */
204
+ function seekVideo(el: HTMLVideoElement, targetSec: number): Promise<void> {
205
+ const HAVE_CURRENT_DATA = 2;
206
+ // If we're already at (or within a frame of) the target with data ready,
207
+ // there's nothing to wait for — assigning currentTime won't fire `seeked`.
208
+ const alreadyThere =
209
+ Math.abs(el.currentTime - targetSec) < 1e-3 && el.readyState >= HAVE_CURRENT_DATA;
210
+ el.currentTime = targetSec;
211
+ if (alreadyThere) return Promise.resolve();
212
+
213
+ return new Promise<void>((resolve) => {
214
+ let done = false;
215
+ const finish = () => {
216
+ if (done) return;
217
+ done = true;
218
+ el.removeEventListener("seeked", onSeeked);
219
+ clearTimeout(timer);
220
+ resolve();
221
+ };
222
+ const afterSeeked = () => {
223
+ // Wait for one decoded frame to be presented when the API exists.
224
+ const rvfc = (
225
+ el as unknown as {
226
+ requestVideoFrameCallback?: (cb: () => void) => number;
227
+ }
228
+ ).requestVideoFrameCallback;
229
+ if (typeof rvfc === "function") {
230
+ rvfc.call(el, () => finish());
231
+ } else {
232
+ // No rVFC: yield a microtask so the decode can settle, then finish.
233
+ Promise.resolve().then(finish);
234
+ }
235
+ };
236
+ const onSeeked = () => afterSeeked();
237
+ el.addEventListener("seeked", onSeeked, { once: true });
238
+ // Guard: never let a missing `seeked` stall the render.
239
+ const timer = setTimeout(finish, 2000);
240
+ });
241
+ }
242
+
144
243
  function installTimeline(schema: TimelineSchema): void {
145
244
  const rendererPresent =
146
245
  typeof window !== "undefined" && window.__mvFramesRendererPresent === true;
@@ -157,8 +256,25 @@ function installTimeline(schema: TimelineSchema): void {
157
256
  const naturalMs = isFinite(el.duration) ? el.duration * 1000 : Infinity;
158
257
  const duration = i.duration ?? Math.min(naturalMs, schema.duration - i.at);
159
258
  el.pause();
160
- el.currentTime = seek / 1000;
161
- return [{ kind: "video", at: i.at, duration, seek, el }];
259
+ // In renderer mode the engine drives video by swapping in pre-extracted
260
+ // frame images; we must NOT seek the live <video> (seeking under
261
+ // begin-frame-control crashes headless Chromium). In browser preview the
262
+ // setTimeout scheduler below plays it normally.
263
+ if (!rendererPresent) {
264
+ el.currentTime = seek / 1000;
265
+ }
266
+ return [
267
+ {
268
+ kind: "video",
269
+ at: i.at,
270
+ duration,
271
+ seek,
272
+ el,
273
+ selector: i.selector,
274
+ src: el.currentSrc || el.src,
275
+ frameset: i.frameset,
276
+ },
277
+ ];
162
278
  }
163
279
 
164
280
  if (i.kind === "css") {
@@ -219,28 +335,47 @@ function installTimeline(schema: TimelineSchema): void {
219
335
  return [{ kind: "animation", at: i.at, duration, anim }];
220
336
  });
221
337
 
338
+ // Metadata for the renderer engine: which `<video>`s to pre-extract + swap.
339
+ const videos: VideoSlotInfo[] = slots
340
+ .filter((s): s is VideoSlot => s.kind === "video")
341
+ .map((s) => ({
342
+ selector: s.selector,
343
+ at: s.at,
344
+ duration: s.duration,
345
+ seek: s.seek,
346
+ src: s.src,
347
+ frameset: s.frameset,
348
+ }));
349
+
222
350
  window.__mvFrames = {
351
+ videos,
223
352
  async applyState(t: number) {
224
353
  const videoWaits: Promise<void>[] = [];
225
354
  for (const s of slots) {
226
355
  if (s.kind === "css-pending") continue; // only relevant in browser preview
227
- const local = clamp(t - s.at, 0, s.duration);
228
356
  if (s.kind === "video") {
229
- s.el.pause();
230
- const target = (s.seek + local) / 1000;
231
- // Seeking is async: the decoded frame for `target` is NOT ready the
232
- // instant we assign `currentTime`. The renderer captures each frame
233
- // with a synchronous CDP `beginFrame` right after `applyState`
234
- // resolves, so we MUST wait for the seek to land and the frame to
235
- // decode — otherwise we capture a stale/blank frame, or (under
236
- // deterministic `--enable-begin-frame-control`) race the media
237
- // pipeline and wedge/crash the headless tab.
238
- videoWaits.push(seekVideo(s.el, target));
239
- } else {
240
- s.anim.currentTime = local;
357
+ const local = clamp(t - s.at, 0, s.duration);
358
+ // Seek the live <video> EXCEPT on the renderer's begin-frame-control
359
+ // capture path (where seeking crashes the headless tab the engine
360
+ // swaps in pre-extracted frame images instead, flagged via
361
+ // `__mvFramesNoVideoSeek`). On every live-seek path (editor, live
362
+ // preview, AND the renderer's screenshot capture) we must AWAIT the
363
+ // seeked frame's decode before resolving — otherwise a capture races
364
+ // an in-flight seek and grabs a stale/blank frame (and the per-frame
365
+ // loop spins, hitting the render wall-clock budget). `seekVideo`
366
+ // guards with a timeout so a missing `seeked` can't hang the render.
367
+ if (!window.__mvFramesNoVideoSeek) {
368
+ videoWaits.push(seekVideo(s.el, (s.seek + local) / 1000));
369
+ }
370
+ continue;
241
371
  }
372
+ const local = clamp(t - s.at, 0, s.duration);
373
+ s.anim.currentTime = local;
242
374
  }
243
- await Promise.all([document.fonts.ready, ...videoWaits]);
375
+ await Promise.all([
376
+ document.fonts ? document.fonts.ready.then(() => undefined) : Promise.resolve(),
377
+ ...videoWaits,
378
+ ]);
244
379
  },
245
380
  };
246
381
 
@@ -280,52 +415,3 @@ function installTimeline(schema: TimelineSchema): void {
280
415
  function clamp(v: number, lo: number, hi: number): number {
281
416
  return v < lo ? lo : v > hi ? hi : v;
282
417
  }
283
-
284
- /**
285
- * Seek `el` to `targetSec` and resolve only once the seeked frame has
286
- * actually decoded — so a subsequent capture grabs the right frame instead
287
- * of racing an in-flight seek.
288
- *
289
- * Resolution waits for the `seeked` event, then for one decoded video frame
290
- * via `requestVideoFrameCallback` where available (fallback: a microtask, so
291
- * we still yield to the decode). A timeout guards against `seeked` never
292
- * firing (e.g. seeking to the exact current position, or an unsupported
293
- * codec) so `applyState` can't hang the whole render. Already-satisfied
294
- * seeks (`readyState` high enough and time already at target) resolve fast.
295
- */
296
- function seekVideo(el: HTMLVideoElement, targetSec: number): Promise<void> {
297
- const HAVE_CURRENT_DATA = 2;
298
- // If we're already at (or within a frame of) the target with data ready,
299
- // there's nothing to wait for — assigning currentTime won't fire `seeked`.
300
- const alreadyThere =
301
- Math.abs(el.currentTime - targetSec) < 1e-3 && el.readyState >= HAVE_CURRENT_DATA;
302
- el.currentTime = targetSec;
303
- if (alreadyThere) return Promise.resolve();
304
-
305
- return new Promise<void>((resolve) => {
306
- let done = false;
307
- const finish = () => {
308
- if (done) return;
309
- done = true;
310
- el.removeEventListener("seeked", onSeeked);
311
- clearTimeout(timer);
312
- resolve();
313
- };
314
- const afterSeeked = () => {
315
- // Wait for one decoded frame to be presented when the API exists.
316
- const rvfc = (el as unknown as {
317
- requestVideoFrameCallback?: (cb: () => void) => number;
318
- }).requestVideoFrameCallback;
319
- if (typeof rvfc === "function") {
320
- rvfc.call(el, () => finish());
321
- } else {
322
- // No rVFC: yield a microtask so the decode can settle, then finish.
323
- Promise.resolve().then(finish);
324
- }
325
- };
326
- const onSeeked = () => afterSeeked();
327
- el.addEventListener("seeked", onSeeked, { once: true });
328
- // Guard: never let a missing `seeked` stall the render.
329
- const timer = setTimeout(finish, 2000);
330
- });
331
- }