Load VAE (Precision)
ComfyUI decides your decode precision, and it's not always right
- vae
What it is
ComfyUI decides your VAE's precision for you: it casts the weights as it loads them and decodes at that precision, and on any card with fast fp16 it picks fp16. For an image that's invisible. For audio it's the last step before the waveform, and it's measurable.
Load VAE (Precision) loads a VAE at the precision you name - fp32 by default, with bf16 and fp16 available. Load a file out of models/vae, or pull the VAE out of a checkpoint, and wire the result into the ordinary VAE Decode or VAE Decode Audio node like you would core's loader.
The honest framing: this is a tool for audio, and for A/B tests. If you're making pictures, core's Load VAE is fine.
The mechanism, which is the whole point
The reason this can't be a one-line wrapper is that ComfyUI has already rounded the numbers by the time you'd get hold of them. A VAE a loader returned has been cast on the way in, and casting a half-precision tensor back up to fp32 doesn't restore the digits that were dropped. So this node builds its own VAE object from the file's original weights at the dtype you asked for.
That also means it's a separate object. The checkpoint's own VAE, and every other decoder in your graph, keep doing exactly what they were doing, and two decodes of one latent compare cleanly instead of fighting each other.
Getting the weights out of a checkpoint is done lazily: a safetensors file is read key by key, so a multi-gigabyte model doesn't have to be fully loaded just to reach its VAE. It looks for the decoder under vae. (most current models, YuE2 included), first_stage_model. (Stable Diffusion) or pretransform.model. (Stable Audio).
If you'd rather not think about precision at all, the blunt instrument already exists: launching ComfyUI with --no-half-vae keeps every decode in fp32. But that's an install-wide flag you set once and forget, while this is per-decoder - which is what you want when one model in the graph is the problem. That distinction is old news on the image side; SDXL's VAE is the famous case of a decoder that NaNs in fp16 and needed a rescaled refit or a forced fp32 decode, and the VAE is generally the component precision decisions trip over first.
Inputs and outputs
source- a dropdown built from your two model folders:vae/<file>entries fromComfyUI/models/vae, andcheckpoint/<file>entries for checkpoints whose built-in VAE you want at your precision rather than the loader's. New files need a UI refresh before they appear.dtype-fp32(default),bf16,fp16.
One output: vae, wired into VAE Decode, VAE Decode Audio, or anything else expecting VAE.
Why fp32 is the default, and why bf16 is a trap
YuE2's reference pipeline decodes its VAE in fp32 - the model ships fp32 weights and the reference runs bf16 for the AR/NAR stages and fp32 for the VAE. ComfyUI loads that same VAE in fp16 on a card with fast fp16.
The pack measured one real song, one latent, decoded every way, against the fp32 reference:
- fp16 landed at about -52 dB on the whole mix, -42 dB in 4-12 kHz, -39 dB above 12 kHz.
- bf16 landed at -34 dB overall, -24 dB in 4-12 kHz, -21 dB above.
fp16's error sits below anything a whole-mix measurement shows. bf16's doesn't - it measurably dulls the top end. So the useful settings here are fp32 (reference-accurate) or fp16 (ComfyUI's default, close enough), and bf16 is the one to avoid for an audio VAE even though it looks like a sensible middle ground.
One caveat that matters more than the precision: the decoder matters more than either. The VAE inside the YuE2 checkpoint and YuE2-legacy share an encoder tensor for tensor and have entirely different decoders, and they don't agree on transients - the built-in one peaked about 2 dB higher overall and up to 6.6 dB above YuE2-legacy at the strongest high-frequency moments, which by ear is sibilants overdone. That's a file choice, not a precision choice. Decode a latent both ways before you settle.
Install and gotchas
Manager, search Kinburg-Nodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Kinburg/Kinburg-Nodes
Restart, then it's under Kinburg-Nodes → model. No downloads, no dependencies beyond what ComfyUI already has. As with the rest of this pack, install.py will try to install a CUDA llama-cpp-python wheel for the Local LLM nodes on a Manager install; this node needs none of it.
The costs: fp32 is twice the VAE's memory and a slower decode than fp16. Next to generating a song that's nothing, and for a big video VAE it's a real consideration. Also worth saying plainly - this node won't fix a VAE that's wrong for your model. For anything from Flux onward the decoder is baked in, and attaching an external VAE is the thing that breaks output rather than repairs it; the right VAE is the one the checkpoint was trained against. Reach for this when you specifically want the decoder your file was shipped with at the precision you choose.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| source | COMBO | A VAE file from models/vae, or a checkpoint whose own VAE you want — the one its loader's VAE output gives you, here at your precision. | |
| dtype | COMBO | fp32 | The precision the weights are loaded in and the decode runs at. fp32 is what YuE2's reference pipeline decodes its audio in; ComfyUI picks fp16 for it on any card with fast fp16. Twice the VAE's memory, and a slower decode — negligible next to generating the song. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| vae | VAE | — |