Video Overlay (画中画合成)
Stick a video on top of a video — no GPU, no VRAM, just ffmpeg
- video_path
The compositing you keep meaning to do in ComfyUI - a talking head over your footage, a generated character over a scene, a picture-in-picture insert - usually means either installing half a video editor or exporting frames and gluing them back together outside the graph. VideoOverlayNode from GuardSkill's ComfyUI-VideoOverlayFFmpeg pack skips all of that. You hand it a base clip, a smaller clip, and a mask, and it returns a finished MP4 with the small clip composited wherever you want it. The heavy lifting happens in ffmpeg, so this costs zero VRAM and zero GPU time - it's one of the rare ComfyUI nodes that runs entirely on CPU and still finishes before your next diffusion step does.
What it's actually for
Picture-in-picture is the core use case: webcam insert over gameplay, a character standing on top of a scene you generated, a logo or lower-third that moves, two clips that need to coexist in one frame. It's also the honest end of a "face swap into a video" workflow - you render the swapped person as a clip with a mask, then composite instead of trying to do it in one shot.
The nice part is that the mask is a video, not a still. You can drive moving alpha (white = opaque, black = transparent), which is what makes a person appear to stand in the scene rather than float awkwardly over it. That's also where people get burned first: the mask must be grayscale or single-channel, or you'll get color weirdness instead of transparency.
How it works
The node builds an ffmpeg filter graph with ffmpeg-python: it probes both videos for size and duration, scales the small clip to size_ratio of the base clip's height, runs the mask through format=gray + alphamerge, then overlays it at your chosen position with margins. Duration mismatches are handled automatically - if the small clip runs out early it freezes its last frame with tpad, and if the base is shorter it loops. Speed changes ride along with setpts/atempo filters, and audio is mixed using the two volume inputs. Everything gets encoded as libx264 + aac with +faststart, dumped to ComfyUI/output/overlay_xxxx.mp4, and pushed to the front-end preview.
The inputs that matter
Paths are plain strings - big_video_path, small_video_path, mask_video_path. The README warns to use absolute paths and avoid spaces/Chinese characters in them; that advice exists because a bad path is the #1 way this node fails.
The rest are a short list worth touching:
size_ratio(default 0.25) - small clip height as a fraction of the base height. This is your one-stop "make it bigger."position- one ofright_bottom,right_top,left_bottom,left_top,center, plusmargin_x/margin_yto push it off the corner.opacity(0–1) - extra fade on top of the mask.big_video_audio_volume/small_video_audio_volume- note the defaults: base audio is muted (0.0) and the overlay is at 1.0. That's intentional, but it surprises people who expected the base soundtrack.big_video_speeddefaults to 1.8×, which is also worth knowing before you wonder why your base clip races.
The single output, video_path, is the absolute path to the rendered MP4 - wire it to anything that accepts a file path, or just eyeball the preview.
Installing it
No models, no heavy dependencies - the only real requirement is a system ffmpeg on your PATH and the ffmpeg-python pip package. Either install through ComfyUI Manager (search "ComfyUI-VideoOverlayFFmpeg") or:
cd ComfyUI/custom_nodes
git clone https://github.com/GuardSkill/ComfyUI-VideoOverlayFFmpeg
cd ComfyUI-VideoOverlayFFmpeg
pip install -r requirement.txt
Then restart ComfyUI. On the portable Windows build, make sure python_embeded\python.exe can actually call ffmpeg, or you'll get command not found in the console. The preview extension loads automatically via WEB_DIRECTORY - ignore the README's step about manually copying a JS file; the current __init__.py handles it.
Gotchas
If ffmpeg isn't found, add it to PATH and restart. If colors look wrong, your mask isn't single-channel. If nothing appears in the output folder, check the console for the [VideoOverlay] logs - the node is chatty about what it's probing and scaling, which makes most failures self-diagnosing. It's a niche tool, but for "put this clip inside this clip and be done," it's the one I'd reach for.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| big_video_path | STRING | — | |
| small_video_path | STRING | — | |
| mask_video_path | STRING | — | |
| opacity | FLOAT | 1.000–1 | — |
| position | COMBO | right_bottom | 5 options: right_bottom, right_top, left_bottom, left_top, center |
| margin_x | INT | 00–500 | — |
| margin_y | INT | 00–500 | — |
| size_ratio | FLOAT | 0.250.1–1 | — |
| big_video_audio_volume | FLOAT | 0.00–2 | — |
| small_video_audio_volume | FLOAT | 1.00–2 | — |
| big_video_speed | FLOAT | 1.80.25–4 | — |
| small_video_speed | FLOAT | 1.00.25–4 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video_path | STRING | — |