LTX-2.5 Latent Upscale x2 ⚡
The 'make it 1080p' step between LTX-2.5's two sampling passes
- latent
- upscale_model
- vae
- images
- LATENT
LTX-2.5 renders its stage 1 at half resolution on purpose, and something has to double it back. That something is this node: a spatial ×2 upscale of the video half of your joint AV latent, run between the distilled and refine sampling passes, using the official LTX-2.5 latent spatial upscaler. It's the middle of the three-step dance - sample low, upscale, refine high - and it's what turns a 640×360 draft into a 1280×720 finish without a visible pixel-grid seam.
The clever part is that it's a latent upscale, not a pixel one. The video half of the joint AV latent goes through the dedicated upscale model with the VAE's per-channel statistics normalized around it, then re-normalized after. The audio half passes through untouched - the upscale model only understands video-shaped tensors, so the node splits the joint latent, upscales the video branch, and rejoins. Do that wrong (call the upscaler on the concatenated AV tensor) and it silently treats part of the audio latent as video channels. This node does the split for you.
There's also a second job hiding in here: the refine-pass first-frame re-hold. Wire the same first-frame image you gave LTXV25ImgToVideo into images, and the node re-holds it on the upscaled latent at image_strength 1.0 before the refine pass - the official workflow's second in-place image hold. It rebuilds the joint noise mask so held regions stay held. Leave images disconnected for T2V, where the upscaled latent goes to refine with no mask.
The inputs
latent- the distilled pass's output.upscale_model-ltx-2.5-latent-spatial-upscaler-x2-bf16, loaded via coreLatentUpscaleModelLoader.vae- the video VAE, used for the latent statistics and the re-hold encode whenimagesis wired.images/image_strength/img_compression- the optional i2v re-hold.image_strengthdefaults to 1.0 (the official refine value; stage 1 held at 0.7),img_compressionto 18, matching the prep node's round-trip.
One LATENT out → KSampler on refine (3 steps).
Installing it
Part of the ComfyUI-GGUF-Loader pack (ChrisColeTech's fork of city96's ComfyUI-GGUF). ComfyUI Manager: search "ComfyUI-GGUF-Loader". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/ChrisColeTech/ComfyUI-GGUF-Loader
pip install --upgrade gguf
Restart, and grab the upscaler file from the LTX-2.5 kit into models/upscale_models - it's the one extra download this node needs beyond the loader's kit.
Common issues
The order matters and the pack is explicit about it: if your latent came from LTXV25VidToVideo with an IC-LoRA guide appended, run Crop Video Guide before this node. The upscaler cannot tell guide frames from output frames and would double both, and cropping after the upscale removes the wrong count. Also, don't reach for a pixel upscaler instead - the latent path is what the refine pass expects, and mixing a pixel upscale into a latent chain is how you get mushy output.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| latent | LATENT | — | |
| upscale_model | LATENT_UPSCALE_MODEL | ltx-2.5-latent-spatial-upscaler-x2-bf16 via core LatentUpscaleModelLoader. | |
| vae | VAE | Video VAE (for the latent statistics, and the re-hold encode when images is wired). | |
| imagesopt | IMAGE | The SAME first frame given to LTXV25ImgToVideo - re-held on the upscaled latent at image_strength before the refine pass (the official recipe). Leave disconnected for T2V. | |
| image_strengthopt | FLOAT | 1.000–1 | images only. 1.0 is the official refine-pass value (stage 1 held at 0.7). |
| img_compressionopt | INT | 180–100 | images only. Same LTXVPreprocess round-trip as the prep node (official 18; 0 = off) - the workflow feeds one preprocessed image to both holds. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |