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 +58 -9
- package/dist/skills/gsap/SKILL.md +30 -1
- package/dist/templates/_shared/CLAUDE.md +5 -0
- package/package.json +1 -1
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.
|
|
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
|
|
35589
|
+
const buildCaptureOptions = () => ({
|
|
35542
35590
|
...captureOptions,
|
|
35543
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
|
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`.
|