* Arm static-frame dedup for this render (default-on; opt out with HF_STATIC_DEDUP=false). * Runs at init in normal DOM state so the verification screenshots are valid. Predicts * the static set, anchor-verifies it (skip with HF_STATIC_DEDUP_VERIFY=false — unsafe), * and on success stores it on t
( session: CaptureSession, page: Page, logInitPhase: (phase: string) => void, )
| 1599 | * via HF_STATIC_DEDUP_SAMPLES (default 24). |
| 1600 | */ |
| 1601 | async function armStaticDedup( |
| 1602 | session: CaptureSession, |
| 1603 | page: Page, |
| 1604 | logInitPhase: (phase: string) => void, |
| 1605 | ): Promise<void> { |
| 1606 | // Default ON for everyone; opt out via HF_STATIC_DEDUP in {false,0,off} (resolved into |
| 1607 | // EngineConfig.staticFrameDedup by resolveConfig). Verification is the safety net at scale. |
| 1608 | // Default-on: only an explicit `staticFrameDedup === false` (resolved from |
| 1609 | // HF_STATIC_DEDUP) disables; a missing config leaves dedup enabled. |
| 1610 | session.staticDedupEnabled = session.config?.staticFrameDedup !== false; |
| 1611 | if (!session.staticDedupEnabled) return; |
| 1612 | // Conservative gates: dedup is verified against the plain screenshot path, so only arm |
| 1613 | // where the production capture matches what verification measures, and where reuse is |
| 1614 | // sound. Skip when: |
| 1615 | // - capture mode is not screenshot (BeginFrame advances the compositor clock per |
| 1616 | // frame; skipping beginFrame for static frames gaps the tick sequence, and the |
| 1617 | // verifier uses pageScreenshotCapture not beginFrameCapture — its proof wouldn't |
| 1618 | // transfer); |
| 1619 | // - a before-capture hook is set (per-frame video-frame injection — those frames are |
| 1620 | // NOT static even if the GSAP timeline is idle, and the injector is skipped on reuse); |
| 1621 | // - page-side compositing is active (shader transitions / drawElement composite paint |
| 1622 | // a frame the plain verification screenshot doesn't reproduce). |
| 1623 | if (session.captureMode !== "screenshot") { |
| 1624 | session.staticDedupSkipReason = "capture_mode"; |
| 1625 | logInitPhase( |
| 1626 | `static-frame dedup: disabled (capture mode ${session.captureMode}, not screenshot)`, |
| 1627 | ); |
| 1628 | return; |
| 1629 | } |
| 1630 | if (session.onBeforeCapture) { |
| 1631 | session.staticDedupSkipReason = "video_injection"; |
| 1632 | logInitPhase("static-frame dedup: disabled (before-capture hook / video injection active)"); |
| 1633 | return; |
| 1634 | } |
| 1635 | const pageComposite = await page |
| 1636 | .evaluate( |
| 1637 | () => |
| 1638 | typeof (window as unknown as { __hf_page_composite_prepare?: unknown }) |
| 1639 | .__hf_page_composite_prepare === "function", |
| 1640 | ) |
| 1641 | .catch(() => true); // fail CLOSED: if we can't determine, assume compositing → skip dedup |
| 1642 | if (pageComposite) { |
| 1643 | session.staticDedupSkipReason = "page_composite"; |
| 1644 | logInitPhase("static-frame dedup: disabled (page-side compositing active)"); |
| 1645 | return; |
| 1646 | } |
| 1647 | const fps = fpsToNumber(session.options.fps); |
| 1648 | const stats = await computeStaticFrameSet(page, fps); |
| 1649 | if (!stats.eligible || stats.staticFrameSet.size === 0) { |
| 1650 | session.staticDedupSkipReason = "ineligible"; |
| 1651 | logInitPhase(`static-frame dedup: disabled (${stats.reason})`); |
| 1652 | return; |
| 1653 | } |
| 1654 | const rawSamples = Number(process.env.HF_STATIC_DEDUP_SAMPLES ?? "24"); |
| 1655 | const samples = Number.isFinite(rawSamples) && rawSamples >= 1 ? rawSamples : 24; |
| 1656 | const verdict = |
| 1657 | process.env.HF_STATIC_DEDUP_VERIFY === "false" |
| 1658 | ? null |
no test coverage detected