Nodes/AM VFX Tools/AM Frame Range
ComfyUI Node

AM Frame Range

Grab a slice of a batch without loading the whole thing

By am-pipeline-prod·Created 4 months ago·Updated 3 months ago· 3
AM Frame Range
  • image
  • video
  • image
  • video
frame_modesingle
first_frame1
last_frame-1

Stock ComfyUI is stubbornly frame-agnostic: a video is just an IMAGE batch, and there's no native "give me frames 40 through 60" utility. AM Frame Range is that utility - it slices an IMAGE batch (or a VIDEO stream) down to the frames you actually want. It's boring, and that's the point. Every long-video pipeline ends up needing one.

It ships in comfyui-am-vfx-tools ("AM VFX Tools" category), the 13-node VFX toolkit by Adrian Meyer that's the public slice of an internal studio pipeline.

How it works

You pick a frame_mode, and the node emits a sub-batch:

  • single - just first_frame. Output is a one-frame batch, shape (1,H,W,C).
  • range - first_frame through last_frame, inclusive.
  • all - pass the batch through unchanged.

Three widgets, one job. Everything is 1-based (frame 1 = the first frame in the batch), and the bounds are clamped to [1, N] so you can't slice past the end. last_frame defaults to -1, which means "end of batch" - that's the setting you'll use 90% of the time.

Why the video socket is the interesting part

The IMAGE branch is plain slicing. The VIDEO branch is where this node quietly earns its keep. Wire a VideoFromFile source (like the output of AM Read Video's video socket) into the video input, and AM Frame Range returns a lazy wrapper that only decodes the frames in your range - PyAV seeks, pulls exactly those frames, and early-terminates instead of chewing through the source's tail. Peak RAM stays at one frame, and a 10,000-frame source only costs you the 20 frames you asked for.

That's the same lazy VIDEO machinery every pixel node in this pack carries: wire image and you get a plain slice; wire video and the work gets deferred until a downstream consumer actually iterates frames. If you don't need the whole clip in RAM, use the video path.

The inputs that matter

Two, really:

  • frame_mode - set to range and you're slicing; single if you want to peek at one frame; all if you want the node as a no-op passthrough.
  • first_frame / last_frame - your window, 1-based, inclusive. last_frame = -1 = to the end.

Outputs are image (the sliced batch, or the single frame) and video (a FrameRangeVideo wrapper, or a zero-copy VideoFromComponents around the sliced batch). None when nothing's wired.

Installing it

Install the pack once, get all 13 nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/am-pipeline-prod/comfyui-am-vfx-tools.git
cd comfyui-am-vfx-tools
pip install -r requirements.txt

Restart ComfyUI. Or search comfyui-am-vfx-tools in ComfyUI Manager. The pack pulls in OpenImageIO, OpenColorIO, PyAV, and OpenCV headless - the pip step installs those, and it's not optional.

Where people get burned

The 1-based indexing trips people up if they're coming from zero-based code - frame 1 is the first frame, not frame 0. And remember the clamp: if you set first_frame beyond the batch length, it clamps to [1, N] rather than erroring, so a mistyped range silently becomes the whole batch instead of failing loudly. Check the output frame_count if you're not sure you sliced what you think you sliced.

CategoryAM VFX Tools/Util

Inputs (5)

NameTypeDefaultDescription
frame_modeCOMBOsingleWhich frames to emit from the input batch. single = only `first_frame`. range = `first_frame`..`last_frame` inclusive. all = pass the batch through unchanged.
first_frameINT1-999999–999999Frame index in single mode; lower bound in range mode (1-based). Ignored in all mode. Clamped to [1, N].
last_frameINT-1-1–999999Range upper bound (inclusive, 1-based). -1 = end of batch. Ignored in single / all modes. Clamped to [first_frame, N].
imageoptIMAGEImage batch to slice.
videooptVIDEOOptional VIDEO input. When wired, returns a lazy `FrameRangeVideo` wrapper that filters frames on consumption — no IMAGE materialisation here. With a `VideoFromFile` source, PyAV decodes ONLY the frames in the requested range and early-terminates after the last requested frame is yielded. Combined with a downstream AM consumer, peak RAM stays at one frame and the source's unwanted tail frames are never decoded. `image` is ignored when `video` is wired. See invariant 28.

Outputs (2)

NameTypeDescription
imageIMAGESelected image batch. Shape (1,H,W,C) in single mode, (N,H,W,C) in range mode, identical to the input in all mode.
videoVIDEOLazy VIDEO output — emits a `FrameRangeVideo` wrapper when `video` is wired, else a zero-copy `VideoFromComponents` around the sliced IMAGE batch. None when no input is wired.