CPA Final
Where the Matte Actually Comes Out
- plate
- ltx
- selection
- refined
- others
- ltx_isolated
- attn_target
- attn_others
- depth
- native_plate
- tiles
- coverage
- alpha
- comp
- info
Everything in this pack runs toward CPA Final. It's the node that takes the LTX alpha passes, the ViTMatte refined edge, the SAM 3 selection and the other people's masks, blends them into a single matte frame by frame, merges the native-resolution tiles if there are any, writes the files, scores the result, and builds the comp. If you expand a graph and see one node with fifteen wires going in, this is it.
It's also the node whose output you actually use, which is a little unfair given it's hidden from the node menu like every other /internal stage.
The blend, in order
The mode is decided by what's wired, not by a switch:
- Both
attn_targetandattn_othersconnected → the v13 overlap path. The subject pass and the others pass get combined with the front/back ordering fromdepthand the SAM masks, with thehair_guide,occluder_reach,limb_capandfront_smoothingdials doing their thing. If there's no depth wired, it votes from SAM alone. ltx_isolatedconnected → Best (v12): a per-frame hybrid of the LTX matte, the SAM selection and the ViTMatte edge, then a v12 blend that hands over to the isolated-pass result wherever the pixel is near another person.- Neither → Fast (v7): just the hybrid.
Then a coverage fallback, which deserves a sentence. LTX only mattes what it reads as a main subject, so a table or a parked car inside your selection can come out empty. CPA Final compares LTX's coverage against your selection's core over a ~25px neighbourhood, smoothed over time, and blends toward the ViTMatte edge only where LTX left the selection uncovered. That number also becomes the LTX cover badge.
After that: a NaN guard (a NaN matte pixel whites out the entire layer in a compositor, because filters spread it), the native-resolution merge if native_plate and tiles are wired, and the save.
The dials
near_px (default 15) is how close to another person the ViTMatte edge takes over from LTX - the v12 and Fast behaviour. Raise to ~25 if your matte grows a halo of the neighbour where two people touch; lower to ~8 to keep more generative edge near them. It does nothing in v13, which has its own plumbing.
filename_prefix and first_frame give you alpha_01001.png - 16-bit PNG by default, or half-float EXR with format. save skips the write if you're previewing, qc skips the score, and comp builds the comp IMAGE - only worth wiring if you want it, because a full 1080p shot in float32 is several gigabytes.
hair_guide and hair_radius only apply in v13: a guided filter re-fitting the crossing person's hair to the plate's own edges. Great on dark hair over a lighter subject, actively bad on stripes, which it reads as hair.
Outputs
alpha - the MASK, at the plate's native size if native edges ran. This is the thing you wire into SaveImage, a compositor handoff, or anything downstream.
comp - the subject over mid-grey, float32. Handy for judging the matte; a placeholder if you're actually compositing.
info - JSON as a STRING: mode, frame count, first frame, output dir, format, LTX coverage, flicker ratio, detail match, and for 4K the native size and tile count. CPA EdgeColour takes this as its info input and adds to it, which is how the pack keeps one coherent report across two stages.
Alongside the outputs, the node writes JPEG previews into temp for the in-node viewer - plate, comp and alpha, up to 48 of them - so the compare scrubber works without holding a second copy of your shot in VRAM.
The QC badges
flicker (motion-compensated against LTX alone, green at ≤1.3x), detail match (how closely your edge matches LTX's hair, green at ≥80%), LTX cover (green at ≥90%). They're computed on the 1080p proxy even on a 4K plate, which is the right call - it's a consistency score, not a delivery spec.
Read them as a triage tool. A red LTX cover means part of your selection came from ViTMatte and will look soft; that's usually a prop or a background object rather than a person. A red detail match means the generative edge didn't land - try another seed before you retune anything, since a new seed moves the edge about as much as any single setting does.
Install
Part of the pack.
cd ComfyUI/custom_nodes
git clone https://github.com/rik-python/ComfyUI-Comfy-Pro-Alpha-Generator.git
pip install -r ComfyUI-Comfy-Pro-Alpha-Generator/requirements.txt
EXR output uses OpenCV, and the pack sets OPENCV_IO_ENABLE_OPENEXR at import time so it works out of the box. If an EXR write ever fails with "OpenCV EXR disabled", start ComfyUI with OPENCV_IO_ENABLE_OPENEXR=1 or switch to png16 - you'll get a message saying exactly that rather than a silent empty folder.
Inputs (27)
| Name | Type | Default | Description |
|---|---|---|---|
| plate | IMAGE | — | |
| ltx | MASK | — | |
| selection | MASK | — | |
| refined | MASK | — | |
| others | MASK | — | |
| near_px | INT | 15 | — |
| filename_prefix | STRING | comfy_pro_alpha/shot | — |
| format | COMBO | 2 options: png16, exr | |
| first_frame | INT | 1 | — |
| save | BOOLEAN | true | — |
| qc | BOOLEAN | true | — |
| comp | BOOLEAN | true | — |
| ltx_isolatedopt | MASK | — | |
| attn_targetopt | MASK | — | |
| attn_othersopt | MASK | — | |
| depthopt | MASK | — | |
| hair_guideopt | BOOLEAN | false | — |
| hair_radiusopt | INT | 4 | — |
| occluder_reachopt | INT | 20 | — |
| limb_capopt | INT | 90 | — |
| front_smoothingopt | INT | 3 | — |
| native_plateopt | IMAGE | — | |
| native_startopt | INT | 0 | — |
| tilesopt | MASK | — | |
| coverageopt | MASK | — | |
| tile_countopt | INT | 0 | — |
| everyoneopt | BOOLEAN | false | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| alpha | MASK | — |
| comp | IMAGE | — |
| info | STRING | — |