Load Video From Folder (Batch)
Frame extraction that loops for you
- FRAMES
- folder_path
- filename_stem
- filename_full
- current_index
- total_videos
- frame_count
- fps
- duration_seconds
Video is where folder batching gets genuinely painful. You can't just load a clip like an image - you have to pick frames, then do it again for the next clip, and the next. Load Video From Folder (Batch) from hodgemann's ComfyUI-BatchFolderTools is the sibling of the pack's image loader, built for exactly that: it walks a folder of videos one at a time, extracts frames as a standard IMAGE batch, and hands each clip to your workflow. Team it with the pack's Queue Next node and you caption, analyze, or thumbnail an entire folder on one Queue click.
The natural use case is video captioning for training data: sample a few frames per clip, run a vision-language model over them, save a text file. The pack's own example workflow does this with QwenVL-Mod, sampling 16 evenly-spaced frames per video. It's the same pattern llm-in-comfyui.md § VLM captioning describes, aimed at a folder instead of a single file.
How it works
Under the hood it's OpenCV (cv2.VideoCapture) reading the file straight from disk. It grabs the total frame count and framerate, works out which indices to read for your frame mode, seeks to each, converts from OpenCV's BGR to RGB, and stacks them into a [N, H, W, C] IMAGE tensor - the same shape the image loader produces, just with N frames instead of 1. Like the image loader, the sequential counter auto-advances per execution and IS_CHANGED returns NaN so ComfyUI never caches the run away; when the folder's exhausted it errors out before Queue Next re-queues, stopping the loop cleanly.
The frame modes - this is the whole product
- first_frame / last_frame - one frame. Use these for thumbnails, previews, or "does this clip contain what I think it does" checks.
- all_frames - every frame in the video. Handy, and a fast way to blow up your VRAM: a 10-minute clip at 24fps is 14,400 frames. Treat this mode with respect.
- evenly_spaced - the default workhorse. Extracts
frame_countframes (default 16) spread evenly across the whole clip, start to end. This is what the captioning workflow uses: enough coverage to describe what happens without drowning the model in near-duplicate frames. - frame_range - a contiguous slice from
start_frametoend_frame.end_frameof-1means "to the end," which is how the field is documented.
Everything else - folder_path, mode (sequential/manual), index, sort_by, reset_counter, skip_captioned - behaves exactly like the image loader. skip_captioned is the resume mechanism again: after a crash or restart the in-memory counter is gone, so it scans for existing .txt / .caption / .cap files next to each video and skips anything already done, zero GPU cost.
The outputs
FRAMES is the IMAGE batch you feed downstream. Then the metadata:
- fps and duration_seconds - read off the clip itself (OpenCV's
CAP_PROP_FPS, frames ÷ fps). Useful if you want to log or filter clips, or annotate a caption with duration. If the file's framerate reads as garbage, it falls back to 24.0. - frame_count - how many frames were actually extracted this run.
- filename_stem / filename_full / folder_path - wire the stem and path into the pack's Save Text File node so captions land next to their video.
- current_index / total_videos - where you are in the folder.
Installing it
Same pack, same steps: ComfyUI Manager, search Batch Folder Tools, install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/hodgemann/ComfyUI-BatchFolderTools.git
pip install opencv-python
That pip install is the one real dependency in this pack - the image loader, save node, and queue node all run on what a stock ComfyUI ships; the video loader is the only node that needs OpenCV (cv2). Forget it and the node raises an ImportError with that exact command in the message. On a ComfyUI Manager install, Python dependency handling may or may not have gotten it for you - if the video loader errors with cv2 not found, run the pip line yourself and restart.
Where people get burned
- A video that won't open (corrupt file, codec your OpenCV build can't read) raises "Cannot open video" and, because it throws mid-loop, the batch stops. You'll see it in the console; the counter has already advanced, so it won't retry the bad file endlessly.
all_frameson long clips is the VRAM trap - if you crash a batch halfway through,skip_captionedgets you back to where you were.- The supported extensions are MP4, AVI, MOV, MKV, WebM, FLV, WMV, M4V. Throw a
.tsor.mpgat it and it's quietly ignored until "no video files found" hits you.
One config note: 16 frames is a sane default, but for long clips you'll get more representative captions by bumping frame_count rather than switching to all_frames.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| folder_path | STRING | Absolute path to video folder. Supports /mnt/ WSL paths, Linux, macOS, Windows, network shares. | |
| frame_mode | COMBO | first_frame | What to extract: first_frame, last_frame, all_frames, evenly_spaced, or frame_range. |
| frame_count | INT | 161–9999 | Number of frames to extract. Only used in evenly_spaced mode. |
| start_frame | INT | 00–9999999 | First frame index. Only used in frame_range mode. |
| end_frame | INT | -1-1–9999999 | Last frame index (-1 = end of video). Only used in frame_range mode. |
| mode | COMBO | sequential | sequential: auto-advances each execution. manual: uses the index widget. |
| index | INT | 00–9999999 | Video index (0-based). Only used in manual mode. |
| sort_by | COMBO | alphabetical | How to sort the files before indexing. |
| reset_counter | BOOLEAN | false | Reset the sequential counter back to 0. |
| skip_captioned | BOOLEAN | false | Skip videos that already have a caption file. Checks for .txt/.caption/.cap next to the video. Use this to resume an interrupted batch. |
Outputs (9)
| Name | Type | Description |
|---|---|---|
| FRAMES | IMAGE | — |
| folder_path | STRING | — |
| filename_stem | STRING | — |
| filename_full | STRING | — |
| current_index | INT | — |
| total_videos | INT | — |
| frame_count | INT | — |
| fps | FLOAT | — |
| duration_seconds | FLOAT | — |