Nodes/ComfyUI-FFMPEGA/FaceCam (FFMPEGA)
ComfyUI Node

FaceCam (FFMPEGA)

Make Wan 2.2 orbit a face without the head melting

By AEmotionStudio·Created 8 months ago·Updated a day ago· 16
FaceCam (FFMPEGA)
  • model_high
  • images
  • model_low
  • vae
  • clip
  • images
  • video_path
  • latent
promptA portrait of a person
negative_prompt
seed0
steps50
cfg_scale5.0
sampler_nameeuler
schedulersimple
high_model_ratio0.20
camera_presetorbit_left
num_frames81
width480
height704
video_path
start_azimuth0
end_azimuth0
start_elevation0
end_elevation0
start_fov40
end_fov40
mesh_sourceauto
blockswap_blocks0
allow_model_downloadstrue

Camera movement is the thing Wan 2.2 will not give you from a text prompt. Ask for "the camera orbits left around her face" and you get a cut, or a face that quietly turns into someone else's. FaceCam fixes that by not asking the model nicely - it draws the camera path onto the frame and hands it over as conditioning.

What it actually is

FaceCam is a partial fine-tune of Wan 2.2 I2V-A14B, trained on portrait video for camera control (CVPR 2026, by the FaceCam authors; this node wraps it). "Partial" is the important word: the shipped checkpoints only carry self-attention and patch-embedding weights, about 402 keys. The node swaps those into a base Wan 2.2 model at runtime. So you don't load FaceCam instead of Wan - you load your normal Wan 2.2 A14B high/low pair and the FaceCam weights ride along on top.

It keeps Wan 2.2's two-pass shape - high-noise model for motion and composition, low-noise model for detail. In this node the split is explicit: high_model_ratio (default 0.2) is the fraction of steps run on the HIGH model, which carries the camera trajectory, and the rest go to the LOW model for refinement. model_low is optional - leave it unconnected and the HIGH model runs every step.

How the camera signal is built

Camera pose is written as a MediaPipe face mesh drawn on your input frame, VAE-encoded, and fed in as the camera condition. The 2.20.0 release changed how that mesh is produced and it's worth knowing which path you're on. mesh_source defaults to auto, which poses MediaPipe's canonical 468-vertex model with the camera matrices directly and projects it. The old detected path rendered a 3D proxy head along the camera path and ran a face detector over the renders - and MediaPipe loses the mesh past roughly 40–50° of yaw, which is precisely the pose an orbit produces. That's why conditioning used to go blank at the ends of a sweep. analytic forces the new path and errors if it can't calibrate. Leave it on auto.

Inputs you'll actually touch

  • model_high (required) and model_low - your Wan 2.2 A14B pair, loaded however you normally load it; the docs assume GGUF via Load Diffusion Model. Plus vae (Wan 2.2 VAE) and clip (T5-XXL).
  • images or video_path - the source frame. Just a frame or two is normal; FaceCam animates from it.
  • camera_preset - eleven options. orbit_left / orbit_right swing the camera to ±45°, zoom_in pushes FOV 50→25°, zoom_out pulls back, look_up / look_down tilt the subject, dramatic_pan, subtle_drift (the most natural), dolly_zoom, random, and custom.
  • width / height - defaults are 480×704, and that's not a lazy default. FaceCam is trained on portrait video; landscape is off-distribution and camera control measurably weakens.
  • num_frames - 81 out of the box, stepping in 4s.
  • blockswap_blocks - 0 disabled and recommended at 24 GB+; 8–16 for 12–16 GB cards, 20+ for 8–12 GB.

Set camera_preset to custom and the manual sliders take over: start_azimuth/end_azimuth (±90°, negative = camera left), start_elevation/end_elevation (±60°, positive = looking down), and start_fov/end_fov (10–60, lower is tighter). Outputs are images, video_path, and a latent you can hand to another sampler or a second FaceCam pass.

Install

ComfyUI Manager → search ComfyUI-FFMPEGA → Install. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/AEmotionStudio/ComfyUI-FFMPEGA.git
pip install -r ComfyUI-FFMPEGA/requirements.txt

Restart ComfyUI. The pack wants FFMPEG on PATH for everything it does. On first FaceCam run the node auto-downloads the FaceCam bf16 checkpoints - roughly 16.8 GB (high + low) into ComfyUI/models/diffusion_models/, plus the landmark task bundle and gaussians file - from AEmotionStudio/facecam-wan2.2-14b-bf16. Your base Wan 2.2 A14B pair is separate and still yours to source. Flip allow_model_downloads off if you'd rather place them by hand; the node then fails with a clear message instead of quietly fetching.

Where people get burned

