Comfyui-MMH3-UltimateUpscale README

The project's README from github.com/bbaudio-2025/Comfyui-MMH3-UltimateUpscale. As one markdown file: README.md.

Comfyui-MMH3-UltimateUpscale

Upscale long, high-resolution MiniMax H3 video on a VRAM-limited GPU — in a single node.

This node re-samples (enhances / upscales) an already-denoised MiniMax H3 AV latent through the full auto pipeline under tight VRAM constraints: it processes the clip with temporal chunking (so arbitrarily long videos fit in memory) + spatial tiling (so arbitrarily high resolutions fit in memory), keeping peak VRAM bounded to a single tile, while preserving the audio track intact.

MiniMax H3 generates video as a nested latent that bundles 24-channel video and 32-channel audio in one tensor. Standard ComfyUI upscale nodes do not understand this structure. MMH3 Ultimate Upscale wraps the entire temporal split -> latent upscale -> spatial split -> per-tile sampling -> spatial stitch -> temporal stitch loop into one node, so you can upscale a finished H3 clip the same way you would upscale a normal latent — without breaking audio and without running out of VRAM even on small cards.


Changelog


Features


Advantages

Temporal consistency & smooth time transitions

Pixel-space consistency & smooth spatial transitions

Other


Why chunked re-sampling beats dynamic VRAM offloading

Modern PyTorch/CUDA can shuffle weights between RAM and VRAM on demand, so in principle you can generate without tiling even when the working set exceeds VRAM. In practice this is dramatically slower, and the reason is a bandwidth gap of one to two orders of magnitude:

Path Typical bandwidth
GPU VRAM (GDDR/HBM) ~1000 GB/s
PCIe 4.0 x16 (RAM ↔ GPU) ~32 GB/s
PCIe 5.0 x16 ~64 GB/s

Diffusion sampling runs tens of sequential denoising steps, and a transformer revisits its blocks in the same cyclic order every step — the worst case for any residency cache. If the weights do not fit, nearly all non-resident bytes are re-moved over PCIe on every step:

T(offload) ≈ steps × non-resident bytes / PCIe_bandwidth      ← bandwidth-bound
T(chunked) ≈ pieces × FLOPs_piece / GPU_FLOPS                 ← compute-bound

Unified-memory page faults additionally serialize the CUDA stream, so GPU utilization collapses to single digits. Chunked re-sampling instead bounds the peak working set to all weights + one piece's activations, keeping every forward pass compute-bound. The price is only a small, predictable redundancy:

A constant factor of ~1.2–1.8× always beats a 15–60× per-byte penalty. Host↔VRAM offloading only pays when the excess is small and every moved byte gets high reuse; large-DiT multi-step denoising satisfies neither.


Tuning chunk & tile sizes for your VRAM

Per-piece sampling VRAM ≈ model weights + activations, where the activation part scales roughly with chunk_length × tile_width × tile_height:

