Video Frame Router
Pull one frame out and put it back
- video_image
- frame_image
- frame_index
- total_frames
- passthrough
Most of ComfyUI's image nodes want a batch. Some jobs only make sense on one frame at a time - a colour reference, a per-shot grade lookup, a scope reading, a "what does frame 200 look like" check. Video Frame Router is the valve between those two worlds: give it a frame batch and an index, get a single frame out.
Inputs and outputs
video_image is the batch. frame_index (default 0, 0–4096) is the 0-based frame to extract. wrap_index (default on) decides what happens when you ask for a frame past the end: on, it wraps around modulo the frame count; off, it clamps to the last frame.
That wrap-versus-clamp choice is the most useful thing in the node. Wrapping is right when the index is coming from something cyclic - an animation phase, a beat, a repeating pattern - because frame_index % total keeps producing sensible frames however the number grows. Clamping is right when the index is a deliberate position in the shot and you'd rather see the last frame than silently jump back to the start. The failure mode of getting it wrong is subtle: a graph that seems to work, except the frame it grabbed is from the wrong part of the clip.
Outputs are frame_image ([1,H,W,3] - one frame for grading), frame_index (which frame it actually took), total_frames, and passthrough (the original batch, unchanged).
That set is well designed for real graphs. passthrough exists so you can branch: send the whole clip down one path and simultaneously pull a frame for analysis, without duplicating the decode. total_frames lets you sanity-check the arithmetic before it matters. And frame_index coming back out means a chained node doesn't need to recompute which frame it's on.
The loop it's meant for
The source docstring is direct about this: "This node outputs a single frame per call. To process all frames, use ComfyUI's native batch iteration." In practice that means the router feeds per-frame processing, and the frames go back into a sequence via Video Assembler, which accumulates them and emits the finished batch.
So the shape is: decode → Video Frame Router → grade/grain/whatever → Video Assembler → export. That's a real pattern and it's the one most usages of this node land in.
Be aware of what it costs you: for each frame, ComfyUI executes the whole downstream chain. That's how you get per-frame grading in a graph with no loop construct, and it's also why the upstream nodes are worth keeping cheap - a smart move is to do the expensive work (decode, load, upscale) once on the batch and only route the light stuff through the per-frame path.
A note on indexes and caching
Because the node's inputs are just a batch and an integer, it re-executes when either changes and not otherwise. So nothing here magically iterates on its own - something upstream has to drive frame_index across the range. If you queue a graph with the index at 0, you get frame 0, forever, and no error to tell you why.
If you're just browsing a clip, the pack's Viewer is the better tool: it takes the whole IMAGE batch and gives you playback, so you can scrub to the frame you want and read its values scopes-style. Use the router when a node needs one frame, not when you want to look at one.
Install
- ComfyUI Manager → search Radiance → Install → restart → refresh the browser.
- Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/fxtd-studios/radiance.git
cd radiance
python -m pip install -r requirements.txt
Windows portable users: run the pip line with python_embeded\python.exe. Nothing downloads for this node - it's indexing into a tensor. Radiance's overall dependency list is long (OpenEXR, OpenImageIO, OpenColorIO, transformers, diffusers, scipy) and its install.py checks the colour libraries after a Manager install. If the node behaves differently from the docs, check your version: the Comfy Registry has been serving an older release than the README's 3.5.0, so git pull or Update in Manager.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| video_image | IMAGE | Frame batch to pick from. Also returned unchanged on passthrough. | |
| frame_index | INT | 00–4096 | 0-based frame to extract. Past the end it wraps or clamps to the last frame, per wrap_index. |
| wrap_indexopt | BOOLEAN | true | If frame_index >= total_frames, wrap around (modulo). Off: clamp to the last frame. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| frame_image | IMAGE | — |
| frame_index | INT | — |
| total_frames | INT | — |
| passthrough | IMAGE | — |