Nodes/ComfyUI-CustomNodePacks/Load Video Path (C2C)
ComfyUI Node

Load Video Path (C2C)

The loader for files that aren't in your input folder

By Code2CollapseΒ·Created 8 months agoΒ·Updated about 18 hours agoΒ· 59
Load Video Path (C2C)
  • vae
  • IMAGE
  • frame_count
  • audio
  • video_info
  • video
  • mask
  • info
β—„videoβ€”β–Ί
β—„force_rate0β–Ί
β—„custom_width0β–Ί
β—„custom_height0β–Ί
β—„frame_load_cap0β–Ί
β—„skip_first_frames0β–Ί
β—„select_every_nth1β–Ί
β—„formatNoneβ–Ί
β—„sequence_fps24.00β–Ί
β—„crop_x0.000β–Ί
β—„crop_y0.000β–Ί
β—„crop_w1.000β–Ί
β—„crop_h1.000β–Ί
β—„decoderautoβ–Ί
β—„seconds_cap0.0β–Ί
β—„resolutioncustomβ–Ί
β—„divisible_by1β–Ί
β—„audio_when_missingsilenceβ–Ί
β—„handlesoffβ–Ί
β—„handle_frames8β–Ί
β—„handle_target0β–Ί
β—„handle_sideheadβ–Ί
β—„handle_gridfrom formatβ–Ί
β—„handle_custom_step4β–Ί
β—„handle_custom_plus1β–Ί

Every video widget in ComfyUI lists files from ComfyUI/input/. That's fine for experiments and infuriating for actual work, where the plate lives on the NAS, on an external drive, or anywhere other than the one folder the widget can see. This node takes a path string instead, and it takes an image sequence or a sequence pattern too - so one node covers D:/plates/interview.mov and /mnt/nas/shot_010/####.exr.

Same output set as its sibling: IMAGE (or LATENT if you wire a VAE), frame_count, audio, video_info in VideoHelperSuite format, the lazy C2C_VIDEO handle, and mask.

What you type and why it validates

video is a plain string and the node checks it before the run: if there's nothing at that path, you get a message naming the absolute path it tried - with the quote-stripping applied, so a pasted "D:\plates\clip.mov" works. Sequences are detected by extension (EXR, HDR, PNG, JPG, TIFF, DPX) or by pattern (####, %04d, $F4, [1-10]), so a folder of frames and a shot_####.exr string are both legitimate inputs.

Everything else matches Load Video (C2C) - force_rate (0 keeps source), custom_width / custom_height (0 derives one from the other), frame_load_cap, skip_first_frames, select_every_nth, and the format preset that rounds frames onto a model's grid and snaps dimensions to its required multiple. If a clip came out shorter than you selected and you didn't ask for it, format is the first thing to check.

The extra widget here is sequence_fps. A video file carries its own frame rate; a folder of EXR frames does not. This is how you tell the loader what the sequence's rate is - 24 by default - and it matters the moment anything downstream cares about time rather than just frame order. Audio has no meaning for a sequence, so the audio output stays empty there.

The lazy decode, and why it's not just a gimmick

The node reads the container or sequence header first and returns frame_count plus a C2C_VIDEO handle without touching pixels. Actual decoding happens only if the IMAGE/LATENT output is wired to something, and then only for the frames your skip/nth/cap selection kept. The batch is also checked against free system memory before it's allocated, and if it doesn't fit you get a refusal with the numbers and a suggested frame cap rather than an out-of-memory death halfway through a queue.

That's the difference between a loader you can put at the top of a graph and one you're scared of.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git

Or "CustomNodePacks" in ComfyUI Manager, then restart. Decoding is via PyAV (av), which modern ComfyUI builds already include; if it's missing, pip install av in ComfyUI's own Python environment. No model downloads. Don't blanket-install the pack's requirements.txt over a working install - opencv-python, scipy, safetensors are the real hard requirements and ComfyUI already provides torch, numpy, torchvision and Pillow.

Where people get burned

Absolute paths are absolute, and ComfyUI may be running in a container, a WSL distro, or on a different machine from the one you're browsing on. /mnt/nas/... on your desktop isn't the same filesystem the server sees. When the validation says nothing's there, believe it and check from inside the server's environment.

Second: an EXR sequence is read as-is, and the pack's own pipeline treats images as normal 0–1 floats downstream. If you're loading 16-bit linear plates and expecting ACES-correct colour, you want the pack's colour-science nodes in the chain rather than assuming the loader did the transform.

