CPA DecodeStitch
Decoding Tiles Without Caching a Gigabyte Each
- vae
- chunk_0
- chunk_1
- chunk_2
- chunk_3
- chunk_4
- chunk_5
- chunk_6
- chunk_7
- chunk_8
- chunk_9
- chunk_10
- chunk_11
- chunk_12
- chunk_13
- chunk_14
- chunk_15
- chunk_16
- chunk_17
- chunk_18
- chunk_19
- chunk_20
- chunk_21
- chunk_22
- chunk_23
- alpha
Once a plate is bigger than 1920x1088, the pack stops trying to matte it in one pass. It runs the whole job on a proxy, then cuts the plate into half-overlapping 1920x1088 tiles at native resolution, renders only the tiles that touch the subject's edge, and merges those tile alphas back into a full-size matte. CPA DecodeStitch is the small, unglamorous node that turns each tile's pile of sampled latents into one continuous alpha for that tile.
Compositors will recognise the shape of the problem. You've rendered a region in tiles; the tiles overlap; each one is a separate pass with its own noise; and if you hard-cut them together you can see a rectangle on every join. This node is the cross-fade.
What it does
You hand it a plan and a vae, plus up to 24 optional chunk_0 … chunk_23 LATENT inputs. The plan is JSON the graph builds for you - frame count, tile height and width, chunk length, and the start index of each chunk. You should never type one by hand; if you do, one wrong starts entry will silently slide your alpha in time rather than erroring.
It then walks the chunks in order and, for each one:
- Decodes with core's tiled VAE decode (512-pixel tiles, 64 overlap, 8 temporal tiles), same settings as everywhere else in the pack.
- Averages the colour channels into a single alpha plane and casts to
float16. - Crops to the tile's real height and width - undoing the multiple-of-32 padding that
CPA TileGuideandCPA ChunkPadadded. - Accumulates it into a frame buffer weighted by
chunk_weight, the same triangular cross-fade used by the 1080p path: each chunk ramps in over its overlap with the previous one and ramps out over its overlap with the next, and the first and last chunks don't ramp at the outside edges.
Finally it divides by the accumulated weight, clamps to 0–1, and returns a float16 MASK.
That weight division is the bit that matters. In the middle of an overlap both chunks contribute, so the accumulator holds a weighted sum; dividing by the weight sum brings it back to a valid alpha value instead of a blown-out double. The pack's README notes the joins actually measure steadier than the rest of a shot, which is a nice side effect of averaging two independently noisy passes.
Why it's one node instead of two
Because on the tile path the decoded chunk is the expensive object. A 1080p float32 RGB decode is around 1.2 GB; with one of these per chunk per tile, letting each decode become a normal cached node output would put the whole tile set in RAM and swap your machine to death. So decode and stitch are fused here, one chunk alive at a time, and the buffer is deleted before the next decode starts.
This is the same reasoning behind CPA DecodeAlpha + CPA Stitch on the 1080p path, just compressed one step further. If you're wondering why the pack has three near-identical decode nodes (DecodeAlpha, DecodeStitch, DecodeStitchRGB), this is why: each is shaped by what it's allowed to keep in memory.
Where it sits
Inside CPA NativeEdges, once per rendered tile. The output MASK goes into CPA TileMerge, which feather-blends the tiles into full native-resolution frames and produces the coverage map. From there the tiles land in CPA Final, which merges them into the proxy alpha away from other people and away from anywhere a tile disagrees with the proxy over an area.
Nobody calls it directly, and like every /internal node it's hidden from the node menu - flagged deprecated so it stays out of search. You'll meet it in an expanded graph and in error messages, not in the palette.
Install
Part of the pack; nothing extra:
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
You need ComfyUI 0.38+ for the tile path, and the pack needs ComfyUI-LTXVideo - the guide node it drives (LTXAddVideoICLoRAGuide) is what assembles the tile chunks in the first place.
Failure modes
If native-resolution edges run out of memory, it's rarely this node's fault - it's the tile set being large. The pack raises a clear error above 64 tiles and suggests switching native edges off or cropping, and for a 4K shot the sane move is a ~100-frame split rather than tuning anything here.
On a plate only a bit over 1080p - 2K, say - you're paying the full tile cost for very little strand detail. The README says so plainly: switch native edges off there, take the 1080p matte scaled up, and save 2–3x the render time.
Inputs (26)
| Name | Type | Default | Description |
|---|---|---|---|
| plan | STRING | — | |
| vae | VAE | — | |
| chunk_0opt | LATENT | — | |
| chunk_1opt | LATENT | — | |
| chunk_2opt | LATENT | — | |
| chunk_3opt | LATENT | — | |
| chunk_4opt | LATENT | — | |
| chunk_5opt | LATENT | — | |
| chunk_6opt | LATENT | — | |
| chunk_7opt | LATENT | — | |
| chunk_8opt | LATENT | — | |
| chunk_9opt | LATENT | — | |
| chunk_10opt | LATENT | — | |
| chunk_11opt | LATENT | — | |
| chunk_12opt | LATENT | — | |
| chunk_13opt | LATENT | — | |
| chunk_14opt | LATENT | — | |
| chunk_15opt | LATENT | — | |
| chunk_16opt | LATENT | — | |
| chunk_17opt | LATENT | — | |
| chunk_18opt | LATENT | — | |
| chunk_19opt | LATENT | — | |
| chunk_20opt | LATENT | — | |
| chunk_21opt | LATENT | — | |
| chunk_22opt | LATENT | — | |
| chunk_23opt | LATENT | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| alpha | MASK | — |