ComfyUI Node

LoadJPGFrame

Load One JPG Out of a Numbered Frame Sequence — the Workhorse Nobody Notices

By BetaDoggo·Created 2 years ago·Updated 2 years ago· 16
LoadJPGFrame
    • IMAGE
    • FLOAT
    frame1
    frameRate0
    path

    LoadJPGFrame is the quiet sibling of Load Video Frame. Instead of pulling a frame out of a video file with OpenCV, it reads one image out of a folder of sequentially-numbered JPGs. No glamour, but it's the most predictable node in the pack: point it at a directory, give it a frame number, get a standard IMAGE tensor back. That makes it genuinely handy for frame-accurate batch img2img - the workflow where you've already exported your video to frames and don't want OpenCV re-decoding the whole file for every single step.

    What it actually does

    Three inputs: path (the folder), frame (1-based number), and frameRate. It builds the filename as frame zero-padded to five digits - so 1 becomes 00001.jpg - opens it with PIL, converts to RGB, normalizes to the 0–1 range, and returns it as an image tensor with a batch dimension. Same FLOAT timestamp and pacing behavior as LoadVideoFrame: frameRate > 0 sleeps 1/frameRate seconds per call and returns frame/frameRate as the timestamp; set it to 0 for unthrottled batch work.

    The gotcha that gets everyone

    The README's manual workflow talks about frames "generated by convert-video.py" - but read the source and the two don't match. convert-video.py writes .txt emoji files named 1.txt, 2.txt... while LoadJPGFrame expects zero-padded .jpg files like 00001.jpg. It will not read what the pack's convert scripts produce. The node that reads those .txt files is the pack's fifth node, LoadFrame - a different one.

    So if you actually want to use LoadJPGFrame, you need JPG frame sequences from somewhere else. The classic source is ffmpeg:

    ffmpeg -i video.mp4 -vf fps=24 frame_%05d.jpg
    

    That produces frame_00001.jpg-style files matching the node's naming. Or any tool that exports zero-padded frame sequences, including frames generated by AnimateDiff or LTX-Video - anything that lands as numbered JPGs. If the file doesn't exist, you get a RuntimeError from the read, so make sure your frame counter stops at the last real frame.

    Inputs and outputs

    • frame - which image to load, 1-based.
    • frameRate - 0 for batch mode, or your source FPS for paced playback.
    • path - the folder. Quotes auto-stripped ("Copy as path" friendly), and a trailing slash is fine.

    Outputs: IMAGE (into img2img or anything that eats an image) and FLOAT (the frame/frameRate timestamp when pacing is on).

    Install

    Same as the rest of the pack - ComfyUI Manager (search "VideoPlayer") or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/BetaDoggo/ComfyUI-VideoPlayer
    

    Restart. opencv-python comes in via the pack's requirements.txt even though this node itself is pure PIL - you're not paying anything extra. No models to download.

    It's a small utility from a small pack, and it's honest about being one: file exists, it loads; file doesn't, clear error. If your workflow runs on exported frame sequences rather than raw video files, this is the node you'll actually end up relying on.

    CategoryVideoPlayer

    Inputs (3)

    NameTypeDefaultDescription
    frameINT11–100000
    frameRateINT00–144
    pathSTRING

    Outputs (2)

    NameTypeDescription
    IMAGEIMAGE
    FLOATFLOAT