PySceneDetect: Video → Scenes
Split a video into shots without ever loading all the frames
- video
- images
- scenes_json
- scene_count
Here's the situation that made this node for me: you want to run a real video clip through an img2img or upscale pipeline, but you don't need every frame - you need shots. One frame per cut, the way a storyboard would do it. And you definitely don't want to load the whole clip as a float32 image batch first, because that's how you find out your GPU has 8GB and the video has 12,000 frames.
PySceneDetect: Video → Scenes is the fix. It's a thin, well-made wrapper around PySceneDetect - the battle-tested scene-detection library - that takes a video, finds the cuts, and hands you back one representative frame per scene as a normal ComfyUI IMAGE batch, plus the metadata to know exactly where each scene lives in the timeline.
What it is and why you'd reach for it
In ComfyUI, video work is less about the one model and more about what you do to the frames around it. Scene detection is the front of that chain. Feed it a movie trailer or a camera-roll dump and you get:
- a storyboard - one frame per cut, ready to run through img2img, ControlNet, or a face detailer;
- shot boundaries for keyframing or shot-by-shot prompting on video-to-video work;
- thumbnails for organizing footage without scrubbing it by hand.
The old-school alternative was loading every frame via VideoHelperSuite and doing math on the batch. This node's whole trick is that it doesn't.
How it works
The node takes ComfyUI's built-in VIDEO type straight from the Load Video node. PySceneDetect reads the file, a detector walks it looking for cut points, and only the chosen representative frames get decoded into tensors. No full-frame batch ever exists in RAM.
The method dropdown picks which detector you get:
- content (default): measures frame-to-frame difference. Good all-rounder for hard cuts.
- adaptive: uses a rolling average so it handles slow lighting shifts and fades that would trip up plain content detection.
- threshold: cuts on brightness, good for obvious transitions on luma.
luma_only makes content/adaptive ignore color and compare brightness only - and it doesn't apply to threshold, which stays color-based in PySceneDetect 0.7.
The inputs and outputs that matter
Most of the time you touch three settings:
method- start withcontent, switch toadaptiveif fades and slow motion are causing false cuts.threshold- detection sensitivity (default 27). Higher = fewer, cleaner cuts; lower = more aggressive.min_scene_len_sec- the minimum scene length. Set this to keep the node from chopping a clip into a cut every half second; a non-zero value overridesmin_scene_len_frames.
Worth knowing but optional: representative picks which frame stands in for each scene (start, middle, or end), max_width/max_height downscale keeping aspect ratio, limit_scenes caps the count, and write_thumbs dumps JPEGs into output/scene_thumbs for files-on-disk instead of just tensors.
The outputs wire up plainly:
images- the IMAGE batch, one frame per scene. Preview it, img2img it, save it, whatever.scenes_json- a JSON string with per-scene start/end frame numbers, SMPTE-style timestamps, and durations (plus video info). Feed it to a text preview or parse it in a script.scene_count- an INT, handy for gating downstream logic on how many shots you got.
Installing it
No model downloads, no weights. Through ComfyUI Manager, search Comfyui-SceneDetect and install - it handles the Python deps. Or do it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/hndrr/Comfyui-SceneDetect
cd Comfyui-SceneDetect
pip install -r requirements.txt
Then restart ComfyUI. The requirements are light: scenedetect-headless>=0.7.1,<0.8, opencv-python-headless>=4.9, and numpy - PyTorch already ships with ComfyUI. You do need Python 3.10+ and a ComfyUI build with the built-in VIDEO type. VideoHelperSuite is not required - only the pack's legacy VHS-compatible node uses it.
Common issues
The README's troubleshooting list matches what the source actually does, so trust it:
- Empty or 1x1 black output. That's the node's "nothing to show" fallback. It means either the video failed to decode or no scenes made it past your threshold and minimum scene length. Raise the threshold or loosen
min_scene_len_secfirst; if it's still black, check the codec. - OpenCV can't open the video. Codec or file-path problem - confirm
opencv-python-headlessis installed and the file actually plays. - PySceneDetect version mismatch. Reinstall it within the
0.7.xrange the requirements pin, since the detector APIs shifted between versions. - Memory still exploding? You're probably on the legacy VHS path, which has to hold the whole frame batch. Use the built-in
Load Video→ this node route and the problem mostly disappears.
The genuinely fiddly part is the threshold - what's a cut to one clip is noise to another. Start conservative, check scene_count, and tune; scenes_json shows where each boundary landed.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| video | VIDEO | — | |
| 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 | — |