Video To Image
Turn clips into frame batches for img2img and training data
- image_paths
The FairLab Video To Image node extracts frames from a video and writes them as JPGs to disk, using OpenCV under the hood. It's the "get stills out of a clip" node, and it exists because so many workflows start from video: frame-by-frame img2img, video-to-video preprocessing, or building a training dataset from footage.
The README groups it under video I/O, and the sibling is Image To Video (frames back into an MP4) - the pack wants to be your whole frame round-trip story. ComfyUI's built-in VHS-style video nodes are powerful, but this one is a plain, honest "dump frames as files" tool with no exotic codecs or model downloads required.
How it works
It opens the video with OpenCV's VideoCapture, prints the video's metadata (width, height, FPS, frame count) to the console, then reads frames one at a time and writes every Nth one as a JPG. There's a progress bar for long videos, and the node strips stray double-quote characters from your path inputs - a small robustness touch.
The output is a list of the saved image paths, so you can see exactly what landed where.
The inputs that matter - and the trap
- video_path - path to the source video.
- capture_rate - default 30. Here's the trap: despite the name, this is not "frames per second." It's a sampling interval: save one frame every N frames. With a 30 FPS video and
capture_rate=30, you get one frame per second of footage - roughly. It's the step of the extraction, not the rate of the output. - frame_offset - default 0. Skips the first N frames before extraction starts.
- image_dir - where the JPGs go.
- image_name_prefix - a prefix for each file.
Filenames are <prefix><frame_counter>.jpg, numbered by the frame counter, not a sequential 0,1,2 index - so with capture_rate=30 you get files like clip_1.jpg, clip_31.jpg, clip_61.jpg. That's fine for most uses and worth knowing if you expected clean sequential names.
The other gotchas
- It writes files to disk, not a tensor. The output is a list of paths, not an
IMAGEbatch. To feed frames into a sampler you'll load them back - the same pack's Load Image Batch From Directory is the natural companion, and the README pairs them explicitly. - The directory must already exist.
cv2.imwritewon't create folders for you. - Needs
opencv-python. It's in the pack's requirements, but if you installed manually and skipped that step, this is one of the nodes that will fail at runtime. - JPGs only. No PNG option here. Lossy frames, fine for most pipelines, wrong for pixel-perfect work.
- Big videos = big runs. The README warns processing time scales with resolution and frame count. A 10-minute 4K clip at
capture_rate=1is a lot of JPGs; sample sensibly.
When you'd use it
- Frame-by-frame img2img: extract stills, process them, recombine.
- Dataset prep: pull training frames out of footage for LoRA or fine-tuning data.
- Grabbing a handful of stills from a clip for reference.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/yanhuifair/ComfyUI-FairLab.git
cd ComfyUI-FairLab
pip install -r requirements.txt
Restart, or search "ComfyUI-FairLab" in ComfyUI Manager. Verify OpenCV landed with pip list | grep opencv - it's the one dependency this node genuinely needs, and the README's cv2 troubleshooting note exists because people miss it.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| video_path | STRING | — | |
| capture_rate | INT | 30 | — |
| frame_offset | INT | 0 | — |
| image_dir | STRING | — | |
| image_name_prefix | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image_paths | STRING | — |