CMK FaceSwap Video
The Node That Started CMK, Still Doing Full-Length Video
- SEGMENTS
- IMAGE SOURCE
- LOG
- SEGMENTS
- LOG
- diagnostic
The pack's own documentation says this node is where CMK began, and that it was deliberately not modernised. That reads like a warning, but it's actually the pitch: it's the one piece of the flow that does the entire job in a single node, and it has had years of use to knock the edges off.
What it is
Give it a set of video segments plus a source face image, and it swaps the target face across every frame - decode, detect, track, swap, re-encode, streaming through ffmpeg pipes so a five-minute clip never lands in RAM as a tensor.
It's not a frame-by-frame detector. That distinction is the whole design. A per-frame "Largest" would jump to a different person the moment someone walks past the camera. This node picks a target once, then tracks it: bounding-box IoU plus an ArcFace embedding comparison, with max_missing_frames (default 12) letting it survive occlusions and bad frames without dropping the identity, and tracking_iou_threshold (0.08) and tracking_embedding_threshold (0.35) deciding when a detection is still the same person. Loosen the embedding threshold and tracking gets clingier; loosen IoU and it survives wilder motion.
Face detection on every frame is exactly the expensive thing in this pipeline - and this pack runs InsightFace through ONNX Runtime's CPU provider by default - so tracking isn't a nicety, it's what makes long clips tractable at all.
What you feed it
SEGMENTS is the pack's CMK_VIDEO_SEGMENTS context - the persistent video project that CMK Split Video into Segments (or the FaceSwap Video Loader) produces. IMAGE SOURCE is your face reference, LOG is the log pipe. All three are required, and the node type-checks them: feed it the wrong dict and you get a TypeError naming the input rather than a mystery crash three modules later.
SEGMENT SELECTION controls scope, and it's the control you'll use most:
- Full Path (Batch) - every segment, the whole video.
- Randomize - one random segment, and it deliberately avoids re-picking the one it used last time.
- Last Used Segment - re-process exactly the segment Randomize landed on. Handy for iterating on one trouble spot without re-running twenty minutes of video.
Randomize forces the node to re-execute every queue (there's no caching a random choice), which is expected behaviour rather than a bug.
The swap controls are the set you know from the image node - SWAP MODEL, DETECT MODEL, FACE ENHANCER (Off or GPEN), TARGET FACE, SOURCE FACE, BLEND, plus the advanced bbox_dilation, crop_factor, drop_size and feather. FACE SWAP off is a real bypass: the segments come back untouched and the log says BYPASSED, so you can park the node in a workflow without deleting it.
Outputs
SEGMENTS is the swapped project context, ready for CMK Merge and Save Video to reassemble and publish. LOG accumulates the per-segment report, and diagnostic carries the run summary including the segment count and selection mode.
The resume behaviour is the good bit
Each run writes a manifest under output/video/face_swap/<video>/<signature>/ keyed on a signature that includes the source manifest, the source image hash, the swap model file and every setting. Per segment, a fingerprint combines that base with the segment's file id and time range. If the fingerprint matches a completed record and the output file is still there, the segment logs REUSED and is skipped.
Practical consequence: you can interrupt a long video swap, restart ComfyUI, run it again, and it picks up instead of starting over. Change one setting and only that changes - everything else is still a hit. This is the one place in the pack where a cache genuinely survives a restart, and it's worth structuring your video work around.
Install
Manager: search CMK Flow, install, restart. Manual, from your ComfyUI root:
git clone https://github.com/CMKFlow/cmk_nodes.git custom_nodes/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py
python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py --models-root "/path/to/ComfyUI-Shared"
You need inswapper_128.onnx and the buffalo_l detector in ComfyUI/models/insightface, plus an ffmpeg binary on the system - the pack depends on imageio-ffmpeg, but it shells out to ffmpeg for the streaming decode/encode. Videos are read from ComfyUI/input/video/.
Where people get burned
The ContentGuard runs on every target frame. It's mandatory, it's local (NudeNet plus InsightFace age estimation), and it aborts the whole run rather than skipping a frame. On a long clip that's a real risk of burning twenty minutes to a hard stop - so run a short segment range first.
CPU inference. The pack's detector and swapper default to CPU providers. Budget accordingly; the tracking keeps detection from dominating, but the swap itself is per frame.
Licensing. The library is MIT, the models are not, and inswapper is research-only. Local experiments, yes. Product, no.
Inputs (18)
| Name | Type | Default | Description |
|---|---|---|---|
| SEGMENTS | CMK_VIDEO_SEGMENTS | — | |
| IMAGE SOURCE | IMAGE | — | |
| LOG | CMK_LOG_PIPE | — | |
| FACE SWAP | BOOLEAN | true | — |
| SEGMENT SELECTION | COMBO | Full Path (Batch) | 3 options: Full Path (Batch), Randomize, Last Used Segment |
| SWAP MODEL | COMBO | 1 options: inswapper_128.onnx | |
| DETECT MODEL | COMBO | 1 options: buffalo_l | |
| FACE ENHANCER | COMBO | Off | 2 options: Off, GPEN |
| TARGET FACE | COMBO | Largest | 6 options: Largest, Leftmost, Rightmost, Topmost, Bottommost, Center |
| SOURCE FACE | COMBO | Largest | 6 options: Largest, Leftmost, Rightmost, Topmost, Bottommost, Center |
| BLEND | FLOAT | 1.000–1 | — |
| bbox_dilation | INT | 0-512–512 | — |
| crop_factor | FLOAT | 1.51–3 | — |
| drop_size | INT | 101–8192 | — |
| feather | INT | 00–100 | — |
| max_missing_frames | INT | 120–300 | — |
| tracking_iou_threshold | FLOAT | 0.080–1 | — |
| tracking_embedding_threshold | FLOAT | 0.35-1–1 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| SEGMENTS | CMK_VIDEO_SEGMENTS | — |
| LOG | CMK_LOG_PIPE | — |
| diagnostic | CMK_DIAGNOSTIC | — |