Nodes/ComfyUI-chronophotography/Create Chronophotography
ComfyUI Node

Create Chronophotography

Turn any video into a Marey-style motion ghost still

By kusurin·Created about a year ago·Updated about a year ago· 0
Create Chronophotography
  • frames
  • masks
  • chronophotography
modearange
start_frame0
step_frame30
stop_frame100
render_frames0,30,60,90
gaussian_blur_size21
morphology_kernel_size5

You know the look even if you don't know the name: a golfer mid-swing repeated four or five times along the arc of the club, a dancer frozen at every position of a spin, all in one frame. That's chronophotography, the 1870s-80s trick Étienne-Jules Marey and Eadweard Muybridge pioneered to study motion frame by frame - and it's exactly what CreateChronophotography reproduces from your video.

It's a tiny, honest little node: no model weights, no diffusion, no API, no key. The README pitches it as turning video into "motion stock image," and that's accurate. Feed it a batch of frames plus a mask per frame, and it composites the moving subject into one still that looks like the shot was taken with a camera that never closed its shutter.

Where it sits in a workflow

The catch is in that "plus a mask per frame." This node does not do segmentation - it's a pure compositor, and it will sit there staring at you if you only hand it frames. The included example workflow wires it as: VHS_LoadVideo → SAM2 video segmentation (with point prompts to track the subject) → CreateChronophotographyPreviewImage. So the real skill here is upstream: get a good per-frame mask of the moving subject (SAM2 video tracking, or a segmentation/background-removal pass like BiRefNet on sampled frames), and this node does the rest.

How it works

The mechanism is straightforward and worth knowing because it explains every knob. First it picks which frames to render, in one of two modes:

  • arange - start_frame, step_frame, stop_frame; takes every step_frame-th frame in that range (defaults 0/30/100).
  • list - render_frames as a comma-separated string of explicit indices like 0,30,60,90.

The last picked frame becomes the background. Every earlier picked frame is then composited back onto it in reverse order: its mask is cleaned up (morphological open → close → dilate, keeping only the largest connected region so stray specks don't ghost into the shot), blurred into a soft alpha using gaussian_blur_size, and blended in. Earlier positions end up as progressively fainter ghosts behind the newest one. Output is a single IMAGE (chronophotography) - just wire it to a save or preview node.

The inputs that matter

  • frames (IMAGE) and masks (MASK) - a batch of frames and one aligned mask per frame. Same count, same order, or it silently skips whatever doesn't line up.
  • mode - arange or list; pick your poison for choosing which frames appear.
  • gaussian_blur_size (default 21, odd, 1–101) - the big artistic knob. Higher = softer, more ethereal ghosts; lower = crisp stacked copies.
  • morphology_kernel_size (default 5, odd, 1–15) - how aggressively it denoises the masks before compositing.

That's honestly the whole thing. Two knobs you'll actually touch, everything else defaults fine.

Installing it

The easy way: ComfyUI Manager → search "ComfyUI-chronophotography" → install. Or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/kusurin/ComfyUI-chronophotography
# restart ComfyUI

Refreshingly light on dependencies - requirements.txt is just numpy and opencv-python (torch comes with ComfyUI). No model files to download. If you see a cv2 import error, it means opencv-python didn't get installed; pip install opencv-python in your ComfyUI environment fixes it.

Gotchas

  • Don't feed it bare frames. Without masks the compositing has nothing to blend, and you'll get a single, boring background frame - which is also what it does silently when none of your frame indices are valid. If it "did nothing," check your indices against the actual batch length first.
  • Default step_frame is 30. On a 24–30 fps video that's roughly a second between ghosts, which is the right vintage-motion-study spacing - but on a slow-moving subject you may want smaller steps or the list mode.
  • It keeps only the largest mask region per frame. If your subject is two disconnected things (a dancer and a swirling prop), only the biggest survives each frame. That's a deliberate choice in the code, not a bug - but it will surprise you the first time.

It's a niche tool with zero fanfare behind it, but when you want that specific "one frame, many positions" poster shot, it's the exact node you'd hand-roll anyway - just in a tidy package.

Categorychronophotography

Inputs (9)

NameTypeDefaultDescription
framesIMAGE
masksMASK
modeCOMBOarange2 options: arange, list
start_frameoptINT0
step_frameoptINT30
stop_frameoptINT100
render_framesoptSTRING0,30,60,90
gaussian_blur_sizeoptINT211–101
morphology_kernel_sizeoptINT51–15

Outputs (1)

NameTypeDescription
chronophotographyIMAGE