diff --git a/packages/engine/src/services/frameCapture.ts b/packages/engine/src/services/frameCapture.ts index 011660056f..9e464dc80b 100644 --- a/packages/engine/src/services/frameCapture.ts +++ b/packages/engine/src/services/frameCapture.ts @@ -963,6 +963,13 @@ export async function initializeSession(session: CaptureSession): Promise await gotoEntryPage(); logInitPhase("page.goto complete"); + // Flush the GSAP proxy queue synchronously instead of waiting for + // rAF-based batch ticks (100 ops/tick at ~16ms). In headless mode there's + // no UI responsiveness concern, so draining instantly eliminates the + // largest init-time cost for tween-heavy compositions. + await page.evaluate(`window.__hfFlushSync?.()`); + logInitPhase("GSAP proxy flush complete"); + const pageReadyTimeout = session.config?.playerReadyTimeout ?? DEFAULT_CONFIG.playerReadyTimeout; await pollHfReady(page, pageReadyTimeout); @@ -974,24 +981,37 @@ export async function initializeSession(session: CaptureSession): Promise await applyVideoMetadataHints(page, session.options.videoMetadataHints); logInitPhase("applyVideoMetadataHints complete"); - // Wait for all video elements to have decoded their CURRENT frame, not - // just metadata. readyState >= 2 (HAVE_CURRENT_DATA) means a frame is - // actually rasterized and ready to paint — at >= 1 (HAVE_METADATA) we - // only know the dimensions, and the first