PMA Eye Stabilizer V2 (Ethnicity-Aware)
Auto-calibrating eye tracking plus a blink-suppression knob that earns its name
- images
- stabilized_images
- eye_mask
- debug_visualization
- preset_info
What V2 adds
Same mission as the original PMA Eye Stabilizer - rescue eyes in Wan2.2 motion transfer - but aimed at two specific failures of V1. First, MediaPipe's landmarking is noticeably weaker on some eye shapes and skin tones: monolids and epicanthic folds get read as closed eyes, and darker skin gets fewer usable landmarks. Second, Wan2.2 has a habit of making people blink far too much - the pack's own guide counts every 5–20 frames versus a human's roughly 200 at 60fps. V2 answers with an ethnicity-aware preset system and a blink-suppression mode. The second one is the feature you'll actually feel.
Ethnicity presets: what they really do
ethnicity_preset offers auto, east_asian, south_asian, african, caucasian, middle_eastern, and latino. Each preset tunes the same machinery - blink threshold (Eye Aspect Ratio), smoothing strength, enhancement strength - plus an iris-visibility factor, an eyelid tracking weight, and, for the african preset, a contrast boost applied before detection. Let's be honest about these: they're blunt heuristics, since eye shape varies plenty within any group. But they're a sensible starting point when detection is clearly misfiring on a particular face.
auto is the defensible one. It samples the eye aspect ratio over the first ~30 frames, takes the 75th percentile as your "eyes open" baseline, and sets the blink threshold relative to that. If you're unsure, leave it on auto and let it calibrate to the actual person in the video. Three overrides (smoothing_override, enhancement_override, blink_threshold_override) let you push past a preset - -1 means "use the preset value."
The blink-suppression mode
This is where V2 earns its keep. blink_suppression_mode has off/light/moderate/aggressive, and the tooltip spells out the logic: light filters 1–2 frame blinks, moderate 3+, aggressive 5+. Mechanically, the detector counts consecutive frames where the eye reads closed and only counts it as a real blink once it passes the minimum duration. Wan2.2's micro-dips - a frame or two of eye-closing noise - get filtered out, while a genuine multi-frame blink survives moderate. For the "this person blinks like a strobe light" failure mode, moderate is the right starting point. Aggressive will happily swallow real quick blinks, so don't set it and forget it.
Outputs and placement
Same flow as V1 - a batch of images in, stabilized_images, eye_mask, and debug_visualization out - plus a preset_info STRING that reports which preset was applied and, if auto-calibrated, the baseline EAR it learned. That string is genuinely useful for diagnosing why a result looks the way it does: it's the node telling you its assumptions.
Slot it into the same spot as V1, between background removal and control-map generation:
Video → RMBG → [PMA Eye Stabilizer V2] → DWPose/Depth → WanVaceToVideo
Install and gotchas
Same pack, same single real dependency:
cd ComfyUI/custom_nodes
git clone https://github.com/Pis7i/COMFYUI-MODELINSTALLER
pip install mediapipe==0.10.21
or ComfyUI Manager → search COMFYUI-MODELINSTALLER, then restart. Confirm the console prints "[PMA Utils] Eye stabilizer V2 (ethnicity-aware) loaded."
Watch for: auto-calibration needs ~30 frames, so the first second of a short clip runs on preset defaults; no landmarks in debug means the face isn't being found (forward-facing, one face); and if you're getting plain sharpening with no tracking at all, MediaPipe isn't installed and you're in fallback mode. Test on a 3–4 second clip before a long render.
V1 or V2?
If your subject is a plain-vanilla face with no blink pathology, V1 is perfectly fine and simpler. If there's any question about eye shape, skin tone, or blink frequency, reach for V2 and start with auto plus moderate suppression. The preset logic is guessy, but the auto-calibration and blink suppression are real improvements you can see in the output.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| ethnicity_preset | COMBO | auto | Select ethnicity for optimized eye detection and tracking |
| enable_temporal_smoothing | BOOLEAN | true | — |
| enable_blink_detection | BOOLEAN | true | — |
| enable_eye_enhancement | BOOLEAN | true | — |
| blink_suppression_mode | COMBO | off | Reduce excessive blinking from Wan2.2 (off=normal, light=filter 1-2 frame blinks, moderate=3+ frames, aggressive=5+ frames) |
| smoothing_overrideopt | FLOAT | -1.00-1–1 | Override preset smoothing (-1 = use preset) |
| enhancement_overrideopt | FLOAT | -1.0-1–2 | Override preset enhancement (-1 = use preset) |
| blink_threshold_overrideopt | FLOAT | -1.00-1–0.5 | Override preset blink threshold (-1 = use preset) |
| eye_region_dilationopt | INT | 100–50 | Pixels to expand eye mask region |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| stabilized_images | IMAGE | — |
| eye_mask | MASK | — |
| debug_visualization | IMAGE | — |
| preset_info | STRING | — |