Nodes/Comfyui-SceneDetect/PySceneDetect: Scenes → Images (Legacy VHS)
ComfyUI Node

PySceneDetect: Scenes → Images (Legacy VHS)

Cutting a video into shots right inside the graph (no ffmpeg CLI needed)

By hndrr·Created 10 months ago·Updated a day ago· 2
PySceneDetect: Scenes → Images (Legacy VHS)
  • image
  • video_info
  • images
  • scenes_json
  • scene_count
methodcontent
threshold27.0
min_scene_len_sec0.00
min_scene_len_frames15
luma_onlytrue
representativestart
max_width0
max_height0
limit_scenes0
write_thumbsfalse
thumbs_dir

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. image is the frame batch, and video_info is 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, or threshold. 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.

CategoryVideo/PySceneDetect

Inputs (13)

NameTypeDefaultDescription
imageIMAGE
video_infoVHS_VIDEOINFO
methodCOMBOcontent3 options: content, adaptive, threshold
thresholdFLOAT27.00–1000
min_scene_len_secFLOAT0.00
min_scene_len_framesINT15
luma_onlyBOOLEANtrue
representativeoptCOMBOstart3 options: start, middle, end
max_widthoptINT0
max_heightoptINT0
limit_scenesoptINT0
write_thumbsoptBOOLEANfalse
thumbs_diroptSTRING

Outputs (3)

NameTypeDescription
imagesIMAGE
scenes_jsonSTRING
scene_countINT