Nodes/FFRAMES/FFRAMES
ComfyUI Node

FFRAMES

Cut a video down to the two frames your video model actually wants

By spiritform·Created 2 days ago·Updated a day ago· 1
FFRAMES
  • images
  • images
  • first_frame
  • last_frame
  • frame_count
  • fps
  • duration
frame_start0
frame_end0
range_modetrue
media

If you've ever tried to do image-to-video properly, you know the pain FFRAMES is pointing at: your Wan or Seedance workflow doesn't want a clip, it wants bookends. Seedance takes a start frame and an end frame and invents everything between. Wan2GP has a first-frame/last-frame mode, and most of those recipes want one clean shot of each endpoint plus a frame count. So you load your source video, squint at frame 12, and ask yourself how you're going to hand the graph just those two frames without guessing.

The classic answer was a brittle little chain - VHS_LoadVideo into a SliceImageBatch with two hardcoded numbers you couldn't eyeball, or worse, exporting frames in an external editor. FFRAMES is the visual answer: a hybrid frame picker + trimmer that puts a scrubbable timeline right on the node, with two draggable handles for your first and last frame, and hands the result to the rest of your graph. It's brand new, it's tiny, and it's genuinely the tool for this one chore.

How it works

The node is two halves working together. The frontend (a custom widget in web/frame_picker.js) renders the video preview, the frame strip, and those two handles. The backend (frame_picker.py) does the actual decode through OpenCV - BGR to RGB, uint8 to float32 in the [0,1] range you need for a tensor - and hands the sliced batch to downstream nodes.

There are two ways to feed it, and they behave differently. Connect an IMAGE batch (say from VHS_LoadVideo) to the optional images input, and it just slices your existing tensor - no decode, no re-read, instant. Or skip the upstream node entirely: double-click the empty preview to upload a video file (the media dropdown lists everything already in your ComfyUI input/ folder), and the node decodes the clip itself and reports real metadata.

Either way, the two draggable markers set your range. Here's the bit that'll trip you up the first time: FF can sit past LF and it's not a bug. Put the start handle at frame 84 and the end at frame 46 and you get a reversed sequence - the output batch runs 84 → 46, with first_frame and last_frame still matching their markers. Handy for playing clips backwards; confusing if you don't know it's coming.

The inputs and outputs that matter

  • frame_start / frame_end - integers, 0 to 999999, but you rarely type these. Dragging the handles writes them. They're also where the preview-only FF/LF transport buttons jump the playhead, so you can eyeball exactly what each marker is sitting on.
  • range_mode - on means "give me everything from FF to LF." Flip it off and the node collapses to a single frame (the one at frame_start). That's your cheap way to extract one clean frame for a T2V or i2v seed.

Outputs: images (the sliced batch - flipped if reversed), first_frame and last_frame (single images, ready to wire straight into a Wan i2v image input or a Seedance image-pair), plus frame_count, fps, and duration. One honest gotcha: fps and duration are only real when you let the node decode the file itself. Feed it an IMAGE batch from VHS and those two come back as 0 - a tensor carries no container metadata, so there's nothing to read.

Install

ComfyUI Manager (search "FFRAMES"), or the manual way:

cd ComfyUI/custom_nodes
git clone https://github.com/spiritform/FFRAMES

Then restart ComfyUI. The one wrinkle: dependencies (opencv-python, pillow, numpy) are declared in pyproject.toml, not a requirements.txt. Manager handles that fine, but if you cloned by hand and hit a "opencv-python is required" error, pip install opencv-python into your Comfy environment fixes it.

Where people get burned

  • Long ranges eat RAM. The decoder pre-allocates the whole requested slice as one float32 buffer, so a 500-frame range of a 4K clip is a couple of gigabytes and can OOM. The error literally tells you the fix: narrow the range or drop to single-frame mode.
  • Reversed ranges - covered above; it's a feature, but check the marker order before you blame the node.
  • The duration output is rounded to whole seconds and exists to plug straight into a video model's duration field - but again, only on the file-decoding path.

Scrubbing is nice, too: click anywhere on the strip to jump, / step one frame (Shift steps ten), Space plays, the download icon exports a zero-padded PNG, and you can drag the preview onto the canvas to spawn a LoadImage with the current frame. For a one-trick pack, it's a well-finished trick.

Categoryimage/animation

Inputs (5)

NameTypeDefaultDescription
frame_startINT00–999999
frame_endINT00–999999
range_modeBOOLEANtrue
imagesoptIMAGE
mediaoptCOMBO1 options:

Outputs (6)

NameTypeDescription
imagesIMAGE
first_frameIMAGE
last_frameIMAGE
frame_countINT
fpsFLOAT
durationINT