VRAM. FaceCam doubles the temporal dimension, so it needs noticeably more memory than a plain Wan 2.2 run at the same resolution. If you're on a 12–16 GB card, set blockswap_blocks before you start, not after the OOM.

Sweeps past ~45°. The presets deliberately stop at 45° because that's where the face goes into profile and the landmark tracker loses the mesh. custom will happily let you punch in 90° and hand you mush - the tooltip says so, and it means it.

Patience. A plain Wan 2.2 720p 81-frame clip already runs about 25 minutes on a 5090 at full quality without speed LoRAs. FaceCam is heavier on top of that. Budget the run before you queue five of them.

CategoryFFMPEGA

Inputs (27)

NameTypeDefaultDescription
model_highMODELWan2.2 base model (high-noise)
promptSTRINGA portrait of a person
negative_promptSTRING
seedINT00–4294967295
stepsINT501–200
cfg_scaleFLOAT5.01–20
sampler_nameCOMBOeuler4 options: euler, euler_ancestral, dpmpp_2m, dpmpp_sde
schedulerCOMBOsimple4 options: simple, normal, karras, sgm_uniform
high_model_ratioFLOAT0.200–1Fraction of steps using HIGH model (camera trajectory). Remaining steps use LOW model (detail refinement). 0=all LOW, 1=all HIGH.
camera_presetCOMBOorbit_leftCamera motion preset. Every preset starts at the input pose (frontal) and moves outward, matching what FaceCam was trained on: 'orbit_left' = camera swings left (az 0→-45°). 'orbit_right' = swings right (az 0→+45°). 'zoom_in' = pushes in tight (FOV 50→25°). 'zoom_out' = pulls back wide (FOV 25→50°). 'look_up' = subject looks up (elev 0→-30°). 'look_down' = subject looks down (elev 0→+30°). 'dramatic_pan' = orbit 0→45° + tilt + zoom tightening. 'subtle_drift' = gentle orbit 0→15° + tilt 0→-8° (most natural). 'dolly_zoom' = orbit 0→25° while zooming in (Hitchcock effect). 'random' = randomized direction, up to 45° from frontal. 'custom' = use the manual azimuth/elevation/FOV sliders below. Note: sweeps beyond ~45° push the face into profile, where the landmark tracker loses the mesh and camera control weakens.
num_framesINT815–321
widthINT480128–1920FaceCam is trained on portrait video — upstream defaults to 480×704 (w×h). Landscape is off-distribution and weakens camera control.
heightINT704128–1920FaceCam is trained on portrait video — upstream defaults to 480×704 (w×h).
imagesoptIMAGEInput image/frames (alternative to video_path)
video_pathoptSTRINGInput video path (connect from LoadVideoPath node)
model_lowoptMODELWan2.2 base model (low-noise) for refinement pass. If not connected, HIGH model runs all steps.
vaeoptVAEWan 2.2 VAE
clipoptCLIPT5-XXL text encoder
start_azimuthoptFLOAT0-90–90Horizontal rotation start. Negative=camera left, positive=right.
end_azimuthoptFLOAT0-90–90Horizontal rotation end.
start_elevationoptFLOAT0-60–60Vertical rotation start. Positive=looking down, negative=looking up.
end_elevationoptFLOAT0-60–60Vertical rotation end.
start_fovoptFLOAT4010–60Field of view start. Higher=wider (zoom out), lower=tighter (zoom in).
end_fovoptFLOAT4010–60Field of view end.
mesh_sourceoptCOMBOautoHow camera conditioning is built. 'auto' (recommended) poses MediaPipe's canonical face model with the camera matrices directly — total coverage, perfectly smooth motion, and left/right orbits are exact mirrors. Falls back to detection if calibration fails. 'analytic' forces projection and errors if it can't calibrate. 'detected' uses the old path: render a 3D proxy head and run a face detector over it, which loses the mesh past ~45° and has to interpolate the gaps.
blockswap_blocksoptINT00–40BlockSwap: number of Wan2.2 DiT blocks (of 40) to keep off-GPU during sampling, cast back per-layer on forward. 0 = disabled (keep everything on GPU, recommended for ≥24 GB VRAM). 8-16 = for 12-16 GB cards. 20+ = for 8-12 GB cards. FaceCam doubles the temporal dimension, so it needs noticeably more VRAM than a plain Wan2.2 run at the same resolution. Higher values trade speed for headroom.
allow_model_downloadsoptBOOLEANtrueAuto-download FaceCam checkpoints (~16.8 GB) from HuggingFace on first use. Turn Off to prevent downloads — you must manually place models in ComfyUI/models/diffusion_models/.

Outputs (3)

NameTypeDescription
imagesIMAGE
video_pathSTRING
latentLATENT