@@ -77,7 +77,7 @@ const ERRORS = {
7777// the different capture modes
7878const CAPTURE_MODES = [ "CANVAS" , "VIEWPORT" ]
7979// the list of accepted trigger modes
80- const TRIGGER_MODES = [ "DELAY" , "FN_TRIGGER" , "FN_TRIGGER_GIF" ]
80+ const TRIGGER_MODES = [ "DELAY" , "FN_TRIGGER" ]
8181
8282//
8383// UTILITY FUNCTIONS
@@ -94,7 +94,7 @@ function isUrlValid(url) {
9494}
9595
9696// is a trigger valid ? looks at the trigger mode and trigger settings
97- function isTriggerValid ( triggerMode , delay , playbackFps ) {
97+ function isTriggerValid ( triggerMode , delay ) {
9898 if ( ! TRIGGER_MODES . includes ( triggerMode ) ) {
9999 return false
100100 }
@@ -106,15 +106,8 @@ function isTriggerValid(triggerMode, delay, playbackFps) {
106106 delay >= DELAY_MIN &&
107107 delay <= DELAY_MAX
108108 )
109- } else if ( triggerMode === "FN_TRIGGER_GIF" ) {
110- return (
111- typeof playbackFps !== undefined &&
112- ! isNaN ( playbackFps ) &&
113- playbackFps >= GIF_DEFAULTS . MIN_FPS &&
114- playbackFps <= GIF_DEFAULTS . MAX_FPS
115- )
116109 } else if ( triggerMode === "FN_TRIGGER" ) {
117- // fn trigger and fn trigger gif don 't need any params
110+ // fn trigger doesn 't need any param
118111 return true
119112 }
120113}
@@ -330,7 +323,6 @@ const resizeCanvas = async (image, resX, resY) => {
330323}
331324const performCapture = async (
332325 mode ,
333- triggerMode ,
334326 page ,
335327 canvasSelector ,
336328 resX ,
@@ -345,22 +337,14 @@ const performCapture = async (
345337 // if viewport mode, use the native puppeteer page.screenshot
346338 if ( mode === "VIEWPORT" ) {
347339 // we simply take a capture of the viewport
348- return captureViewport (
349- page ,
350- triggerMode ,
351- gif ,
352- frameCount ,
353- captureInterval ,
354- playbackFps
355- )
340+ return captureViewport ( page , gif , frameCount , captureInterval , playbackFps )
356341 }
357342 // if the mode is canvas, we need to execute som JS on the client to select
358343 // the canvas and generate a dataURL to bridge it in here
359344 else if ( mode === "CANVAS" ) {
360345 const canvas = await captureCanvas (
361346 page ,
362347 canvasSelector ,
363- triggerMode ,
364348 gif ,
365349 frameCount ,
366350 captureInterval ,
@@ -435,7 +419,7 @@ const validateParams = ({
435419 if ( ! url || ! mode ) throw ERRORS . MISSING_PARAMETERS
436420 if ( ! isUrlValid ( url ) ) throw ERRORS . UNSUPPORTED_URL
437421 if ( ! CAPTURE_MODES . includes ( mode ) ) throw ERRORS . INVALID_PARAMETERS
438- if ( ! isTriggerValid ( triggerMode , delay , playbackFps ) )
422+ if ( ! isTriggerValid ( triggerMode , delay ) )
439423 throw ERRORS . INVALID_TRIGGER_PARAMETERS
440424
441425 if ( gif && ! validateGifParams ( frameCount , captureInterval , playbackFps ) )
@@ -472,21 +456,29 @@ const validateParams = ({
472456 }
473457}
474458
475- async function captureFramesWithTiming (
476- captureFrameFunction ,
459+ async function captureViewport (
460+ page ,
461+ isGif ,
477462 frameCount ,
478- captureInterval
463+ captureInterval ,
464+ playbackFps
479465) {
466+ if ( ! isGif ) {
467+ return await page . screenshot ( )
468+ }
469+
480470 const frames = [ ]
481471 let lastCaptureStart = performance . now ( )
482472
483473 for ( let i = 0 ; i < frameCount ; i ++ ) {
484474 // Record start time of screenshot operation
485475 const captureStart = performance . now ( )
486476
487- // Use the provided capture function to get the frame
488- const frame = await captureFrameFunction ( )
489- frames . push ( frame )
477+ // Capture raw pixels
478+ const frameBuffer = await page . screenshot ( {
479+ encoding : "binary" ,
480+ } )
481+ frames . push ( frameBuffer )
490482
491483 // Calculate how long the capture took
492484 const captureDuration = performance . now ( ) - captureStart
@@ -510,88 +502,6 @@ async function captureFramesWithTiming(
510502 lastCaptureStart = performance . now ( )
511503 }
512504
513- return frames
514- }
515-
516- async function captureFramesProgrammatically ( page , captureFrameFunction ) {
517- const frames = [ ]
518-
519- page . on ( "console" , msg => {
520- console . log ( "BROWSER:" , msg . text ( ) )
521- } )
522-
523- // set up the event listener and capture loop
524- await page . exposeFunction ( "captureFrame" , async ( ) => {
525- const frame = await captureFrameFunction ( )
526- frames . push ( frame )
527- console . log ( `programmatic frame ${ frames . length } captured` )
528- return frames . length
529- } )
530-
531- // wait for events in browser context
532- await page . evaluate (
533- function ( maxFrames , delayMax ) {
534- return new Promise ( function ( resolve ) {
535- const handleFrameCapture = async event => {
536- const frameCount = await window . captureFrame ( )
537-
538- console . log ( JSON . stringify ( event ) )
539- console . log ( JSON . stringify ( { frameCount, maxFrames } ) )
540- console . log (
541- JSON . stringify ( { isLastFrame : event . detail ?. isLastFrame } )
542- )
543- if ( event . detail ?. isLastFrame || frameCount >= maxFrames ) {
544- window . removeEventListener (
545- "fxhash-capture-frame" ,
546- handleFrameCapture
547- )
548- resolve ( )
549- }
550- }
551-
552- window . addEventListener ( "fxhash-capture-frame" , handleFrameCapture )
553-
554- // timeout fallback
555- setTimeout ( ( ) => {
556- window . removeEventListener ( "fxhash-capture-frame" , handleFrameCapture )
557- resolve ( )
558- } , delayMax )
559- } )
560- } ,
561- GIF_DEFAULTS . MAX_FRAMES ,
562- DELAY_MAX
563- )
564-
565- return frames
566- }
567-
568- async function captureViewport (
569- page ,
570- triggerMode ,
571- isGif ,
572- frameCount ,
573- captureInterval ,
574- playbackFps
575- ) {
576- if ( ! isGif ) {
577- return await page . screenshot ( )
578- }
579-
580- const captureViewportFrame = async ( ) => {
581- return await page . screenshot ( {
582- encoding : "binary" ,
583- } )
584- }
585-
586- const frames =
587- triggerMode === "FN_TRIGGER_GIF"
588- ? await captureFramesProgrammatically ( page , captureViewportFrame )
589- : await captureFramesWithTiming (
590- captureViewportFrame ,
591- frameCount ,
592- captureInterval
593- )
594-
595505 const viewport = page . viewport ( )
596506 return await captureFramesToGif (
597507 frames ,
@@ -604,7 +514,6 @@ async function captureViewport(
604514async function captureCanvas (
605515 page ,
606516 canvasSelector ,
607- triggerMode ,
608517 isGif ,
609518 frameCount ,
610519 captureInterval ,
@@ -623,24 +532,36 @@ async function captureCanvas(
623532 return Buffer . from ( pureBase64 , "base64" )
624533 }
625534
626- const captureCanvasFrame = async ( ) => {
535+ const frames = [ ]
536+ let lastCaptureStart = Date . now ( )
537+
538+ for ( let i = 0 ; i < frameCount ; i ++ ) {
539+ const captureStart = Date . now ( )
540+
627541 // Get raw pixel data from canvas
628542 const base64 = await page . $eval ( canvasSelector , el => {
629543 if ( ! el || el . tagName !== "CANVAS" ) return null
630544 return el . toDataURL ( )
631545 } )
632- if ( ! base64 ) throw new Error ( "Canvas capture failed" )
633- return base64
634- }
546+ if ( ! base64 ) throw null
547+ frames . push ( base64 )
635548
636- const frames =
637- triggerMode === "FN_TRIGGER_GIF"
638- ? await captureFramesProgrammatically ( page , captureCanvasFrame )
639- : await captureFramesWithTiming (
640- captureCanvasFrame ,
641- frameCount ,
642- captureInterval
643- )
549+ // Calculate timing adjustments
550+ const captureDuration = Date . now ( ) - captureStart
551+ const adjustedInterval = Math . max ( 0 , captureInterval - captureDuration )
552+
553+ console . log ( `Frame ${ i + 1 } /${ frameCount } :` , {
554+ captureDuration,
555+ adjustedInterval,
556+ totalFrameTime : Date . now ( ) - lastCaptureStart ,
557+ } )
558+
559+ if ( adjustedInterval > 0 ) {
560+ await sleep ( adjustedInterval )
561+ }
562+
563+ lastCaptureStart = Date . now ( )
564+ }
644565
645566 const dimensions = await page . $eval ( canvasSelector , el => ( {
646567 width : el . width ,
@@ -750,7 +671,6 @@ exports.handler = async (event, context) => {
750671 const processCapture = async ( ) => {
751672 const capture = await performCapture (
752673 mode ,
753- triggerMode ,
754674 page ,
755675 canvasSelector ,
756676 resX ,
@@ -767,16 +687,10 @@ exports.handler = async (event, context) => {
767687 return upload
768688 }
769689
770- if ( triggerMode === "FN_TRIGGER_GIF" ) {
771- // for FN_TRIGGER_GIF mode, skip preview waiting entirely
772- // the capture functions will handle event listening internally
773- console . log ( "Using FN_TRIGGER_GIF mode - skipping preview wait" )
690+ if ( useFallbackCaptureOnTimeout ) {
691+ await waitPreviewWithFallback ( context , triggerMode , page , delay )
774692 } else {
775- if ( useFallbackCaptureOnTimeout ) {
776- await waitPreviewWithFallback ( context , triggerMode , page , delay )
777- } else {
778- await waitPreview ( triggerMode , page , delay )
779- }
693+ await waitPreview ( triggerMode , page , delay )
780694 }
781695
782696 httpResponse = await processCapture ( )
0 commit comments