PuppetFace ▸ Load Video
The boring front door to the Puppet Face pack (and why its video loader is the part that matters)
- images
- fps
- frame_count
PuppetFaceLoadVideo doesn't do the fun part. It doesn't draw dots on anyone's face and it doesn't puppeteer anything, yet it's the node you'll hit first with this pack, because the whole "Puppet Face" look - a face mesh plus a cartoon mouse cursor wiggling over expression frames - starts by turning a video into the frame batch everything else eats. Think of it as the pack's own no-ffmpeg substitute for a Load Video node, and once you know its three knobs you'll stop fighting it.
The pack's pipeline: generate a portrait and a few expression frames (the author's framing is GPT Image → LivePortrait or Wan 2.2), overlay a landmark mesh and animated cursor, then export an MP4. Load Video is what you use when the input isn't generated frames but a clip you recorded or downloaded. It reads the file with OpenCV and outputs three things: an IMAGE batch (RGB frames, 0–1 float, exactly what ComfyUI nodes expect), the effective fps, and frame_count. Wire images into the overlay node and connect fps through to the saver so playback speed survives.
The three inputs that actually matter
The dropdown, video, is populated from files in your ComfyUI input folder - the same one where you drag images. Drop a clip there, refresh, and it shows up. Supported extensions include .mp4, .mov, .webm, .mkv, .avi, .gif and .m4v. No videos present? The box helpfully offers the literal placeholder (drop a video in input/ then refresh). Running it like that just errors; that's not a bug, it's the prompt.
The other three required inputs are the memory dials, and you will need them:
frame_load_cap(default 0) - stop after this many frames. 0 means no cap.select_every_nth(default 1) - keep every Nth frame. Handy for a 30 fps clip you only want at 10 fps.max_side(default 0) - resize so the longest side is this many pixels; 0 keeps the original size.
Here's the trap that bites everyone once: videos come in as a giant tensor in RAM/VRAM. A 30-second 1080p clip at 30 fps is ~900 frames, and each one is ~25 MB as float32 - over 20 GB before you do anything clever. If a high-res clip makes your machine crawl, frame_load_cap and max_side aren't optional extras, they're the fix. Note select_every_nth changes the output fps too (it divides the source rate by N), so if you sample every 3rd frame of a 30 fps clip you get 10 fps out - feed that into the saver or your animation will run at the wrong speed.
One optional input worth knowing: path_override. Set it to a full path to any video anywhere on disk and it overrides the dropdown - it even tolerates Windows' "Copy as path" quotes. This is the escape hatch when you don't want to copy media into the input folder.
How it actually behaves
Under the hood it's plain cv2.VideoCapture: decode, BGR→RGB, optional downscale (only ever downscales, never upscales), stack, normalize. No models, no downloads, no ffmpeg binary to chase. It also registers the source file's modification time as its cache key, so if you overwrite the clip the node re-runs on the next queue - nice for iterating on footage without clearing the cache. One honest caveat: it decodes video only, never audio, and this pack's MP4 saver doesn't mux sound either. If your project needs the original soundtrack, you'll be remuxing it in after.
Installing it
This pack is so new (first release September 2026) that ComfyUI Manager support isn't confirmed yet - the Registry entry exists but the Manager listing was still pending, so don't hunt for it in the Manager search and get frustrated. The reliable path is git:
cd ComfyUI/custom_nodes
git clone https://github.com/mariobilly/msch-puppet-face.git
cd msch-puppet-face
# same Python environment as ComfyUI!
python -m pip install -r requirements.txt
Then restart ComfyUI. The requirements are just numpy, Pillow, torch, and opencv-python - you almost certainly have the first three already, so opencv-python is the only real addition. On the Windows portable build, use .\python_embeded\python.exe -m pip install ... instead.
The gotcha nobody tells you
If a file refuses to open or you get a "no frames decoded" error, it's usually OpenCV's codec coverage, not your file - the pip opencv-python wheel bundles a broad but not universal ffmpeg build, so an exotic codec in an .mkv can fail where .mp4 (H.264) sails through. Re-encode the clip and move on.
One more thing, so you don't install a zombie: the author has folded this whole pack into a unified MSCH Nodes collection and marked this standalone repo as superseded. Existing installs keep working fine, but for anything new you'd rather install the merged pack and avoid duplicate nodes later.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| video | COMBO | 1 options: (drop a video in input/ then refresh) | |
| frame_load_cap | INT | 00–100000 | — |
| select_every_nth | INT | 11–100 | — |
| max_side | INT | 00–4096 | 0 = keep original; else resize longest side |
| path_overrideopt | STRING | Full path to ANY video; if set, overrides the dropdown. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| fps | FLOAT | — |
| frame_count | INT | — |