PySceneDetect: Scenes → Images (Legacy VHS)
Cutting a video into shots right inside the graph (no ffmpeg CLI needed)
- image
- video_info
- images
- scenes_json
- scene_count
You've got a long video loaded into ComfyUI and you need it split into shots. Maybe you want a clean keyframe to feed an img2vid node, maybe you're building training data and need scene-level cuts instead of arbitrary 2-second windows, maybe you just want a storyboard of the whole thing. Whatever the reason, the answer is the same: stop doing it by hand, and don't leave the graph to do it. That's what ZNGB-PySceneDetect is for.
This is a single-node pack wrapping PySceneDetect, the long-running Python shot-detection library, into a ComfyUI node. Good news up front: no API, no key, no model download - the only "heavy" thing is a couple of pip packages. It's a preprocessing utility, and in ComfyUI's video pipeline it fills a hole that has no button anywhere else in the UI.
How it works
The name is the honest part: you feed it a batch of frames and it detects where the scenes change. The mechanism is worth understanding because it explains both gotchas below. The node takes your IMAGE batch plus metadata from a video loader, writes those frames back to a temporary video file with OpenCV, runs PySceneDetect's detector on it, and then hands you three things per scene: a representative frame, a metadata blob, and an exported mp4 segment.
Under the hood it's using PySceneDetect's classic detectors - ContentDetector, AdaptiveDetector, ThresholdDetector - so if you've ever used the library from the CLI, the tuning concepts carry straight over.
The inputs that matter
- image and video_info - these are the whole point.
imageis the frame batch, andvideo_infois the fourth output from VHS Load Video (or another compatible loader). The node requires a valid fps value in there; without it, execution fails hard. - method -
content(default),adaptive, orthreshold. Content compares frame-to-frame differences with a fixed threshold, which is the good all-rounder for most footage. Adaptive tunes its own threshold per-window, so it's the one to reach for when your footage mixes slow pans with fast action. Threshold is for detecting hard cuts and brightness flashes - more of a niche tool. - threshold - default 27, the classic content-detector value. Higher = fewer, longer scenes.
- min_scene_len_sec / min_scene_len_frames - the minimum shot length, your filter against noise. If you set the seconds field, it wins over the frames field.
- luma_only - on by default, and worth leaving on for most video: it ignores color changes and only looks at brightness, which avoids false cuts on hue shifts and runs a bit faster.
The rest are optional: representative picks which frame from each scene you get back (start/middle/end), max_width/max_height downscale those frames (0 = keep original), limit_scenes caps the count, and write_thumbs dumps a jpg per scene into thumbs_dir (defaults to ./scene_thumbs).
The outputs
Four of them, and they cover the realistic use cases:
- images - a batch of representative frames, one per scene. Wire this into a preview or a Save Image node and you instantly get a storyboard of your footage.
- scenes_json - a JSON string with fps, method, threshold, and per-scene start/end frame, timecode, and duration. Feed it to a JSON-parsing node for metadata-driven logic, or just read it.
- scene_count - an INT. Handy for a conditional that only proceeds if there are enough scenes.
- path_string - newline-separated absolute paths of the exported mp4 segments.
Note the segments are written to ComfyUI's temp directory, in a fresh random transnet_segments_xxxx/ folder per run, not your output folder. They're also re-encoded by OpenCV (MJPG/mp4v), so don't treat them as frame-perfect lossless rips - they're for convenience, not archival.
Install
ComfyUI Manager will find it if you search "Comfyui-ZNGB-SceneDetect". Otherwise:
cd ComfyUI/custom_nodes
git clone https://github.com/zhinangubei/Comfyui-ZNGB-SceneDetect
pip install -r requirements.txt
The dependencies are just scenedetect, opencv-python, and numpy - no model files, no ffmpeg to hunt down. Restart ComfyUI and you're done.
Where people get burned
The recurring complaint with PySceneDetect in general (one r/StableDiffusion user hit it exactly) is that the cuts come back too granular - a slow pan or a flicker splits into three "scenes" and destroys the consistency you were trying to preserve. Fix: raise threshold, bump min_scene_len_frames, or switch to adaptive. A few minutes of tuning here is the difference between a useful storyboard and a chaotic one.
The other classic footgun is wiring the wrong thing into image. The node rejects LATENT tensors at runtime with a fairly explicit error - if you see it, you've connected the VAE-decoded output from your video loader instead of the frame/image output. And if you skip video_info entirely and feed it from a plain image loader, you'll get the "no valid FPS" error. This node is built around VHS Load Video; give it the fourth output and it's happy.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| video_info | VHS_VIDEOINFO | — | |
| method | COMBO | content | 3 options: content, adaptive, threshold |
| threshold | FLOAT | 27.00–1000 | — |
| min_scene_len_sec | FLOAT | 0.00 | — |
| min_scene_len_frames | INT | 15 | — |
| luma_only | BOOLEAN | true | — |
| representativeopt | COMBO | start | 3 options: start, middle, end |
| max_widthopt | INT | 0 | — |
| max_heightopt | INT | 0 | — |
| limit_scenesopt | INT | 0 | — |
| write_thumbsopt | BOOLEAN | false | — |
| thumbs_diropt | STRING | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| scenes_json | STRING | — |
| scene_count | INT | — |