@hyperframes/engine 0.8.86 → 0.8.88
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 +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/services/browserManager.d.ts +5 -0
- package/dist/services/browserManager.d.ts.map +1 -1
- package/dist/services/browserManager.js +9 -0
- package/dist/services/browserManager.js.map +1 -1
- package/dist/services/extractionCache.d.ts +2 -0
- package/dist/services/extractionCache.d.ts.map +1 -1
- package/dist/services/extractionCache.js +12 -7
- package/dist/services/extractionCache.js.map +1 -1
- package/dist/services/frameCapture.d.ts +4 -0
- package/dist/services/frameCapture.d.ts.map +1 -1
- package/dist/services/frameCapture.js +74 -68
- package/dist/services/frameCapture.js.map +1 -1
- package/dist/services/hdrCapture.d.ts.map +1 -1
- package/dist/services/hdrCapture.js +2 -0
- package/dist/services/hdrCapture.js.map +1 -1
- package/dist/services/parallelCoordinator.d.ts.map +1 -1
- package/dist/services/parallelCoordinator.js +11 -1
- package/dist/services/parallelCoordinator.js.map +1 -1
- package/dist/services/videoFrameExtractor.d.ts +2 -0
- package/dist/services/videoFrameExtractor.d.ts.map +1 -1
- package/dist/services/videoFrameExtractor.js +4 -1
- package/dist/services/videoFrameExtractor.js.map +1 -1
- package/dist/services/videoFrameInjector.d.ts.map +1 -1
- package/dist/services/videoFrameInjector.js +7 -8
- package/dist/services/videoFrameInjector.js.map +1 -1
- package/package.json +3 -3
|
@@ -366,9 +366,19 @@ export function prepareBeginFrameTimeline(session, state, warmupIntervalMs) {
|
|
|
366
366
|
},
|
|
367
367
|
};
|
|
368
368
|
}
|
|
369
|
+
/** Runs BeginFrame session setup; a failure stops the warm-up loop, which would otherwise tick forever. */
|
|
370
|
+
export async function cancelWarmupOnError(state, setup) {
|
|
371
|
+
try {
|
|
372
|
+
return await setup();
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
state.cancelled = true;
|
|
376
|
+
throw error;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
369
379
|
export async function driveWarmupTicks(options, state) {
|
|
370
380
|
const sleep = options.sleep ?? realSleep;
|
|
371
|
-
while (
|
|
381
|
+
while (!state.cancelled) {
|
|
372
382
|
if (options.lockWarmupTicks) {
|
|
373
383
|
// Locked mode exits on the iteration count, ignoring `state.running` —
|
|
374
384
|
// the caller flips `running=false` after page-readiness but we keep
|
|
@@ -1771,76 +1781,72 @@ export async function initializeSession(session) {
|
|
|
1771
1781
|
})();
|
|
1772
1782
|
warmupLoopPromise.catch(() => { });
|
|
1773
1783
|
logInitPhase("warmup loop started");
|
|
1774
|
-
await
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1784
|
+
await cancelWarmupOnError(warmupState, async () => {
|
|
1785
|
+
await gotoEntryPage();
|
|
1786
|
+
logInitPhase("page.goto complete");
|
|
1787
|
+
// Flush the GSAP proxy queue synchronously. In BeginFrame mode the rAF-based
|
|
1788
|
+
// batch drain runs on the warmup loop's 33ms ticks — for tween-heavy
|
|
1789
|
+
// compositions this is the dominant init cost. Flushing synchronously
|
|
1790
|
+
// eliminates the wait entirely.
|
|
1791
|
+
await page.evaluate(`window.__hfFlushSync?.()`);
|
|
1792
|
+
logInitPhase("GSAP proxy flush complete");
|
|
1793
|
+
// Poll for window.__hf readiness using manual evaluate loop (waitForFunction
|
|
1794
|
+
// uses rAF polling internally, which won't fire in beginFrame mode).
|
|
1795
|
+
const pageReadyTimeout = session.config?.playerReadyTimeout ?? DEFAULT_CONFIG.playerReadyTimeout;
|
|
1786
1796
|
await pollHfReady(page, pageReadyTimeout);
|
|
1787
1797
|
logInitPhase("pollHfReady complete");
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1798
|
+
session.subTimelineWaitOutcome = await pollSubCompositionTimelines(page, pageReadyTimeout, undefined, () => session.scriptLoadFailures, undefined, (ids) => {
|
|
1799
|
+
session.pendingTimelineIds = [...ids];
|
|
1800
|
+
});
|
|
1801
|
+
logInitPhase(`pollSubCompositionTimelines complete (${session.subTimelineWaitOutcome})`);
|
|
1802
|
+
recordSubTimelineWarning(session, pageReadyTimeout);
|
|
1803
|
+
await applyVideoMetadataHints(page, session.options.videoMetadataHints);
|
|
1804
|
+
logInitPhase("applyVideoMetadataHints complete");
|
|
1805
|
+
// Run independent readiness checks in parallel — videos, images, fonts,
|
|
1806
|
+
// and Tailwind don't depend on each other's completion.
|
|
1807
|
+
const bfSkipVideoIds = session.options.skipReadinessVideoIds ?? [];
|
|
1808
|
+
const [bfVideosReady] = await Promise.all([
|
|
1809
|
+
pollVideosReady(page, bfSkipVideoIds, pageReadyTimeout),
|
|
1810
|
+
pollImagesReady(page, pageReadyTimeout).then(async (ready) => {
|
|
1811
|
+
if (!ready) {
|
|
1812
|
+
const failedImages = await page.evaluate(() => {
|
|
1813
|
+
return Array.from(document.querySelectorAll("img"))
|
|
1814
|
+
.filter((img) => {
|
|
1815
|
+
const ie = img;
|
|
1816
|
+
const src = ie.getAttribute("src") || "";
|
|
1817
|
+
if (!src || src.startsWith("data:"))
|
|
1818
|
+
return false;
|
|
1819
|
+
return !(ie.complete && ie.naturalWidth > 0);
|
|
1820
|
+
})
|
|
1821
|
+
.map((img) => img.src || img.getAttribute("src") || "(no src)")
|
|
1822
|
+
.join(", ");
|
|
1823
|
+
});
|
|
1824
|
+
console.warn(`[FrameCapture] Some image elements did not load within ${pageReadyTimeout}ms: ${failedImages}. ` +
|
|
1825
|
+
`Continuing render — affected images may appear blank/missing in early frames.`);
|
|
1826
|
+
}
|
|
1827
|
+
await decodeAllImages(page);
|
|
1828
|
+
return ready;
|
|
1829
|
+
}),
|
|
1830
|
+
page.evaluate(`document.fonts?.ready`),
|
|
1831
|
+
waitForOptionalTailwindReady(page, pageReadyTimeout),
|
|
1832
|
+
]);
|
|
1833
|
+
logInitPhase("media + fonts + tailwind ready");
|
|
1834
|
+
if (!bfVideosReady) {
|
|
1835
|
+
const failedVideos = await page.evaluate((skipIdList) => {
|
|
1836
|
+
const skip = new Set(skipIdList);
|
|
1837
|
+
return Array.from(document.querySelectorAll("video"))
|
|
1838
|
+
.filter((v) => !skip.has(v.id))
|
|
1839
|
+
.filter((v) => v.readyState < 2 && !v.error)
|
|
1840
|
+
.map((v) => v.src || v.getAttribute("src") || "(no src)")
|
|
1841
|
+
.join(", ");
|
|
1842
|
+
}, bfSkipVideoIds);
|
|
1843
|
+
console.warn(`[FrameCapture] Some video elements did not decode within ${pageReadyTimeout}ms: ${failedVideos}. ` +
|
|
1844
|
+
`Continuing render — affected videos will appear as blank/black frames.`);
|
|
1845
|
+
}
|
|
1846
|
+
recordCaptureWarnings(session, await collectMediaReadinessWarnings(page, bfSkipVideoIds, pageReadyTimeout));
|
|
1847
|
+
await recordLiveMapWarning(session, page);
|
|
1848
|
+
await recordSessionInitTelemetry(session, initStart);
|
|
1795
1849
|
});
|
|
1796
|
-
logInitPhase(`pollSubCompositionTimelines complete (${session.subTimelineWaitOutcome})`);
|
|
1797
|
-
recordSubTimelineWarning(session, pageReadyTimeout);
|
|
1798
|
-
await applyVideoMetadataHints(page, session.options.videoMetadataHints);
|
|
1799
|
-
logInitPhase("applyVideoMetadataHints complete");
|
|
1800
|
-
// Run independent readiness checks in parallel — videos, images, fonts,
|
|
1801
|
-
// and Tailwind don't depend on each other's completion.
|
|
1802
|
-
const bfSkipVideoIds = session.options.skipReadinessVideoIds ?? [];
|
|
1803
|
-
const [bfVideosReady] = await Promise.all([
|
|
1804
|
-
pollVideosReady(page, bfSkipVideoIds, pageReadyTimeout),
|
|
1805
|
-
pollImagesReady(page, pageReadyTimeout).then(async (ready) => {
|
|
1806
|
-
if (!ready) {
|
|
1807
|
-
const failedImages = await page.evaluate(() => {
|
|
1808
|
-
return Array.from(document.querySelectorAll("img"))
|
|
1809
|
-
.filter((img) => {
|
|
1810
|
-
const ie = img;
|
|
1811
|
-
const src = ie.getAttribute("src") || "";
|
|
1812
|
-
if (!src || src.startsWith("data:"))
|
|
1813
|
-
return false;
|
|
1814
|
-
return !(ie.complete && ie.naturalWidth > 0);
|
|
1815
|
-
})
|
|
1816
|
-
.map((img) => img.src || img.getAttribute("src") || "(no src)")
|
|
1817
|
-
.join(", ");
|
|
1818
|
-
});
|
|
1819
|
-
console.warn(`[FrameCapture] Some image elements did not load within ${pageReadyTimeout}ms: ${failedImages}. ` +
|
|
1820
|
-
`Continuing render — affected images may appear blank/missing in early frames.`);
|
|
1821
|
-
}
|
|
1822
|
-
await decodeAllImages(page);
|
|
1823
|
-
return ready;
|
|
1824
|
-
}),
|
|
1825
|
-
page.evaluate(`document.fonts?.ready`),
|
|
1826
|
-
waitForOptionalTailwindReady(page, pageReadyTimeout),
|
|
1827
|
-
]);
|
|
1828
|
-
logInitPhase("media + fonts + tailwind ready");
|
|
1829
|
-
if (!bfVideosReady) {
|
|
1830
|
-
const failedVideos = await page.evaluate((skipIdList) => {
|
|
1831
|
-
const skip = new Set(skipIdList);
|
|
1832
|
-
return Array.from(document.querySelectorAll("video"))
|
|
1833
|
-
.filter((v) => !skip.has(v.id))
|
|
1834
|
-
.filter((v) => v.readyState < 2 && !v.error)
|
|
1835
|
-
.map((v) => v.src || v.getAttribute("src") || "(no src)")
|
|
1836
|
-
.join(", ");
|
|
1837
|
-
}, bfSkipVideoIds);
|
|
1838
|
-
console.warn(`[FrameCapture] Some video elements did not decode within ${pageReadyTimeout}ms: ${failedVideos}. ` +
|
|
1839
|
-
`Continuing render — affected videos will appear as blank/black frames.`);
|
|
1840
|
-
}
|
|
1841
|
-
recordCaptureWarnings(session, await collectMediaReadinessWarnings(page, bfSkipVideoIds, pageReadyTimeout));
|
|
1842
|
-
await recordLiveMapWarning(session, page);
|
|
1843
|
-
await recordSessionInitTelemetry(session, initStart);
|
|
1844
1850
|
// Stop warmup, then drain the loop in BOTH modes before any further
|
|
1845
1851
|
// BeginFrame on this session (drawElement init, the render-frame commit tick
|
|
1846
1852
|
// at the end of init, and frame 0). Clearing the flag only stops new
|