FOMM Partswap
Animate a face and swap only the parts you choose
- source_image
- driving_video_input
- audio
- seg_src_viz
- seg_tgt_viz
- images
- audio
- frame_rate
FOMM Partswap is where this pack stops being "animate a photo" and gets weird in a useful way. It's the ComfyUI port of the part-swap variant from Motion Supervised co-part Segmentation (Siarohin et al., 2021). Instead of just transferring motion from a driving video onto a source face, it replaces the chosen semantic parts of the target face with the source's. Eyes, mouth, hair, chin - you pick which parts swap and which stay, per frame, across the whole driving clip.
Concretely: it's a face-swap that respects the driving video's motion, with surgical control over what gets transferred. Swap only the mouth for a lip-sync-style result. Swap the whole face to get the driver's motion on the source identity. Leave the hair and background alone. That part-level control is the entire point, and it's the one thing the other runners in this pack can't do.
How it works
A segmentation module predicts semantic segments (5, 10, or 15 regions depending on the model) for the source image and every driving frame. The chosen_seg_indices string tells the node which segments to treat as the "swap" mask - the blend mask is built by summing just those segmentation channels. A reconstruction module then warps the source's pixels onto the target through that mask, so the selected parts ride the driving motion while the rest of the frame comes from the target. If use_source_seg is on (default), the source's segmentation drives the mask, which the README notes can help when the target's regions are missing or poorly detected.
The inputs that matter
model_name- six options: the dedicatedvox-5segments,vox-10segments,vox-15segmentsmodels, plusvox-cpk,vox-adv-cpk, andvox-first-order(which reuse a 10-segment config and run the FOMM-style dense-motion path). Default isvox-10segments.chosen_seg_indices- the heart of it. A plain string like1_2_5listing which segment indices to swap. You normally don't type this by hand - you wire it from a Seg Chooser node (FOMM_Seg5Chooser / Seg10Chooser / Seg15Chooser). Match the chooser to the model's segment count.use_source_seg- use the source's segmentation for the mask instead of the target's. On by default.hard_edges- make the swap boundary hard instead of feathered. Off by default; feathering is usually nicer, hard edges can look cleaner if the segments are well detected.use_face_parser- optional face-parsing pass to clean up residual background. The README says to only use it with the 15-segment model, and to definitely use it for FOMM-style models. Needs the optional face-parsing weights (see below).blend_scale- the author's own tooltip is "No idea, keeping at default = 1.0 seems to be fine." Leave it.viz_alpha- opacity of the segmentation overlay in the two viz outputs, which are color-coded previews of the detected segments (source and target). Great for checking whether the segments are doing what you think.
Outputs: seg_src_viz and seg_tgt_viz (the segment overlays), images (the animated+swapped clip), audio (pass-through), frame_rate.
Install and models
Same pack install - ComfyUI Manager (search "FirstOrderMM") or git clone + pip install -r requirements.txt into custom_nodes/. Deps are light: numpy, torch, scipy, pyyaml, matplotlib, einops, timm.
Model files go in checkpoints/ and are not auto-downloaded: vox-5segments.pth.tar, vox-10segments.pth.tar, vox-15segments.pth.tar, vox-first-order.pth.tar, plus vox-cpk.pth.tar / vox-adv-cpk.pth.tar if you want those two options. All from the motion-cosegmentation repo. If you enable use_face_parser, you also need the two face-parsing weights in the pack's face_parsing/ folder: resnet18-5c106cde.pth and 79999_iter.pth - the node will load fine without them, but that toggle will quietly not work.
Common issues
- Nothing swaps -
chosen_seg_indicesis empty, or you wired a 5-segment chooser into a 15-segment model. The node filters out-of-range indices silently, so a mismatch just means no-op. - Background leaks into the swap - enable
use_face_parser(with its weights installed) on FOMM-style models, per the README. - Harsh seams - turn on feathering (leave
hard_edgesoff) or tryuse_source_seg. - Blurry swapped regions - 256×256 internal resolution again. Upscale the final
imagesoutput.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| source_image | IMAGE | — | |
| driving_video_input | IMAGE | — | |
| model_name | COMBO | vox-10segments | 6 options: vox-5segments, vox-10segments, vox-15segments, vox-cpk, vox-adv-cpk, vox-first-order |
| frame_rate | FLOAT | 30.00 | — |
| blend_scale | FLOAT | 1.000.6–1 | — |
| use_source_seg | BOOLEAN | true | — |
| hard_edges | BOOLEAN | false | — |
| use_face_parser | BOOLEAN | false | — |
| chosen_seg_indices | STRING | — | |
| viz_alpha | FLOAT | 0.60–1 | — |
| audioopt | AUDIO | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| seg_src_viz | IMAGE | — |
| seg_tgt_viz | IMAGE | — |
| images | IMAGE | — |
| audio | AUDIO | — |
| frame_rate | FLOAT | — |