Load Video (Nodes 2.0 only) [BETA]
This video loader plays your clip inside the node — but only on the Nodes 2.0 frontend
- frames
- audio
- fps
- frame_count
Sooner or later you stop generating video and start editing it. You have a clip - a phone recording, something you rendered last week - and you want it as frames, in an IMAGE batch, so the image half of ComfyUI can chew on it: ControlNet passes, depth, upscaling, interpolation, or a Wan/LTX video-to-video run. That's the job this node does, with a real <video> player inside the node so you can see what you're feeding in without running the graph.
If you've done this before, you did it with VideoHelperSuite's Load Video (Upload). That's the incumbent and still fine. This is the same idea with better in-canvas ergonomics and a couple of sharp edges the README doesn't spell out.
What it actually does
The Python side is PyAV, not ffmpeg-the-cli. It opens the container, takes the first video stream, demuxes packet by packet and decodes each frame into the [N, H, W, C], 0.0–1.0 float tensor every image node in ComfyUI expects. Audio is decoded alongside it and concatenated into the {"waveform", "sample_rate"} dict audio nodes want. FPS comes from the stream's average_rate.
The JavaScript layer explains the node's weird name. It registers a DOM widget holding a video element, and the pack adds two backend routes for it: /inputvideo serves the file out of ComfyUI/input, and /get_video_metadata reads FPS and total frame count from container metadata without decoding a single frame. Resolution, fps and frame count show up as overlays on the player, which also actively hides the preview element the new frontend draws. All of that reaches into the Nodes 2.0 Vue DOM - hence Nodes 2.0 only. On the legacy canvas those selectors don't exist and the node renders wrong; it's a pack written for the new frontend rather than broken by it.
The two widgets, four outputs
Only two inputs exist, and one of them you'll never type into:
video- a dropdown listing every.mp4,.avi,.mov,.mkv,.webmfound recursively underComfyUI/input, plus drag-and-drop/upload. SelectingNoneis the off position.max_frames- integer, default0, tooltip in the author's own words: "0 = all". This is the one you set.
frames is the batch, and it wires into anything image-shaped: VAE Encode, a preprocessor, Save Image (which writes every frame out as its own PNG), or a video model. audio goes to Save Audio, a lip-sync node, or - handily - straight into Video Maker V2 from this same pack, whose inputs are exactly images, fps, audio and a trim_audio toggle. fps and frame_count are the bookkeeping pair: feed fps to that encoder, and use frame_count to size a generation instead of guessing.
One distinction that looks like a bug but isn't: the player overlay shows the total frames in the file, while frame_count reports what was actually loaded. Cap max_frames at 81 and the player still says 400, because the file still has 400.
Installing it
ComfyUI Manager, search DemonAlone-JS_Addon-ComfyUI, or:
cd ComfyUI/custom_nodes
git clone https://github.com/DemonAlone/DemonAlone-JS_Addon-ComfyUI
Restart ComfyUI. No models to download. There's no requirements.txt, and the pyproject.toml declares no dependencies, so nothing extra installs - but the module does import av (PyAV), which ComfyUI already pulls in for its own video nodes. If you somehow get ModuleNotFoundError: No module named 'av', pip install av into that same environment.
Where people get tripped up
The dropdown looks empty right after you add a clip. The file list is built when the node's inputs get built, so a video you copied into ComfyUI/input by hand won't appear until the page refreshes. The node's own upload widget handles the refresh itself; dropped-in files don't.
Uploads land in ComfyUI/input under the bare filename and overwrite whatever's there. Two clips called output.mp4 and the second one deletes the first. Rename before you drop.
Long clips are an image batch, and image batches are memory. 300 frames of 1080p float32 is roughly 7.5 GB sitting in RAM before anything else runs - use max_frames. It truncates the audio to match, too, since the demux loop stops at the cap.
Do the frame math for your target model before you load. Wan's native window is 81 frames, LTX wants counts of 8n+1 - set max_frames to fit rather than loading 400 frames and slicing later.
Expect some paranoia about color. Video loaders in this ecosystem have a documented history of hue shifts; VHS's loader had a well-known pink-skin bug that took a separate FFmpeg-based node to fix. If colors look off after a load/re-encode round trip, suspect the pipeline before the model.
Picking None doesn't give you a blank batch. Downstream image nodes will complain. Unplug the branch instead.
It takes a file off your disk, hands you frames, sound and timing, and the same author's encoder takes them straight back. That's the whole loop.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| video | COMBO | 2 options: None, No video files found | |
| max_frames | INT | 00–1000000 | 0 = all |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| frames | IMAGE | Batch of video frames as images (torch.Tensor) [N, H, W, C] |
| audio | AUDIO | Dictionary with 'waveform' and 'sample_rate', or None if no audio |
| fps | FLOAT | Frames per second of the video (float) |
| frame_count | INT | Actual number of frames loaded, respecting the 'max_frames' limit |