Nougan Load Video Batch From Folder ποΈ
Caption a folder of clips without hitting Queue 200 times
- frames
- audio
- filename
- path
- index
- total
- fps
- video
Almost every video node in ComfyUI loads one path per run. Captioning a video LoRA dataset, then, means a hundred clips and a hundred Queue presses - and somewhere around clip forty you lose track of which ones you've done. This node deletes the chore: point it at a folder, press Run once, and it walks the folder itself, one clip per execution, until it runs out.
The pack ships workflow/Nougan_Video_Captioning_Workflow.json doing exactly that - loader β VLM captioner β the pack's Save Caption node - and the same graph batch-processes clips through an upscale or interpolate graph unattended.
How it actually works
folder_path gets listed non-recursively and filtered to video extensions (.mp4 .mov .mkv .webm .avi .m4v .flv .wmv .mpg .mpeg .ts .3gp). Then sort_mode orders the list, index picks one file with a modulo (index % total, so an out-of-range index wraps instead of erroring), and PyAV decodes it into a single IMAGE batch.
The frames aren't streamed, they're all held in memory as one tensor, which is the honest cost of this node: a 4K/60 clip is a VRAM event. frame_load_cap and resize_longest_side exist for that reason, and select_every_nth thins frames while recomputing the reported fps, so downstream playback timing stays correct. force_rate only ever reduces frame rate (the code only resamples when the target is below the source), so setting it higher than the clip's own fps does nothing.
Audio is decoded separately, resampled to stereo, and sliced to the same window your frame options selected, so it stays in sync even when you skip into the middle of a clip. Silent clips come back as ten milliseconds of silence rather than None, so audio-expecting nodes downstream don't crash.
The whole-folder loop is frontend, not backend: web/nougan_folder_batch.js listens for each successful execution, bumps index, and re-queues. So the loop needs a live browser session, and it stops dead the moment a clip errors.
Inputs worth touching
folder_path- quotes,~and%ENV%are all stripped/expanded, so a Windows "Copy as path" paste works as-is.sort_mode- numeric is natural order (clip2beforeclip10,001, 002, 10), alphabetical is plain case-insensitive AβZ. If your dataset is numbered, leave it on numeric.auto_run_folder- the labeled toggle: run whole folder advances itself, single video runs just the currentindex. Turn it off while you're testing prompts.frame_load_cap/resize_longest_side- your VRAM insurance. Start at something like 121 frames and 720β1024 px longest side, then raise.
Outputs
frames is the decoded IMAGE batch - feed it to a captioner, an upscaler, or a video model. audio is an AUDIO dict for the same window. filename is the stem with no extension (nice for naming captions), while path is the full path - wire path, not filename, into anything writing a file next to the source clip. index and total tell you where you are in the folder, fps carries the effective frame rate for reassembly, and video is ComfyUI's native VIDEO type when your build has it.
Install
ComfyUI Manager β search Nougan, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Winnougan/Nougan_Nodes
# restart ComfyUI
The pack declares no Python dependencies (dependencies = [] in pyproject.toml), but the decode path imports PyAV lazily, inside the function. PyAV ships with ComfyUI core, so a normal install is fine; on a hand-built venv you'll meet ModuleNotFoundError: No module named 'av' at execution time, not boot - pip install av into ComfyUI's own environment fixes it.
Where it bites
It does one clip and stops. The auto-run loop is the JS extension, so a stale browser cache or a missing web/ file means no loop - hard refresh (Ctrl+F5). The π Refresh folder button it adds hits a backend scan route: it re-counts the folder, resets index to 0 if it was past the end, and previews the current clip's first frame without running the graph.
Everything queues twice. Two copies of the loader in custom_nodes means two extensions both re-queueing - the pack kept the node ID short so older standalone installs kept loading, which is how the old copy hangs around and fights the new one. Delete one and restart. Also leave the queue's batch count at 1.
"No videos found inβ¦" is nearly always a subfolder (they aren't scanned) or an extension outside the list above. A folder of .pngs is invisible here by design - that's FolderImageBatchLoader, same pack.
"video" output is empty on older ComfyUI builds. The console says so plainly and tells you to use frames + audio; do that.
You swapped a clip and it still renders the old one. Its cache fingerprint is path + mtime + size + file count, so touch the file if your filesystem preserved the original timestamp.
One last note on the pack: it's a hobbyist suite from the person behind the Krea 2 quantizations, grown out of his own workflow glue. The README doesn't even list these loaders, and the docs cover the image variant far better than the video one. When a detail matters, read the source - it's short and it's what runs.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| folder_path | STRING | β | |
| sort_mode | COMBO | 2 options: numeric (001, 002, 10...), alphabetical | |
| index | INT | 00β16777215 | β |
| auto_run_folder | BOOLEAN | true | β |
| force_rateopt | FLOAT | 0.00β120 | β |
| frame_load_capopt | INT | 00β100000 | β |
| skip_first_framesopt | INT | 00β1000000 | β |
| select_every_nthopt | INT | 11β1000 | β |
| resize_longest_sideopt | INT | 00β8192 | β |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| frames | IMAGE | β |
| audio | AUDIO | β |
| filename | STRING | β |
| path | STRING | β |
| index | INT | β |
| total | INT | β |
| fps | FLOAT | β |
| video | VIDEO | β |