Third: this is the loader the Image Mask Editor can show frame-by-frame without a run, along with the input-folder version - which is a genuinely nice pair for rotoscoping, since it means you paint masks on the real frames instead of on a stale preview.

Category🐺 C2C/🧰 Core/Video

Inputs (26)

NameTypeDefaultDescription
videoSTRINGPath to a video file or image sequence.
force_rateFLOAT00–240Output FPS; 0 keeps source.
custom_widthINT00–16384Output width; 0 keeps source or derives from height.
custom_heightINT00–16384Output height; 0 keeps source or derives from width.
frame_load_capINT00–1000000Max frames; 0 = no cap.
skip_first_framesINT00–1000000Skip this many frames first.
select_every_nthINT11–100000Keep every Nth frame.
vaeoptVAEEncode to LATENT instead of IMAGE.
formatoptCOMBONoneModel preset (frame grid / dim multiple).
sequence_fpsoptFLOAT24.001–240FPS for image sequences only.
crop_xoptFLOAT0.0000–1Crop, as a fraction of the frame (x, y, width, height; 0, 0, 1, 1 = no crop). Set it with the Crop tool in the player; custom_width / custom_height then resize the cropped frame.
crop_yoptFLOAT0.0000–1Crop, as a fraction of the frame (x, y, width, height; 0, 0, 1, 1 = no crop). Set it with the Crop tool in the player; custom_width / custom_height then resize the cropped frame.
crop_woptFLOAT1.0000–1Crop, as a fraction of the frame (x, y, width, height; 0, 0, 1, 1 = no crop). Set it with the Crop tool in the player; custom_width / custom_height then resize the cropped frame.
crop_hoptFLOAT1.0000–1Crop, as a fraction of the frame (x, y, width, height; 0, 0, 1, 1 = no crop). Set it with the Crop tool in the player; custom_width / custom_height then resize the cropped frame.
decoderoptCOMBOautoauto: the fast path only where it is faster with the same colour - measured, that is the exact reader on the tested machine. fast: ffmpeg decodes 8-bit 4:2:0 video (the same frames; on an NVIDIA GPU the colour conversion runs there, mean 0.5/255 from the exact reader). exact: the frame-accurate PyAV reader (10-bit, HDR, alpha, ProRes and image sequences always use it).
seconds_capoptFLOAT0.00–86400Load at most this many seconds after skip_first_frames (0 = no limit), at the force_rate rate when set. Works with frame_load_cap: the smaller one wins, and a format preset then snaps the count.
resolutionoptCOMBOcustomOutput size by its LONGEST side, keeping the aspect: 2160p is 3840, 1080p is 1920. custom uses custom_width / custom_height (0 = keep the source size or follow the aspect). source ignores them.
divisible_byoptCOMBO1Round both output dimensions to a multiple of this. A format preset or a VAE may raise it.
audio_when_missingoptCOMBOsilenceWhen the file has no audio: silence outputs a silent track as long as the loaded frames (what the loader always did, so downstream nodes keep working); none outputs nothing.
handlesoptCOMBOoffHandles = extra frames for a video model to settle on, added here and trimmed off again by Save Video (C2C) (it reads them from video_info). fit: pad the clip UP to the model's frame grid (handle_target = frames you want out, 0 = this clip's length). add: put handle_frames on, rounded onto the grid. Repeated edge frames, never black; the audio moves with them.
handle_framesoptINT80–400add: frames to put on (side both: on EACH end). With a grid, 0 = just enough to land on it.
handle_targetoptINT00–1000000fit: how many frames you want out after the trim. 0 = this clip's own length.
handle_sideoptCOMBOheadWhich end gets the handles. head is where a video model settles; both splits them.
handle_gridoptCOMBOfrom formatThe model's frame grid: 'from format' uses the format preset above (MiniMax H3 17n+5, Wan 4n+1, LTXV 8n+1 ...), so there is one grid, not two; or pick one here.
handle_custom_stepoptINT41–1000custom grid: step (frames = step * n + plus).
handle_custom_plusoptINT10–1000custom grid: plus.

Outputs (7)

NameTypeDescription
IMAGEIMAGE,LATENTβ€”
frame_countINTβ€”
audioAUDIOβ€”
video_infoVHS_VIDEOINFOβ€”
videoC2C_VIDEOβ€”
maskMASKβ€”
infoSTRINGβ€”