ComfyUI Node

FOMM Partswap

Animate a face and swap only the parts you choose

By FuouM·Created 2 years ago·Updated about a year ago· 9
FOMM Partswap
  • source_image
  • driving_video_input
  • audio
  • seg_src_viz
  • seg_tgt_viz
  • images
  • audio
  • frame_rate
model_namevox-10segments
frame_rate30.00
blend_scale1.00
use_source_segtrue
hard_edgesfalse
use_face_parserfalse
chosen_seg_indices
viz_alpha0.6

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 dedicated vox-5segments, vox-10segments, vox-15segments models, plus vox-cpk, vox-adv-cpk, and vox-first-order (which reuse a 10-segment config and run the FOMM-style dense-motion path). Default is vox-10segments.
  • chosen_seg_indices - the heart of it. A plain string like 1_2_5 listing 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_indices is 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_edges off) or try use_source_seg.
  • Blurry swapped regions - 256×256 internal resolution again. Upscale the final images output.
CategoryFirstOrderMM

Inputs (11)

NameTypeDefaultDescription
source_imageIMAGE
driving_video_inputIMAGE
model_nameCOMBOvox-10segments6 options: vox-5segments, vox-10segments, vox-15segments, vox-cpk, vox-adv-cpk, vox-first-order
frame_rateFLOAT30.00
blend_scaleFLOAT1.000.6–1
use_source_segBOOLEANtrue
hard_edgesBOOLEANfalse
use_face_parserBOOLEANfalse
chosen_seg_indicesSTRING
viz_alphaFLOAT0.60–1
audiooptAUDIO

Outputs (5)

NameTypeDescription
seg_src_vizIMAGE
seg_tgt_vizIMAGE
imagesIMAGE
audioAUDIO
frame_rateFLOAT