Video Frame Reorder & Skip
Swap your video's halves and drop frames without ever leaving the graph
- image_sequence
- processed_images
One node, two jobs nobody gives you a built-in for
Once your ComfyUI video is out of the VAE decode, it's just a big tensor of frames - and the core toolset gives you surprisingly few ways to rearrange them. You can encode them, save them, combine them, but "change the order" or "keep every other one" isn't a button anywhere. VideoFrameReorderAndSkip (class VideoFrameReorderAndSkip, from the tiny zhaocaiji/ComfyUI-VideoFrameTools pack) is a two-in-one utility for exactly that. It does two things: swaps the two halves of your sequence, and decimates it by an interval. That's it. No weights, no models, no hidden pipeline - just a couple of tensor slices.
The pack is almost absurdly small - one Python file, zero dependencies beyond torch, which ComfyUI already ships. That's the right size for this job, and it means there's no install drama beyond dropping it in.
What it actually does under the hood
The mechanism is worth knowing because it explains the quirks. Your image_sequence arrives as a tensor shaped [frames, height, width, channels], and the node only touches that first (frame) dimension.
First, it always reorders: it cuts the sequence in half and concatenates the halves back in swapped order. For 16 frames you get [8..15, 0..7], not a true reversal. Second, it skips frames: skip_interval of N keeps 1 frame every N frames, implemented as a stride of N+1. Set 0 and the stride is 1, so nothing is dropped.
Read the source (video_tools.py in the repo) and one gotcha jumps out: the half-swap runs unconditionally. There is no toggle to disable it. If you only wanted frame skipping, you still get the halves swapped first. There's also a guard - if your sequence has fewer than 2 frames, the swap is skipped entirely and only the skip applies.
The two inputs that matter
image_sequence(IMAGE) - wire this to aVAE Decodeoutput, or an image sequence/loader node. The README says it plainly: batch frames in, batch frames out.skip_interval(INT, default 0, range 0–120) - 0 keeps everything; 1 keeps 1 frame in every 2 (halves the frame count); 2 keeps 1 in 3, and so on.
The single output, processed_images (IMAGE), feeds straight into VideoCombine or SaveImage - same slot the decoded frames would have gone into.
Installing it
ComfyUI Manager is the easy path - search for "VideoFrameTools" and install. Otherwise, from your ComfyUI/custom_nodes directory:
git clone https://github.com/zhaocaiji/ComfyUI-VideoFrameTools
Then restart ComfyUI. No model files, no pip installs, no heavy dependencies - the whole thing is one video_tools.py plus a mapping in __init__.py. It appears under My Custom Nodes → Video Tools in the node menu.
Where it earns its keep, and where it burns you
Frame skipping is the genuinely useful half. It's how you fit long generations into short context windows, turn a 60fps render into 30fps, or cut a 121-frame LTX clip down to something your VRAM can re-encode in one pass. The half-swap is more situational - it's handy when you're splicing two halves of a clip back together in a different order, or pairing first-half/last-half frames for interpolation-style work.
The burn: beginners reach for this expecting a "reverse" button and get a split-and-swap instead. If you want a true reversed playback, this won't give it to you. And because the swap can't be turned off, it's not a clean "just decimate" node either - feed it a sequence and check that the swapped order is actually what you want before you commit frames to a render. The naming in the code comments ("first half", "second half") matches the behavior exactly, so a quick look at the source saves you a wasted encode.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image_sequence | IMAGE | — | |
| skip_interval | INT | 00–120 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| processed_images | IMAGE | — |