Aim for the largest pieces that keep peak VRAM just under capacity (watch ComfyUI's VRAM meter during the first tile), keeping total redundancy within roughly ×1.3–1.8. Starting points for H3:

GPU VRAM tile_width × tile_height chunk_length (multiple of 17 px frames)
8 GB 320–384 34–68
12 GB 384–512 51–102
16 GB 512–576 102–153
24 GB 576–768 136–170

Notes:


Nodes

Node Role
MMH3 Ultimate Upscale Main node. Runs the whole loop. Inputs: latent, conditioning, model, noise, sampler, sigmas, optional negative + cfg, and the three optional param inputs.
MMH3 Temporal Split Params chunk_length (px frames, multiple of 17), temporal_overlap (multiple of 17), anchor_strength.
MMH3 Spatial Split Params tile_width / tile_height (px, multiple of 32), spatial_w_overlap / spatial_h_overlap (px, multiple of 32), fade_width / fade_height (seam mask fade), min_tile_size, overlap_mode, overlap_blend.
MMH3 Latent Upscale with Model Params H3 3D model upscaler: model_name, width, height (snapped to a multiple of 32), device, precision.
MMH3 Latent Upscale Params Model-free interpolation: method, width, height (snapped to a multiple of 32).

Typical workflow

  1. Generate an H3 AV latent with MiniMax H3 (video + audio in one latent).
  2. (Optional) MMH3 Temporal Split Params → connect to temporal_split_param.
  3. (Optional) MMH3 Latent Upscale with Model Params or MMH3 Latent Upscale Params → connect to latent_upscale_param.
  4. (Optional) MMH3 Spatial Split Params → connect to spatial_split_param.
  5. Feed latent, conditioning, model, noise, sampler, sigmas into MMH3 Ultimate Upscale.
  6. Decode the output latent with the H3 VAE.

The width/height you set for upscaling must match the conditioning's generation size (the size the video was conditioned at, after upscale).

Upscale model format: .safetensors only

MMH3 Latent Upscale with Model Params only lists and loads .safetensors checkpoints (.sft is accepted as well, matching ComfyUI core). Pickle formats (.pth / .pt / .ckpt) are skipped while scanning and are rejected before the file is opened.

Why: torch.load() on a pickle checkpoint can execute arbitrary code the moment the model is selected. weights_only=True reduces the risk but is not a reliable mitigation on torch < 2.6 (pickle-time bypass, CVE-2025-32434). Refusing pickle entirely removes that surface.

If you have a .pth checkpoint you trust (for example minimax_h3_latent_upscaler_3d_fp32.pth), convert it once:

import torch, safetensors.torch
sd = torch.load('model.pth', map_location='cpu', weights_only=True)
sd = sd['model'] if isinstance(sd, dict) and 'model' in sd else sd
safetensors.torch.save_file(sd, 'model.safetensors')

If weights_only=True fails, the file is not a plain state dict and should not be trusted — don't work around it by switching back to weights_only=False. Checkpoints left in the folder are reported as ignored in the console at startup.


Reference Projects

This node is built on top of following existing community projects:

The H3 3D upscaler network code and normalization statistics are adapted from the second project; the temporal/spatial split, anchor and append logic follow the first.


Extra

This project was vibe-coded by AI, If you run into any problems, it's best to search with AI.😂

Comfyui-MMH3-UltimateUpscale (bbaudio-2025/Comfyui-MMH3-UltimateUpscale)

Searching Database…

What is this?A ComfyUI custom node that upscales long, high-resolution MiniMax H3 AV video latents on VRAM-limited GPUs, using temporal chunking and spatial tiling inside a single node while keeping the audio track intact.
Is this a standalone app or a ComfyUI custom node?It's a ComfyUI custom node package (Python) that plugs into an existing ComfyUI install, adding nodes like 'MMH3 Ultimate Upscale' rather than running on its own.
How do I use this in a ComfyUI workflow?Install it as a ComfyUI custom node, generate an H3 AV latent with MiniMax H3, then connect it to MMH3 Ultimate Upscale along with the optional Temporal Split, Spatial Split and Latent Upscale param nodes, and decode the output latent with the H3 VAE.
Do I need the MiniMax H3 model and specific checkpoint files?Yes — it operates on a MiniMax H3 AV latent, and the model-based upscale mode loads minimaxh3latentupscaler3d.safetensors checkpoints from a latentupscalemodels folder; the model-free interpolation mode needs no extra checkpoint.
Any gotchas before I rely on this?Only .safetensors/.sft upscaler checkpoints are loaded — pickle formats (.pth/.pt/.ckpt) are rejected for security reasons tied to CVE-2025-32434. The experimental LTX2.5 support is also flagged as buggy for audio and explicitly not reliable yet.
Is there anything unusual about the license or checkpoint handling?The project is MIT licensed, and it deliberately refuses pickle checkpoint formats (.pth/.pt/.ckpt) because torch.load() on them can execute arbitrary code, a risk weightsonly=True doesn't fully mitigate.
How much VRAM do I actually need?The README gives tuning tables starting at 8GB with 320-384px tiles and 34-68 frame chunks, up to 24GB with 576-768px tiles; peak VRAM stays bounded to roughly one tile's activations regardless of video length.
Why not just rely on PyTorch's automatic CPU/GPU offloading instead of tiling?PCIe bandwidth (32-64 GB/s) is 15-60x slower than VRAM, so streaming model weights on demand during multi-step diffusion sampling collapses GPU utilization; chunked re-sampling only costs a small ~1.2-1.8x redundancy instead.
Does the audio track survive the upscale?Yes, the audio channels in the nested AV latent are carried through unchanged on every chunk and stitch and are never re-sampled, so there are no audio artifacts from upscaling.
What is the experimental LTX2.5 node?LTX25 Ultimate Upscale extends the same chunk/tile pipeline to LTX2.5's nested video+audio latents with a fixed 2x model upscale, but it's labeled highly experimental and its audio output is noted as buggy.
Size
0.2 MB
Stars
236
Updated
CommitOct 07
Age
1mo
Commits · 90 Days