Skip to content

Parallel capture: worker's first frame is captured before the seek paints, leaving a fully transparent frame at every worker chunk boundary #2477

Closed as not planned

Description

@yahelshiran-rvr

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:

  1. Open dist/index.js of any published version from 0.7.25 to 0.7.58
  2. Look at executeWorkerTask: it calls captureFrameRange immediately after initializeSession
  3. 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
  4. 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

Activity

  1. mvanhorn commented on Jul 15, 2026

    @mvanhorn
    Contributor

    Opened a PR with a fix: #2489

  2. miguel-heygen commented on Jul 15, 2026

    @miguel-heygen
    Collaborator

    Thanks for the detailed investigation. We confirmed the affected code path, but we have not been able to reproduce the transparent boundary frames locally, including with a 4-worker transparent WebM render under contention.

    @yahelshiran-rvr could you provide a minimal self-contained reproduction fixture (composition HTML plus any required local assets) and the exact render command/configuration used to produce the failure? If possible, please also include the relevant environment variables and either a small affected WebM or a Dockerfile/container command matching the Linux/amd64 environment. That will let us validate the fix against the actual failing case rather than only the call sequence. With a github repo would work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions