FaceCam (FFMPEGA)
Make Wan 2.2 orbit a face without the head melting
- model_high
- images
- model_low
- vae
- clip
- images
- video_path
- latent
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) andmodel_low- your Wan 2.2 A14B pair, loaded however you normally load it; the docs assume GGUF via Load Diffusion Model. Plusvae(Wan 2.2 VAE) andclip(T5-XXL).imagesorvideo_path- the source frame. Just a frame or two is normal; FaceCam animates from it.camera_preset- eleven options.orbit_left/orbit_rightswing the camera to ±45°,zoom_inpushes FOV 50→25°,zoom_outpulls back,look_up/look_downtilt the subject,dramatic_pan,subtle_drift(the most natural),dolly_zoom,random, andcustom.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.
Inputs (27)
| Name | Type | Default | Description |
|---|---|---|---|
| model_high | MODEL | Wan2.2 base model (high-noise) | |
| prompt | STRING | A portrait of a person | — |
| negative_prompt | STRING | — | |
| seed | INT | 00–4294967295 | — |
| steps | INT | 501–200 | — |
| cfg_scale | FLOAT | 5.01–20 | — |
| sampler_name | COMBO | euler | 4 options: euler, euler_ancestral, dpmpp_2m, dpmpp_sde |
| scheduler | COMBO | simple | 4 options: simple, normal, karras, sgm_uniform |
| high_model_ratio | FLOAT | 0.200–1 | Fraction of steps using HIGH model (camera trajectory). Remaining steps use LOW model (detail refinement). 0=all LOW, 1=all HIGH. |
| camera_preset | COMBO | orbit_left | Camera 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_frames | INT | 815–321 | — |
| width | INT | 480128–1920 | FaceCam is trained on portrait video — upstream defaults to 480×704 (w×h). Landscape is off-distribution and weakens camera control. |
| height | INT | 704128–1920 | FaceCam is trained on portrait video — upstream defaults to 480×704 (w×h). |
| imagesopt | IMAGE | Input image/frames (alternative to video_path) | |
| video_pathopt | STRING | Input video path (connect from LoadVideoPath node) | |
| model_lowopt | MODEL | Wan2.2 base model (low-noise) for refinement pass. If not connected, HIGH model runs all steps. | |
| vaeopt | VAE | Wan 2.2 VAE | |
| clipopt | CLIP | T5-XXL text encoder | |
| start_azimuthopt | FLOAT | 0-90–90 | Horizontal rotation start. Negative=camera left, positive=right. |
| end_azimuthopt | FLOAT | 0-90–90 | Horizontal rotation end. |
| start_elevationopt | FLOAT | 0-60–60 | Vertical rotation start. Positive=looking down, negative=looking up. |
| end_elevationopt | FLOAT | 0-60–60 | Vertical rotation end. |
| start_fovopt | FLOAT | 4010–60 | Field of view start. Higher=wider (zoom out), lower=tighter (zoom in). |
| end_fovopt | FLOAT | 4010–60 | Field of view end. |
| mesh_sourceopt | COMBO | auto | How 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_blocksopt | INT | 00–40 | BlockSwap: 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_downloadsopt | BOOLEAN | true | Auto-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)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| video_path | STRING | — |
| latent | LATENT | — |