hyperframes 0.5.0-alpha.12 → 0.5.0-alpha.13

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.5.0-alpha.12" : "0.0.0-dev";
57
+ VERSION = true ? "0.5.0-alpha.13" : "0.0.0-dev";
58
58
  }
59
59
  });
60
60
 
@@ -26423,6 +26423,27 @@ async function pollPageExpression(page, expression, timeoutMs, intervalMs = 100)
26423
26423
  }
26424
26424
  return Boolean(await page.evaluate(expression));
26425
26425
  }
26426
+ async function applyVideoMetadataHints(page, hints) {
26427
+ if (!hints || hints.length === 0) return;
26428
+ await page.evaluate(
26429
+ (metadataHints) => {
26430
+ for (const hint of metadataHints) {
26431
+ if (!hint.id || !Number.isFinite(hint.width) || !Number.isFinite(hint.height) || hint.width <= 0 || hint.height <= 0) {
26432
+ continue;
26433
+ }
26434
+ const video = document.getElementById(hint.id);
26435
+ if (!video) continue;
26436
+ if (!video.hasAttribute("width")) video.setAttribute("width", String(hint.width));
26437
+ if (!video.hasAttribute("height")) video.setAttribute("height", String(hint.height));
26438
+ const computed = window.getComputedStyle(video);
26439
+ if (!video.style.aspectRatio && (!computed.aspectRatio || computed.aspectRatio === "auto")) {
26440
+ video.style.aspectRatio = `${hint.width} / ${hint.height}`;
26441
+ }
26442
+ }
26443
+ },
26444
+ [...hints]
26445
+ );
26446
+ }
26426
26447
  async function initializeSession(session) {
26427
26448
  const { page, serverUrl } = session;
26428
26449
  page.on("console", (msg) => {
@@ -26466,6 +26487,7 @@ async function initializeSession(session) {
26466
26487
  `[FrameCapture] window.__hf not ready after ${pageReadyTimeout2}ms. Page must expose window.__hf = { duration, seek }.`
26467
26488
  );
26468
26489
  }
26490
+ await applyVideoMetadataHints(page, session.options.videoMetadataHints);
26469
26491
  const skipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
26470
26492
  const videosReady = await pollPageExpression(
26471
26493
  page,
@@ -26532,6 +26554,7 @@ async function initializeSession(session) {
26532
26554
  `[FrameCapture] window.__hf not ready after ${pageReadyTimeout}ms. Page must expose window.__hf = { duration, seek }.`
26533
26555
  );
26534
26556
  }
26557
+ await applyVideoMetadataHints(page, session.options.videoMetadataHints);
26535
26558
  const beginframeSkipIdsLiteral = JSON.stringify(session.options.skipReadinessVideoIds ?? []);
26536
26559
  const videoDeadline = Date.now() + (session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout);
26537
26560
  while (Date.now() < videoDeadline) {
@@ -34358,6 +34381,24 @@ function applyRenderModeHints(cfg, compiled, log2 = defaultLogger) {
34358
34381
  reasons: compiled.renderModeHints.reasons.map((reason) => reason.message)
34359
34382
  });
34360
34383
  }
34384
+ function collectVideoReadinessSkipIds(nativeHdrVideoIds, extractedVideos) {
34385
+ return Array.from(
34386
+ /* @__PURE__ */ new Set([
34387
+ ...nativeHdrVideoIds,
34388
+ ...extractedVideos.filter((video) => hasUsableVideoDimensions(video.metadata)).map((video) => video.videoId)
34389
+ ])
34390
+ ).sort();
34391
+ }
34392
+ function hasUsableVideoDimensions(metadata) {
34393
+ return Number.isFinite(metadata.width) && Number.isFinite(metadata.height) && metadata.width > 0 && metadata.height > 0;
34394
+ }
34395
+ function collectVideoMetadataHints(extractedVideos) {
34396
+ return extractedVideos.filter((video) => hasUsableVideoDimensions(video.metadata)).map((video) => ({
34397
+ id: video.videoId,
34398
+ width: video.metadata.width,
34399
+ height: video.metadata.height
34400
+ })).sort((a, b) => a.id.localeCompare(b.id));
34401
+ }
34361
34402
  function resolveRenderWorkerCount(totalFrames, requestedWorkers, cfg, compiled, composition, log2 = defaultLogger, measuredCaptureCost) {
34362
34403
  const captureCost = combineCaptureCostEstimates(
34363
34404
  estimateCaptureCostMultiplier(compiled, composition),
@@ -35369,6 +35410,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35369
35410
  let frameLookup = null;
35370
35411
  const compiledDir = join36(workDir, "compiled");
35371
35412
  let extractionResult = null;
35413
+ let videoReadinessSkipIds = [];
35414
+ let videoMetadataHints = [];
35372
35415
  const nativeHdrVideoIds = /* @__PURE__ */ new Set();
35373
35416
  const videoTransfers = /* @__PURE__ */ new Map();
35374
35417
  if (job.config.hdrMode !== "force-sdr" && composition.videos.length > 0) {
@@ -35425,6 +35468,11 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35425
35468
  if (extractionResult.extracted.length > 0) {
35426
35469
  frameLookup = createFrameLookupTable(composition.videos, extractionResult.extracted);
35427
35470
  }
35471
+ videoReadinessSkipIds = collectVideoReadinessSkipIds(
35472
+ nativeHdrVideoIds,
35473
+ extractionResult.extracted
35474
+ );
35475
+ videoMetadataHints = collectVideoMetadataHints(extractionResult.extracted);
35428
35476
  perfStages.videoExtractMs = Date.now() - stage2Start;
35429
35477
  const existingAudioSrcs = new Set(composition.audios.map((a) => a.src));
35430
35478
  for (const ext of extractionResult.extracted) {
@@ -35538,9 +35586,10 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35538
35586
  format: needsAlpha ? "png" : "jpeg",
35539
35587
  quality: needsAlpha ? void 0 : job.config.quality === "draft" ? 80 : 95
35540
35588
  };
35541
- const buildHdrCaptureOptions = () => ({
35589
+ const buildCaptureOptions = () => ({
35542
35590
  ...captureOptions,
35543
- skipReadinessVideoIds: Array.from(nativeHdrVideoIds)
35591
+ videoMetadataHints,
35592
+ skipReadinessVideoIds: videoReadinessSkipIds
35544
35593
  });
35545
35594
  let captureCalibration;
35546
35595
  let switchedToScreenshotAfterCalibration = false;
@@ -35553,7 +35602,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35553
35602
  calibrationSession = await createCaptureSession(
35554
35603
  fileServer.url,
35555
35604
  calibrationDir,
35556
- buildHdrCaptureOptions(),
35605
+ buildCaptureOptions(),
35557
35606
  videoInjector,
35558
35607
  calibrationCfg
35559
35608
  );
@@ -35677,7 +35726,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
35677
35726
  const domSession = await createCaptureSession(
35678
35727
  fileServer.url,
35679
35728
  framesDir,
35680
- buildHdrCaptureOptions(),
35729
+ buildCaptureOptions(),
35681
35730
  createVideoFrameInjector(frameLookup),
35682
35731
  cfg
35683
35732
  );
@@ -36210,7 +36259,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
36210
36259
  fileServer.url,
36211
36260
  workDir,
36212
36261
  tasks,
36213
- buildHdrCaptureOptions(),
36262
+ buildCaptureOptions(),
36214
36263
  () => createVideoFrameInjector(frameLookup),
36215
36264
  abortSignal,
36216
36265
  (progress) => {
@@ -36240,7 +36289,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
36240
36289
  const session = probeSession ?? await createCaptureSession(
36241
36290
  fileServer.url,
36242
36291
  framesDir,
36243
- buildHdrCaptureOptions(),
36292
+ buildCaptureOptions(),
36244
36293
  videoInjector,
36245
36294
  cfg
36246
36295
  );
@@ -36295,7 +36344,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
36295
36344
  initialWorkerCount: workerCount,
36296
36345
  allowRetry: job.config.workers === void 0,
36297
36346
  frameExt: needsAlpha ? "png" : "jpg",
36298
- captureOptions: buildHdrCaptureOptions(),
36347
+ captureOptions: buildCaptureOptions(),
36299
36348
  createBeforeCaptureHook: () => createVideoFrameInjector(frameLookup),
36300
36349
  abortSignal,
36301
36350
  onProgress: (progress) => {
@@ -36330,7 +36379,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
36330
36379
  const session = probeSession ?? await createCaptureSession(
36331
36380
  fileServer.url,
36332
36381
  framesDir,
36333
- buildHdrCaptureOptions(),
36382
+ buildCaptureOptions(),
36334
36383
  videoInjector,
36335
36384
  cfg
36336
36385
  );
@@ -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.5.0-alpha.12",
3
+ "version": "0.5.0-alpha.13",
4
4
  "description": "HyperFrames CLI — create, preview, and render HTML video compositions",
5
5
  "repository": {
6
6
  "type": "git",