LoadJPGFrame
Load One JPG Out of a Numbered Frame Sequence — the Workhorse Nobody Notices
- IMAGE
- FLOAT
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.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| frame | INT | 11–100000 | — |
| frameRate | INT | 00–144 | — |
| path | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| FLOAT | FLOAT | — |