VAE Decode Tiled (safe, optional cleanup)
VAE Decode is OOMing on long video? This is the node that survives it
- samples
- vae
- IMAGE
IAMCCS_VAEDecodeTiledSafe is a drop-in replacement for the plain VAE Decode node that exists because long video latents explode when you decode them in one shot. On an 81-frame LTX-2 clip it's usually fine; on a 20-second segment that's pushing a gigabyte of decoded frames, the stock decode can OOM, crash, or - the fun one - leave the GPU in a state where the next retry triggers a Windows access violation. This node tries to never get into that fight in the first place.
It's the "safe" in the name that matters. The README bills it as low-RAM decoding done right, and the code does two genuinely different things to earn that: spatial tiling and, for video VAEs, temporal chunking.
How it works
For a video VAE (LTX-2, Wan, and friends), the node splits your latent into small temporal chunks and calls vae.decode() directly on each 5-D slice, accumulating frames in float16 on CPU to halve peak RAM. That sounds obvious, but it deliberately avoids ComfyUI's tiled_scale_multidim, which pre-allocates the whole decoded output in CPU RAM regardless of tile size - the classic cause of "decode OOM on a clip that should fit." It also checks how much VRAM is free before starting and pre-emptively chunks when the estimated output would exceed ~80% of it, so you skip the OOM→recover→retry cycle instead of suffering it.
Two knobs in particular matter for LTX-2:
temporal_size(default 256): frames per temporal chunk, divided by the VAE's temporal compression at runtime. The tooltip spells out the trap: keep it at 256, because 256 / 8 = 32 latent frames and anything smaller invites seam artifacts between chunks.last_frame_fix: an LTX VAE workaround that duplicates the last latent frame before decoding and trims it back after - LTX's decoder can corrupt the final frame at a hard boundary, and this is the reference implementation's trick for it.
There's also plain spatial tiling for image latents: tiling_mode auto picks tile_size/overlap from your VRAM (a 3050 gets 256px tiles, a 4090 gets 768), or set manual and drive them yourself. cleanup_before_decode flushes the CUDA cache first - note it deliberately does not unload models, because unloading forces ComfyUI to reload everything and stalls worse than the OOM you were avoiding.
Inputs and outputs
The ones a beginner actually touches: samples (LATENT), vae, tile (on by default), tiling_mode, tile_size, temporal_size, last_frame_fix. duration_hint_s looks important but only feeds a "Probe HW & Apply" recommendation report - the tooltip is explicit that it doesn't affect the actual decode. Output is a single IMAGE, wired exactly where a normal VAE Decode's would go.
Installing it
This ships in the IAMCCS-nodes pack (one repo, every IAMCCS node). Easiest via ComfyUI Manager → search IAMCCS, or:
cd ComfyUI/custom_nodes
git clone https://github.com/IAMCCS/IAMCCS-nodes.git
Restart ComfyUI and it appears under IAMCCS/HW. There's no requirements.txt - pure Python on top of ComfyUI, so no extra pip installs. The README does ask for ComfyUI ≥ 0.3.0, Python ≥ 3.12, Torch ≥ 2.8 (CUDA 12.6/12.8); on older installs it's the first thing to check if a node throws at import.
Where people get burned
- Long LTX-2 clips with
temporal_sizebelow 256 → seam artifacts. The tooltip says it, and it's the number-one reported issue with tiled video decode generally. - Expecting
duration_hint_sto change output. It doesn't; it's a hint for the hardware-probe path only. - Hitting Windows access violations after a previous failed decode. That's exactly the scenario the proactive chunking exists for - if you still crash, lower
tile_sizeand keepoverlapat ~an eighth of it rather than going nuclear on everything else.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| samples | LATENT | — | |
| vae | VAE | — | |
| tile | BOOLEAN | true | — |
| tiling_mode | COMBO | auto | 2 options: auto, manual |
| tile_size | INT | 51264–4096 | — |
| overlap | INT | 640–4096 | — |
| temporal_size | INT | 2568–4096 | Only for video VAEs: widget-scale frames per temporal chunk (divided by VAE temporal compression at runtime). Keep >= 256 to avoid seam artifacts on LTX-2 (256 / 8 = 32 latent frames). |
| temporal_overlap | INT | 324–4096 | Only for video VAEs: widget-scale overlap frames between chunks (divided by VAE temporal compression at runtime). |
| cleanup_before_decode | BOOLEAN | false | — |
| last_frame_fix | BOOLEAN | false | LTX VAE workaround: duplicates the last latent frame before decoding to prevent last-frame artifacts. |
| duration_hint_s | INT | 00–3600 | Video duration in seconds — used only by 'Probe HW & Apply' to compute the correct tile size recommendation. 0 = auto-detect from workflow. Does NOT affect the actual decode. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |