FlashVSR_SM_Decoder
Where the latent becomes frames, and where the colour drifts back into place
- vae
- latent
- images
Two inputs, four settings, one output. This is the least glamorous node in the pack and the one most likely to be sitting between you and a watchable result, because it does two jobs that get conflated: turning the latent into an image batch, and putting the colours back where they started.
Diffusion restorers drift colour. Not much, but on skin tones across a 200-frame clip "not much" reads as a slowly shifting grade, and it's the sort of thing that makes an otherwise great upscale unusable next to its source. FlashVSR_SM_Decoder's colour correction is the fix, and it's on by default for a reason.
What it does
vae comes from FlashVSR_SM_Vae - the configured decoder, whatever flavour you picked there. latent comes from FlashVSR_SM_KSampler, and it isn't a plain latent: it carries the low-res conditioning frames and the padding count the sampler added to round the frame count up to 8n+1. The decoder uses those to unpad the result and to compare against your source.
So the pipeline is:
FlashVSR_SM_Vae ──vae──┐
├─▶ FlashVSR_SM_Decoder ──images──▶ CreateVideo ──▶ SaveVideo
FlashVSR_SM_KSampler ──latent──┘
images is an IMAGE batch, one frame per image. Feed it to CreateVideo (set your fps - GetVideoComponents can supply the original), and if you want the upscaled clip to have sound, wire the AUDIO from a GetVideoComponents on the source into CreateVideo's audio. That's the one part of the graph this pack doesn't automate.
The four settings
full_tiled defaults to on, and it's your VRAM lever. It wraps the decode in the decoder's tiling path: less peak memory, noticeably more time. This is the same trade the rest of the video-upscaling ecosystem makes - tiling can cut peak VRAM to a fraction of what an untiled run needs while being far slower - and it lands in exactly the same place here. Untiled is the higher-quality, higher-memory option; turn tiling off once you know the run fits.
color_fix defaults to on. It runs the corrected frames against your source frames - histogram-style matching, wavelet domain by default - so the output keeps the palette you started with. Turning it off is occasionally right: on already-clean, non-blurry footage the README suggests it's worth trying without, and if your source is stylised or has a strong grade, the correction can fight it.
fix_method picks how the match is done: wavelet or adain. Wavelet is the default and the one the pack ships in its example workflows. AdaIN is the blunter statistical transfer. If wavelet produces a seam or a colour pulse on the first frames, try adain before disabling the correction entirely - the wavelet path pads an extra leading frame internally and trims it back off, and that's where artefacts tend to show up.
Everything is gated in a try/except: if colour correction throws, the pack prints "color correction failed, return uncorrected images" and hands you the raw decode. So a sudden palette shift with no visible error means the correction silently gave up, not that the model broke.
If you're on FlashVSR+, this node is doing the plus decode too - the plus path defers its latent and finishes here with the TCDecoder from the Vae node. Same four settings, same output.
Install
Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/smthemex/ComfyUI_FlashVSR
cd ComfyUI_FlashVSR && pip install -r requirements.txt
No weights are specific to this node, but it can't do anything without a decoder file - TCDecoder.ckpt in ComfyUI/models/FlashVSR, or a Wan 2.1 VAE in ComfyUI/models/vae. See the Vae page for the folder split, which is where people lose an hour.
Troubleshooting
It dies at 95% with an OOM. This is the decode, and it's the classic video-upscaler failure: sampling fits, the last step doesn't. Turn full_tiled on, or drop the sampler's canvas size. Nothing else here will save you.
Output frames have a green or purple cast. Decoder/weights mismatch more often than colour correction - check the TCDecoder release against your DiT version. If it's subtle rather than catastrophic, it's color_fix falling back silently; check the console.
when use long mode only support tcd_encoder. You switched tiny_long on in the Model node but loaded a Wan VAE or a light decoder in the Vae node. Long mode decodes chunk by chunk and only the TCDecoder knows how - swap the Vae node to tcd_encoder and requeue.
Sharp, but crunchy and over-defined compared to the source. FlashVSR's character is more fidelity than extra detail - if you're getting hard edges, you've probably pre-upscaled the source with something else before feeding it in. Give it the soft original.
Decoded clip looks fine but is way bigger than expected. The image batch is the sampler's canvas × the model's 4× pass; the size is decided two nodes upstream. Read the KSampler page before resizing things here.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| vae | VAE | — | |
| latent | LATENT | — | |
| full_tiled | BOOLEAN | true | — |
| color_fix | BOOLEAN | true | — |
| fix_method | COMBO | 2 options: wavelet, adain |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |