Describe the bug
I render transparent WebM overlays with parallel capture (4 workers, and I see massive flickering
I dug in and found the flicker is baked into the file: a single fully transparent frame at every interior worker chunk boundary. For a 144 frame render with 4 workers that's frames 36, 72 and 108, exactly w * ceil(totalFrames/workers). Worker 0 is fine because frame 0 is the initially painted state.
Root cause: executeWorkerTask calls captureFrameRange right after initializeSession, and the first loop iteration captures task.startFrame right after __hf.seek(t). On loaded machines the seek hasn't painted yet, so the screenshot catches an empty page. Every later frame is fine because the previous iteration's seek already settled the page.
One more thing worth saying: you already have the fix in the codebase. discardWarmupCapture (throwaway seek+capture that restores all the session counters) is defined and exported but never called anywhere.
Link to reproduction
Steps to reproduce
The bug is verifiable in code on any machine, no render needed:
- Open dist/index.js of any published version from 0.7.25 to 0.7.58
- Look at
executeWorkerTask: it calls captureFrameRange immediately after initializeSession
captureFrameRange's first loop iteration captures task.startFrame right after __hf.seek(t), with no settle. Every later frame is fine because the previous iteration's seek already painted
- Note
discardWarmupCapture is defined and exported with zero call sites, so nothing warms up the parallel workers
To detect it on any affected output, decode with libvpx and scan the alpha plane:
ffmpeg -c:v libvpx-vp9 -i out.webm -vf "alphaextract,signalstats,metadata=mode=print" -f null -
Frames at w * ceil(totalFrames/workers) show alpha mean ~0.0 between normal neighbors. The frames are transparent, not black, so color plane blackdetect misses them.
Expected behavior
Every worker's first captured frame contains the actual seeked state of the composition, same as a serial capture of that frame index would produce.
Actual behavior
frame 71 alphaYAVG=4.17
frame 72 alphaYAVG=0.00 <- boundary blank (144/4 * 2)
frame 73 alphaYAVG=4.2
Environment
@hyperframes/producer 0.7.25 on node:22.16-slim (linux/amd64),
Chromium + SwiftShader (no GPU), c6a.4xlarge, 4 parallel workers, forceScreenshot,
transparent WebM (yuva420p)
Additional context
No response
Describe the bug
I render transparent WebM overlays with parallel capture (4 workers, and I see massive flickering
I dug in and found the flicker is baked into the file: a single fully transparent frame at every interior worker chunk boundary. For a 144 frame render with 4 workers that's frames 36, 72 and 108, exactly
w * ceil(totalFrames/workers). Worker 0 is fine because frame 0 is the initially painted state.Root cause:
executeWorkerTaskcallscaptureFrameRangeright afterinitializeSession, and the first loop iteration capturestask.startFrameright after__hf.seek(t). On loaded machines the seek hasn't painted yet, so the screenshot catches an empty page. Every later frame is fine because the previous iteration's seek already settled the page.One more thing worth saying: you already have the fix in the codebase.
discardWarmupCapture(throwaway seek+capture that restores all the session counters) is defined and exported but never called anywhere.Link to reproduction
Steps to reproduce
The bug is verifiable in code on any machine, no render needed:
executeWorkerTask: it callscaptureFrameRangeimmediately afterinitializeSessioncaptureFrameRange's first loop iteration capturestask.startFrameright after__hf.seek(t), with no settle. Every later frame is fine because the previous iteration's seek already painteddiscardWarmupCaptureis defined and exported with zero call sites, so nothing warms up the parallel workersTo detect it on any affected output, decode with libvpx and scan the alpha plane:
ffmpeg -c:v libvpx-vp9 -i out.webm -vf "alphaextract,signalstats,metadata=mode=print" -f null -
Frames at w * ceil(totalFrames/workers) show alpha mean ~0.0 between normal neighbors. The frames are transparent, not black, so color plane blackdetect misses them.
Expected behavior
Every worker's first captured frame contains the actual seeked state of the composition, same as a serial capture of that frame index would produce.
Actual behavior
frame 71 alphaYAVG=4.17
frame 72 alphaYAVG=0.00 <- boundary blank (144/4 * 2)
frame 73 alphaYAVG=4.2
Environment
Additional context
No response