Nodes/ComfyUI_JoyAI_Image/JoyAI_Vae_Decoder
ComfyUI Node

JoyAI_Vae_Decoder

The last node in the pipeline, and the one that turns latents back into something you can save

By smthemex·Created 5 months ago·Updated 5 months ago· 15
JoyAI_Vae_Decoder
  • vae
  • latents
  • image

Every generation workflow in this pack ends here. JoyAI_Vae_Decoder takes the LATENT from JoyAI_Image_SM_KSampler and the VAE from JoyAI_Image_SM_VAE, decodes them, and hands you a normal IMAGE you can feed to SaveImage or PreviewImage. It's the bookend to JoyAI_Image_LATENTS: that node put your reference image into latent space, this one pulls the finished latents back out into pixels.

Two inputs, one output, zero settings. vae and latents in, image out. There's genuinely nothing to configure - the pack hides all the plumbing, and that's the right call.

What's happening under the hood

The decode goes through the Wan 2.1 VAE, wrapped as the pack's WanxVAE. It unpacks the latent dict (or a raw tensor), runs the decoder, and does the normalization dance - rescaling, clamping to [0,1], and reordering the tensor into ComfyUI's batch format. If you're feeding it a latent from any other model, stop: this VAE expects 16-channel Wan-format latents, and JoyAI-Image's sampler output specifically. The decode is the part of the pipeline where wrong-format latents turn into the most confusing failure modes - garbage colors, repeating tile patterns, or straight-up nonsense pixels - because the model happily "succeeds" while producing visual noise.

Wiring it

JoyAI_Image_SM_KSampler → JoyAI_Vae_Decoder → SaveImage

The VAE input almost always comes from the same JoyAI_Image_SM_VAE node that fed JoyAI_Image_LATENTS, so you can think of this pack as: one VAE, two uses - encode at the front, decode at the back.

Install and files

Standard pack install:

cd ComfyUI/custom_nodes
git clone https://github.com/smthemex/ComfyUI_JoyAI_Image
cd ComfyUI_JoyAI_Image
pip install -r requirements.txt

restart ComfyUI, and have Wan2.1_VAE.pth in ComfyUI/models/vae (grab it from https://huggingface.co/jdopensource/JoyAI-Image-Edit under vae/, or the merged GGUF repo). The requirements pin transformers>=4.57,<4.58 and flash-attn>=2.8.0 - the decode itself doesn't need flash-attn, but the pack as a whole won't load without it.

Where people get burned

Two recurring pain points. First, resolution: decode at resolutions wildly above what the model sampled at (e.g. the LATENTS node upscaled your input to 1024 but you somehow generated at another size) and you'll see artifacts that aren't the sampler's fault. Keep the decode consuming exactly what the sampler produced. Second, the memory story again: the VAE decode plus the transformer both wanting VRAM at the tail of a run is when offload settings matter most - if the run OOMs right at the very end, right before the image appears, it's this node, and the fix is turning offload back on in the KSampler, not blaming the decoder.

It's the least glamorous node in the pack, and that's the correct way for the last step of a pipeline to be. If your workflow runs clean to here and produces an image you like, you've beaten the real boss of this pack, which is getting the whole thing to fit in memory in the first place.

CategoryJoyAI_Image

Inputs (2)

NameTypeDefaultDescription
vaeVAE
latentsLATENT

Outputs (1)

NameTypeDescription
imageIMAGE