Nodes/MKRShift_Nodes/Extract Video Frames
ComfyUI Node

Extract Video Frames

Pull frames out of a clip without a separate ffmpeg step

By criskb·Created 7 months ago·Updated 5 months ago· 0
Extract Video Frames
  • video
  • frames
  • frame_count
  • fps
  • width
  • height
  • summary
sample_fps0.0
start_frame0
end_frame-1
stride1
max_frames0

Almost every video workflow in ComfyUI starts the same way: you've got a clip and you need it as an IMAGE batch so the sampler can actually work on it. MKRExtractVideoFrames is that step, but with the slicing options that make it genuinely useful instead of "decode everything and hope."

The core trick is that it accepts video input in whatever form it arrives - an MKR_VIDEO payload from the pack's own nodes, a file path, or even an already-decoded IMAGE tensor - and normalizes it to a tensor batch. So it slots into the graph whether your clip came from MKRLoadVideoMetadata-style nodes, a VHS loader, or was generated upstream as frames.

The inputs that matter

Five knobs, and only two are confusing at first:

  • sample_fps - decode at a capped frame rate. Default 0 means "use the source's native fps." Set it to, say, 12 to pull every frame at 12fps from a 60fps source. This is the cheap man's frame skip.
  • start_frame / end_frame - the range to keep. end_frame defaults to -1, which means "to the end," and it's clamped so you can't overshoot.
  • stride - keep every Nth frame within the range. Stride 2 halves the count, which is handy when you want coverage without every adjacent frame.
  • max_frames - a hard cap on the output. 0 means no cap. If your VRAM is telling you no, this is the leash.

The outputs are what you'd hope: frames (IMAGE), frame_count (INT), fps (FLOAT, the actual rate used), width and height (INT), and summary (JSON string). Wire frames straight into a VAE encode or img2img pass.

How it works

Under the hood it decodes to PIL frames (ffmpeg or Pillow, depending on the source format), slices frames[start:end+1:stride], and converts back to a tensor. gif and webp decode via Pillow; anything else wants ffmpeg on the machine. If you're running the whole pack you've almost certainly installed ffmpeg already - the README calls it out for the export/muxing nodes, and it's the same dependency here. Without it, MP4-style sources will warn and fall back.

One honest warning: sample_fps doesn't resample intelligently, it skips to hit the target rate. If you need proper temporal resampling, decimate and move on - but for feeding a diffusion model, skipping is usually exactly what you want, because the sampler doesn't care about frame timing, just the pixels.

Installing

Same as every node in this pack:

cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes

Restart ComfyUI. ComfyUI Manager works too - search "MKRShift_Nodes." No extra Python packages; it's all numpy/Pillow/torch from the standard ComfyUI stack.

Where people trip

If frame_count comes back 0 and summary mentions a decode warning, the source wasn't readable - check the format and that ffmpeg is installed. And if you set end_frame to a real number, remember it's inclusive; range math on a 1-based editor timeline (frame 1 = first frame) is off by one from this node's 0-based indexing. Set start_frame 0, end_frame -1, stride 1 for the "just give me everything" path.

CategoryMKRShift Nodes/Media/IO

Inputs (6)

NameTypeDefaultDescription
video*
sample_fpsFLOAT0.00–240
start_frameINT00–10000000
end_frameINT-1-1–10000000
strideINT11–1000
max_framesINT00–1000000

Outputs (6)

NameTypeDescription
framesIMAGE
frame_countINT
fpsFLOAT
widthINT
heightINT
summarySTRING