Views
No views yet
.safetensors — the same decoder, converted to the key layout ComfyUI expects,
for anyone who prefers a single file over two inputs.minimax_h3_single_frame_decoder_500k.safetensors downloaded from the original repository — the node
pairs it with the official H3 VAE and does the key translation in memory. The converted files are a
convenience, not a requirement.load_decoder.py is all you need.decoder.* + post_quant_conv.*) and uses
diffusers naming. That is correct for the author's intended flow, which loads a complete H3 VAE and
replaces two submodules:1vae.decoder.load_state_dict(decoder, strict=True)
2vae.post_quant_conv.load_state_dict(post_quant_conv, strict=True)VAELoader builds a VAE from the file.
Worse, detection in comfy/sd.py requires an encoder key:elif "decoder.transformer_blocks.0.scale1" in sd and "encoder.down.5.block.0.conv1.weight" in sd:No VAE weights detected, VAE not initalized,
leaves first_stage_model = None and falls back to Stable Diffusion geometry — 4 latent channels and
8x upscale, against H3's 24 channels and 32x. The result is blocky garbage. It is not a bug in
ComfyUI and not a defect in the checkpoint; the two simply have different contracts.encoder.*,
quant_conv, latents_mean/std, mask_token) from the official H3 VAE. That graft is exactly what
the author's own script does, and it is sound because the author froze the encoder during training —
the official encoder is the one this decoder was trained against.| transform | evidence |
|---|---|
to_qkv is interleaved per head (32 heads, 3, 64 dim_head), not stacked [q;k;v] | matches qkv.view(B, S, -1, 3*dim_head) in comfy/ldm/minimax/vae.py; correlation 0.998 |
ff.w1 halves are swapped relative to diffusers (ComfyUI reads gate first) | correlation: straight −0.013, swapped +2.00 |
MiniMaxH3VideoVAE tiles internally with a constructor default of tile_size=256, and
the stock VAELoader does not expose that field. 256 is the worst value. Measured on a 1056x640 image,
where "seam" is edge energy at tile boundaries relative to the image average (1.0 = invisible):| tile_size | PSNR | seam |
|---|---|---|
| 256 (ComfyUI default) | 22.17 dB | 1.49 — visible |
| 512 | 26.00 dB | 0.91 — invisible |
| 768 | 23.27 dB | 1.71 |
| 1024 | 21.35 dB | 2.42 |
MiniMax-H3 Single-Frame VAE Loader
base_vae→ the official MiniMax-H3 VAE (the complete one, with encoder)single_frame_decoder→minimax_h3_single_frame_decoder_500k.safetensors, straight from the original repositorytiling: True,tile_size: 512The node detects the diffusers naming, converts it in memory and grafts the missing encoder frombase_vae. Nothing is written to disk and the original file is untouched — its SHA-256 still matches, so the author'sload_decoder.pykeeps working with it.
MiniMax-H3 VAE Loader / tile control
vae_name→minimax_h3_single_frame_500k_comfy.safetensorstiling: True,tile_size: 512
fp16 and fp32 also decode bit-identically here — ComfyUI runs this VAE in fp16 either way, so the
fp16 file is the sensible one and the fp32 is provided only to remove the doubt.decoded[:, :, -1] in the author's example). Fine texture is smoothed, and dense thin lines can moiré.