ComfyUI Node

VideoFrameExtractor

One MP4 in, every frame plus per-frame masks out

By bruefire·Created 3 years ago·Updated about a year ago· 48
VideoFrameExtractor
    • images
    • mask_images
    • image_count
    sequence_id
    start_index0
    end_index0

    Video-to-video editing in ComfyUI has a boring prerequisite nobody warns you about: you need every frame on disk as a separate image, and for most edits you also need a mask on at least some of them. VideoFrameExtractor (registered in the node menu as "Video Loader With Mask Editor") is exactly that prep step, with a paint-on-canvas GUI bolted on. Point it at an MP4, it extracts all the frames, and hands you a batch of images plus a per-frame mask editor without you ever touching ffmpeg or writing a shell loop.

    It comes from bruefire's tiny pack, ComfyUI-SeqImageLoader - released back in December 2023 for the AnimateDiff crowd and still the low-friction input stage for Wan-based editing. The repo even ships a wan_video_wrapper.json that routes these frames and masks straight into WanVideoEncode for masked video editing: swap a logo, re-dress a subject, keep the camera motion. Masks are exactly the thing the masked-inpainting crowd still insists on over whole-frame edit models, because unmasked pixels come back bit-identical.

    How it works

    The interesting bit: frame extraction happens in your browser tab, not in Python. The node reuses getVideoFrames.js to decode the MP4 client-side, so there's no ffmpeg binary and no PyAV in your Python environment - which is why installing this pack is genuinely painless. Decoded frames get written to ComfyUI/input/extVideoFrame<id>/, and the sequence_id widget is just the internal path blob the upload button fills in. You never type it.

    Once frames are loaded, right-click the node and pick Open In MaskEditor. The editor is built on ComfyUI's standard Mask Editor: a magic-wand auto-select for the "I want the subject" case, a manual brush, and a sketch layer that gets composited into the image output. Right-click paints the mask, left-click erases it. Two genuinely useful extras: a "paste mask from previous frame" button (huge for video, where masks barely change between frames) and an adjustable brush thickness.

    Inputs and outputs that matter

    Only three inputs, and only two you ever touch:

    • sequence_id - ignore it. The upload button fills it for you.
    • start_index / end_index - both default to 0, meaning "no limit, load everything." If you set them, they act as a 1-based slice into the sorted frame list, so "frames 10–60" becomes a two-integer filter. Nice when you only want to edit a section.

    Outputs:

    • images - the frame batch as one IMAGE tensor, sketches composited in.
    • mask_images - white-on-black per-frame masks, as IMAGE. Wire them through an ImageToMask node to feed MASK inputs like SetLatentNoiseMask or WanVideoEncode.
    • image_count - just an INT with the frame count.

    Install

    ComfyUI Manager → search "SeqImageLoader", or the manual way:

    cd ComfyUI/custom_nodes
    git clone https://github.com/bruefire/ComfyUI-SeqImageLoader
    

    Restart ComfyUI. There's no requirements.txt and no model download - it only needs the torch/PIL/numpy ComfyUI already ships.

    Gotchas

    • MP4 only. WebM, MKV, MOV will not work. Transcode first: ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p input.mp4.
    • Frames pile up in input/extVideoFrame*/ and never get cleaned automatically. Delete the ones you've finished with.
    • Undo/redo in the editor is Alt+Z / Shift+Alt+Z, not Ctrl+Z - Ctrl+Z fires ComfyUI's own undo and will do something you didn't ask for.
    • You get frames, not audio. Reassemble sound with VHS_VideoCombine or your editor.
    • Long videos mean one huge IMAGE batch, so your sampler's VRAM - not this node - sets the ceiling. Clip first.
    Categoryimage

    Inputs (3)

    NameTypeDefaultDescription
    sequence_idSTRING
    start_indexINT0
    end_indexINT0

    Outputs (3)

    NameTypeDescription
    imagesIMAGE
    mask_imagesIMAGE
    image_countINT