Nodes/ComfyUI-Sharp-Selector/3. Parallel Video Loader (Sharpness)
ComfyUI Node

3. Parallel Video Loader (Sharpness)

Rip the sharpest frames out of a movie without ever loading it into RAM

By ethanfel·Created 8 months ago·Updated 6 months ago· 2
3. Parallel Video Loader (Sharpness)
    • images
    • scores_info
    • batch_int
    • batch_status
    video_pathC:\path\to\video.mp4
    batch_index0
    scan_limit1440
    frame_scan_step5
    return_count4
    min_distance24
    manual_skip_start0

    The name understates what this node actually does. It's not a video loader that happens to know about sharpness - it's a full pipeline: scan a movie on disk, score every frame's sharpness in parallel, pick the best ones, and only then decode those few into memory. If your goal is training data from a video file, this is the node from ethanfel/ComfyUI-Sharp-Selector you'll actually reach for.

    The problem it solves is a real one. A two-hour movie at 24fps is over 170,000 frames. Decode all of them into RAM just to pick the 10 sharp ones and you've built a machine that OOMs on a Tuesday. This node never does that. Dataset curation is the whole point - the author built the pack for a personal project extracting sharp frames from massive movies without crashing - and everything here is engineered around "score first, decode only the winners."

    How it works (two passes)

    Pass 1 - scan. It seeks to batch_index * scan_limit + manual_skip_start and reads up to scan_limit frames. Each frame's sharpness is computed as Laplacian variance (edge energy - high = sharp) and submitted to a 16-worker thread pool, so a CPU that would otherwise idle is fully occupied while it chews through the movie. frame_scan_step makes it cheaper: check every Nth frame instead of every frame (skipped frames use grab(), which is nearly free). Roughly a thousand-plus frames a minute, all on CPU - so you can be scanning a movie while your GPU is busy generating.

    Selection. Scores are sorted descending, and the code greedily picks the top return_count - but rejects any frame within min_distance frames of one already chosen. That spread requirement is the quiet clever bit: without it you'd get four near-identical frames from the same two seconds instead of four different shots.

    Pass 2 - extract. The file is reopened, seeks straight to each winning frame index, and only those get decoded, converted BGR→RGB, normalized to 0–1, and stacked into one IMAGE tensor. Peak memory is one movie plus a handful of tensors.

    The inputs that matter

    • video_path - absolute path to the file.
    • batch_index - the paging counter. Connect a Primitive node set to increment and enable Auto Queue; each queue pass advances to the next chunk (scan_limit frames at a time) until the movie's done. This is the "scan a whole movie unattended" trick.
    • scan_limit - frames scanned per batch (default 1440, about a minute of 24fps).
    • frame_scan_step - score every Nth frame (default 5).
    • return_count - best N frames to return (default 4).
    • min_distance - minimum frame gap between picks (default 24, roughly one second at 24fps).
    • manual_skip_start - global offset; set it to ~2000 to skip opening credits forever.

    Outputs

    • images - the sharpest frames as a batch, ready for a Save Image node.
    • scores_info - a string like F:1450 (Score:1500), F:2288 (Score:1310) with original frame numbers.
    • batch_int and batch_status - the current page number and a human-readable progress line ("Batch 2: Skipped 2880 frames...").

    The gotcha the README doesn't warn you about

    The README and the bundled example workflow both tell you to wire scores_info into a "Fast Absolute Saver" node that names files by original frame number and embeds scores in metadata. That node does not ship. The installed NODE_CLASS_MAPPINGS registers only the three Sharpness nodes in this pack - load that example workflow and ComfyUI will report FastAbsoluteSaver missing. In practice: save with a regular Save Image and treat scores_info as a log line. It's a real README-outranks-code case.

    Two other behaviors worth knowing. First, running past the end of the file raises a ValueError ("Processing Complete") - ugly, but in an auto-queue workflow that's actually the stop signal: the queue halts instead of looping forever. Second, a batch that finds zero frames also raises, so a corrupted or blank section will hard-stop rather than silently hand you nothing.

    Install

    ComfyUI Manager (search "ComfyUI-Sharp-Selector") or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/ethanfel/ComfyUI-Sharp-Selector
    

    Dependencies are opencv-python and numpy from requirements.txt; restart after. No model files anywhere in the pack - the scanning is pure OpenCV. If you get a cv2 import error, pip install opencv-python, and watch for the opencv-python-headless clash if another pack pulled that in instead.

    CategoryBetaHelper/Video

    Inputs (7)

    NameTypeDefaultDescription
    video_pathSTRINGC:\path\to\video.mp4
    batch_indexINT00–10000
    scan_limitINT14401–10000000
    frame_scan_stepINT5
    return_countINT41–1024
    min_distanceINT240–10000
    manual_skip_startINT00–10000000

    Outputs (4)

    NameTypeDescription
    imagesIMAGE
    scores_infoSTRING
    batch_intINT
    batch_statusSTRING