hyperframes 0.4.39 → 0.4.40

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/cli.js CHANGED
@@ -54,7 +54,7 @@ var VERSION;
54
54
  var init_version = __esm({
55
55
  "src/version.ts"() {
56
56
  "use strict";
57
- VERSION = true ? "0.4.39" : "0.0.0-dev";
57
+ VERSION = true ? "0.4.40" : "0.0.0-dev";
58
58
  }
59
59
  });
60
60
 
@@ -26182,6 +26182,27 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
26182
26182
  }
26183
26183
  return Boolean(await page.evaluate(expression));
26184
26184
  }
26185
+ async function applyVideoMetadataHints(page, hints) {
26186
+ if (!hints || hints.length === 0) return;
26187
+ await page.evaluate(
26188
+ (metadataHints) => {
26189
+ for (const hint of metadataHints) {
26190
+ if (!hint.id || !Number.isFinite(hint.width) || !Number.isFinite(hint.height) || hint.width <= 0 || hint.height <= 0) {
26191
+ continue;
26192
+ }
26193
+ const video = document.getElementById(hint.id);
26194
+ if (!video) continue;
26195
+ if (!video.hasAttribute("width")) video.setAttribute("width", String(hint.width));
26196
+ if (!video.hasAttribute("height")) video.setAttribute("height", String(hint.height));
26197
+ const computed = window.getComputedStyle(video);
26198
+ if (!video.style.aspectRatio && (!computed.aspectRatio || computed.aspectRatio === "auto")) {
26199
+ video.style.aspectRatio = `${hint.width} / ${hint.height}`;
26200
+ }
26201
+ }
26202
+ },
26203
+ [...hints]
26204
+ );
26205
+ }
26185
26206
  async function initializeSession(session) {
26186
26207
  const { page, serverUrl } = session;
26187
26208
  page.on("console", (msg) => {
@@ -26225,6 +26246,7 @@ async function initializeSession(session) {
26225
26246
  `[FrameCapture] window.__hf not ready after ${pageReadyTimeout2}ms. Page must expose window.__hf = { duration, seek }.`
26226
26247
  );
26227
26248
  }
26249
+ await applyVideoMetadataHints(page, session.options.videoMetadataHints);
26228
26250
  const skipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
26229
26251
  const videosReady = await pollPageExpression(
26230
26252
  page,
@@ -26291,6 +26313,7 @@ async function initializeSession(session) {
26291
26313
  `[FrameCapture] window.__hf not ready after ${pageReadyTimeout}ms. Page must expose window.__hf = { duration, seek }.`
26292
26314
  );
26293
26315
  }
26316
+ await applyVideoMetadataHints(page, session.options.videoMetadataHints);
26294
26317
  const beginframeSkipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
26295
26318
  const videoDeadline = Date.now() + (session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout);
26296
26319
  while (Date.now() < videoDeadline) {
@@ -34108,6 +34131,24 @@ function applyRenderModeHints(cfg, compiled, log2 = defaultLogger) {
34108
34131
  reasons: compiled.renderModeHints.reasons.map((reason) => reason.message)
34109
34132
  });
34110
34133
  }
34134
+ function collectVideoReadinessSkipIds(nativeHdrVideoIds, extractedVideos) {
34135
+ return Array.from(
34136
+ /* @__PURE__ */ new Set([
34137
+ ...nativeHdrVideoIds,
34138
+ ...extractedVideos.filter((video) => hasUsableVideoDimensions(video.metadata)).map((video) => video.videoId)
34139
+ ])
34140
+ ).sort();
34141
+ }
34142
+ function hasUsableVideoDimensions(metadata) {
34143
+ return Number.isFinite(metadata.width) && Number.isFinite(metadata.height) && metadata.width > 0 && metadata.height > 0;
34144
+ }
34145
+ function collectVideoMetadataHints(extractedVideos) {
34146
+ return extractedVideos.filter((video) => hasUsableVideoDimensions(video.metadata)).map((video) => ({
34147
+ id: video.videoId,
34148
+ width: video.metadata.width,
34149
+ height: video.metadata.height
34150
+ })).sort((a, b) => a.id.localeCompare(b.id));
34151
+ }
34111
34152
  function resolveRenderWorkerCount(totalFrames, requestedWorkers, cfg, compiled, composition, log2 = defaultLogger, measuredCaptureCost) {
34112
34153
  const captureCost = combineCaptureCostEstimates(
34113
34154
  estimateCaptureCostMultiplier(compiled, composition),
@@ -35119,6 +35160,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35119
35160
  let frameLookup = null;
35120
35161
  const compiledDir = join35(workDir, "compiled");
35121
35162
  let extractionResult = null;
35163
+ let videoReadinessSkipIds = [];
35164
+ let videoMetadataHints = [];
35122
35165
  const nativeHdrVideoIds = /* @__PURE__ */ new Set();
35123
35166
  const videoTransfers = /* @__PURE__ */ new Map();
35124
35167
  if (job.config.hdrMode !== "force-sdr" && composition.videos.length > 0) {
@@ -35175,6 +35218,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35175
35218
  if (extractionResult.extracted.length > 0) {
35176
35219
  frameLookup = createFrameLookupTable(composition.videos, extractionResult.extracted);
35177
35220
  }
35221
+ videoReadinessSkipIds = collectVideoReadinessSkipIds(
35222
+ nativeHdrVideoIds,
35223
+ extractionResult.extracted
35224
+ );
35225
+ videoMetadataHints = collectVideoMetadataHints(extractionResult.extracted);
35178
35226
  perfStages.videoExtractMs = Date.now() - stage2Start;
35179
35227
  const existingAudioSrcs = new Set(composition.audios.map((a) => a.src));
35180
35228
  for (const ext of extractionResult.extracted) {
@@ -35288,9 +35336,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35288
35336
  format: needsAlpha ? "png" : "jpeg",
35289
35337
  quality: needsAlpha ? void 0 : job.config.quality === "draft" ? 80 : 95
35290
35338
  };
35291
- const buildHdrCaptureOptions = () => ({
35339
+ const buildCaptureOptions = () => ({
35292
35340
  ...captureOptions,
35293
- skipReadinessVideoIds: Array.from(nativeHdrVideoIds)
35341
+ videoMetadataHints,
35342
+ skipReadinessVideoIds: videoReadinessSkipIds
35294
35343
  });
35295
35344
  let captureCalibration;
35296
35345
  let switchedToScreenshotAfterCalibration = false;
@@ -35303,7 +35352,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35303
35352
  calibrationSession = await createCaptureSession(
35304
35353
  fileServer.url,
35305
35354
  calibrationDir,
35306
- buildHdrCaptureOptions(),
35355
+ buildCaptureOptions(),
35307
35356
  videoInjector,
35308
35357
  calibrationCfg
35309
35358
  );
@@ -35427,7 +35476,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35427
35476
  const domSession = await createCaptureSession(
35428
35477
  fileServer.url,
35429
35478
  framesDir,
35430
- buildHdrCaptureOptions(),
35479
+ buildCaptureOptions(),
35431
35480
  createVideoFrameInjector(frameLookup),
35432
35481
  cfg
35433
35482
  );
@@ -35960,7 +36009,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35960
36009
  fileServer.url,
35961
36010
  workDir,
35962
36011
  tasks,
35963
- buildHdrCaptureOptions(),
36012
+ buildCaptureOptions(),
35964
36013
  () => createVideoFrameInjector(frameLookup),
35965
36014
  abortSignal,
35966
36015
  (progress) => {
@@ -35990,7 +36039,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35990
36039
  const session = probeSession ?? await createCaptureSession(
35991
36040
  fileServer.url,
35992
36041
  framesDir,
35993
- buildHdrCaptureOptions(),
36042
+ buildCaptureOptions(),
35994
36043
  videoInjector,
35995
36044
  cfg
35996
36045
  );
@@ -36045,7 +36094,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
36045
36094
  initialWorkerCount: workerCount,
36046
36095
  allowRetry: job.config.workers === void 0,
36047
36096
  frameExt: needsAlpha ? "png" : "jpg",
36048
- captureOptions: buildHdrCaptureOptions(),
36097
+ captureOptions: buildCaptureOptions(),
36049
36098
  createBeforeCaptureHook: () => createVideoFrameInjector(frameLookup),
36050
36099
  abortSignal,
36051
36100
  onProgress: (progress) => {
@@ -36080,7 +36129,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
36080
36129
  const session = probeSession ?? await createCaptureSession(
36081
36130
  fileServer.url,
36082
36131
  framesDir,
36083
- buildHdrCaptureOptions(),
36132
+ buildCaptureOptions(),
36084
36133
  videoInjector,
36085
36134
  cfg
36086
36135
  );
@@ -5,6 +5,28 @@ description: GSAP animation reference for HyperFrames. Covers gsap.to(), from(),
5
5
 
6
6
  # GSAP
7
7
 
8
+ ## HyperFrames Contract
9
+
10
+ HyperFrames controls GSAP through its `gsap` runtime adapter. Create a paused timeline synchronously, register it on `window.__timelines` with the exact `data-composition-id`, and let HyperFrames seek it.
11
+
12
+ ```html
13
+ <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
14
+ <script>
15
+ window.__timelines = window.__timelines || {};
16
+ const tl = gsap.timeline({ paused: true });
17
+
18
+ tl.from(".title", { y: 48, opacity: 0, duration: 0.6, ease: "power3.out" }, 0);
19
+ tl.to(".accent", { scaleX: 1, duration: 0.5, ease: "power2.out" }, 0.25);
20
+
21
+ window.__timelines["main"] = tl; // key must equal data-composition-id on the composition root
22
+ </script>
23
+ ```
24
+
25
+ - The registry key must match the composition root's `data-composition-id`.
26
+ - Do not call `tl.play()` for render-critical motion.
27
+ - Do not build timelines inside async code, timers, or event handlers.
28
+ - Keep loops finite. HyperFrames renders finite video durations.
29
+
8
30
  ## Core Tween Methods
9
31
 
10
32
  - **gsap.to(targets, vars)** — animate from current state to `vars`. Most common.
@@ -21,7 +43,7 @@ Always use **camelCase** property names (e.g. `backgroundColor`, `rotationX`).
21
43
  - **ease** — `"power1.out"` (default), `"power3.inOut"`, `"back.out(1.7)"`, `"elastic.out(1, 0.3)"`, `"none"`.
22
44
  - **stagger** — number `0.1` or object: `{ amount: 0.3, from: "center" }`, `{ each: 0.1, from: "random" }`.
23
45
  - **overwrite** — `false` (default), `true`, or `"auto"`.
24
- - **repeat** — number or `-1` for infinite. **yoyo** — alternates direction with repeat.
46
+ - **repeat** — finite number; never `-1` in HyperFrames. Compute repeats from the visible duration. **yoyo** — alternates direction with repeat.
25
47
  - **onComplete**, **onStart**, **onUpdate** — callbacks.
26
48
  - **immediateRender** — default `true` for from()/fromTo(). Set `false` on later tweens targeting the same property+element to avoid overwrite.
27
49
 
@@ -209,3 +231,10 @@ Pause or kill off-screen animations.
209
231
  - Chain animations with delay when a timeline can sequence them.
210
232
  - Create tweens before the DOM exists.
211
233
  - Skip cleanup — always kill tweens when no longer needed.
234
+ - Use infinite repeat values in HyperFrames compositions. Use finite repeat counts computed from the visible duration.
235
+
236
+ ## Credits And References
237
+
238
+ - HyperFrames adapter source: `packages/core/src/runtime/adapters/gsap.ts`.
239
+ - GSAP documentation: https://gsap.com/docs/v3/
240
+ - GSAP timeline pause and seek behavior: https://gsap.com/docs/v3/GSAP/Timeline/pause%28%29/
@@ -11,6 +11,11 @@
11
11
  | **hyperframes-registry** | `/hyperframes-registry` | Installing blocks and components via `hyperframes add` |
12
12
  | **website-to-hyperframes** | `/website-to-hyperframes` | Capturing a URL and turning it into a video — full website-to-video pipeline |
13
13
  | **gsap** | `/gsap` | GSAP animations for HyperFrames — tweens, timelines, easing, performance |
14
+ | **animejs** | `/animejs` | Anime.js animations registered on `window.__hfAnime` |
15
+ | **css-animations** | `/css-animations` | CSS keyframes that HyperFrames can pause and seek |
16
+ | **lottie** | `/lottie` | `lottie-web` and dotLottie players registered on `window.__hfLottie` |
17
+ | **three** | `/three` | Three.js scenes rendered from HyperFrames `hf-seek` events |
18
+ | **waapi** | `/waapi` | Web Animations API motion driven through `document.getAnimations()` |
14
19
 
15
20
  > **Skills not available?** Ask the user to run `npx hyperframes skills` and restart their
16
21
  > agent session, or install manually: `npx skills add heygen-com/hyperframes`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperframes",
3
- "version": "0.4.39",
3
+ "version": "0.4.40",
4
4
  "description": "HyperFrames CLI — create, preview, and render HTML video compositions",
5
5
  "repository": {
6
6
  "type": "git",