Mouth Mesh Extractor (MediaPipe)
The MediaPipe node that hands you a lip contour render and a fill mask from one pass
- images
- mouth_render
- mouth_mask
- centroid_x_list
- centroid_y_list
- fallback_active_list
This is the node that does two jobs at once, and it's the one from this pack you'd reach for when you want a control image and a mask out of the same MediaPipe pass. MouthMeshExtractor runs Google's FaceLandmarker on your frames and returns, from one run, a rendered lip-contour image - colored lip lines on a black canvas, ready to drive a Wan VACE control - plus a filled mouth mask for the inpainting side of the same workflow. No running MediaPipe, dumping landmarks, and hand-drawing the render yourself.
The pitch is the same as the pack's MediaPipe tracked node, aimed at video: it runs FaceLandmarker in VIDEO mode for temporal tracking, then interpolates landmarks across any dropped frames so the mouth doesn't blink out mid-clip. Where it goes beyond the other nodes is output flexibility.
How it works
MediaPipe's 478-point face mesh includes a dedicated lips connection set (FACE_LANDMARKS_LIPS). The node pulls the inner and outer lip loops from that, then does three things per frame: draws the lip contours as lines, fills the region for the mask, and computes a centroid. The include_inner/include_outer booleans (both default on) control which loops contribute to the render - turn off the inner loop if you only want the vermilion border line.
render_mode picks what the render output contains:
contour_only- just the lip lines on black (cleanest VACE control signal)contour_and_fill- lines plus a filled convex hullfill_only- filled region, no lines
line_color (green/white/red/cyan/magenta) and line_thickness (1–10) set the look. Then the shared pack machinery: auto_fallback swaps in an elliptical mask when the inner/outer lip area ratio drops below fallback_area_threshold (pucker, kiss, occlusion), padded by fallback_pad_h/fallback_pad_v; mask_blur feathers the mask and mask_grow dilates it; person_index picks which face (-1 merges all); max_faces and min_confidence control detection.
Outputs: mouth_render (the IMAGE you feed a VACE control input), mouth_mask (the filled MASK for inpainting), and the by-now-familiar centroid_x_list/centroid_y_list (SAM-2 point prompting) and fallback_active_list (which frames ran on the fallback ellipse).
Installing it
Manager (search "lip_mask_from_pose") or:
cd ComfyUI/custom_nodes
git clone https://github.com/Jalen-Brunson/lip_mask_from_pose
restart. Here's the caveat the README won't tell you: it claims no extra dependencies, but that only covers the pose-based nodes. This one imports mediapipe at module load and there's no requirements.txt for Manager to auto-install, so add it yourself:
pip install mediapipe
First run downloads face_landmarker.task (~7 MB) from Google and saves it to ComfyUI/models/mediapipe/face_landmarker.task - the proper models-dir path, which is a relief compared to its tracked sibling in the same pack, which insists on a container-style /workspace path for the same file.
Troubleshooting
- Mouth render is empty but the mask has content: you picked
fill_onlyand are looking at the render - orinclude_outergot switched off. Checkrender_modefirst. - The mouth blinks despite interpolation: interpolation only covers gaps between detected frames; if FaceLandmarker drops long runs of frames, lower
min_confidence(its tooltip literally says lower = fewer dropped frames but more false positives). - Mask too fat or too skinny:
mask_blurandmask_groware your feather/dilate knobs - bump both a little before blaming the mesh. - Centroid jumps around: that's the fallback ellipse firing on puckers;
fallback_active_listwill confirm.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| render_mode | COMBO | contour_only | 3 options: contour_only, contour_and_fill, fill_only |
| line_color | COMBO | green | 5 options: green, white, red, cyan, magenta |
| line_thickness | INT | 21–10 | Thickness of lip contour lines in pixels. |
| max_faces | INT | 11–10 | — |
| min_confidence | FLOAT | 0.300.05–1 | Lower = fewer dropped frames but more false positives. |
| mask_blur | INT | 50–100 | Gaussian blur for mask edges. 0 = hard edge. |
| mask_grow | INT | 00–200 | Dilate mask outward by this many pixels. |
| person_index | INT | 0-1–9 | Which face (0=first). -1=all faces merged. |
| include_inner | BOOLEAN | true | Include inner lip contour (mouth opening edge). |
| include_outer | BOOLEAN | true | Include outer lip contour (vermilion border). |
| auto_fallback | BOOLEAN | true | Fallback to elliptical mask when lips collapse (pucker/kiss). |
| fallback_area_threshold | FLOAT | 0.150.01–1 | Inner/outer area ratio below which fallback activates. |
| fallback_pad_h | FLOAT | 1.200.5–3 | Horizontal scale for fallback ellipse. |
| fallback_pad_v | FLOAT | 1.300.5–3 | Vertical scale for fallback ellipse. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| mouth_render | IMAGE | — |
| mouth_mask | MASK | — |
| centroid_x_list | FLOAT | — |
| centroid_y_list | FLOAT | — |
| fallback_active_list | BOOLEAN | — |