English ·
中文
# ComfyUI Minimax H3 Latent Upscaler
**Neural Latent Upscaler for Minimax H3 Video Generation**
Learned · High-fidelity · 2D & 3D Variants
## 📰 News
- [2026-08-28] 🚀 **New node combo — MMH3 Split Upscale**: three new nodes (`MMH3 Temporal Split Params`, `MMH3 Spatial Split Params`, `MMH3 Split Upscale`) perform a tiled, hires-fix style latent re-sampling upscale for H3 video. Decomposed and optimized from the **Comfyui-MMH3-UltimateUpscale** project — splitting the AV latent into temporal chunks and spatial tiles, resampling each piece, and stitching with seam denoise, two-level color matching and temporal anchors. Key upgrades vs. original: more stable seams (`seam_denoise` + probe-gated seam polish), zero color drift (two-level matching + first-block/every-chunk pin-source), triple temporal anchors (frame-0/motion/identity), easier use (spatial params simplified to overlap/fade percentages snapping to the latent grid), and a lighter footprint (built-in upscale model removed in favor of an external pre-upscaled latent).
- [2026-08-26] 🚀 **3D node memory & UX optimizations**: zero-copy model loading plus ComfyUI's native `soft_empty_cache` and explicit `.contiguous()` calls reduce RAM/VRAM spikes during load and inference; the post-inference CPU offload is now an optional `force_unload` toggle (default on); `enable_chunking` is renamed to `enable_temporal_chunking` and its effective chunk stride raised from 24 to 32; model files can now live in subfolders (PR #30); `target dimensions` and `megapixels` upper limits raised to 8192 px and 16 MP.
- [2026-08-23] 🚀 **3D node improvements**: added an `enable_chunking` toggle (turn off for short clips to use full-context inference); fixed temporal-chunk edge artifacts with replicate padding and weighted overlap blending, eliminating end-frame flicker; added ROCm (AMD GPU) backend support via the new `rocm` device option.
- [2026-08-21] 🚀 **3D node optimization**: The model is automatically offloaded to CPU after execution to free VRAM for subsequent second-pass sampling; width and height are independently aligned to the align grid (default 32), fixing the bottom light band issue; normalization/denormalization is changed from in-place operations to standard operations; temporal chunking is retained to support long videos.
- [2026-08-19] 🚀 **3D node overhaul**: all three resize modes (`scale by multiplier`, `target dimensions`, `megapixels`) merged into a single node; fixed aspect-ratio mismatch in certain modes and edge artifacts at specific sizes; added a new example workflow and expanded the usage notes.
- [2026-08-18] 🔥 **Precision selector**: both 2D and 3D nodes now support `fp32` / `fp16` / `bf16` inference.
- [2026-08-17] 🎉 **Initial release**: Minimax H3 Latent Upscaler 2D + 3D nodes with bilingual README and inline examples.
A custom ComfyUI node that upscales **Minimax H3** VAE latents (24 channels) with a trained
neural network instead of naive interpolation. Its main purpose is to **accelerate
high-resolution video generation** and improve quality:
- **Skip the slow decode → pixel-upscale → encode round-trip.** Minimax H3 ships a heavy
~5B-parameter VAE, so decoding and re-encoding latents is expensive. Upscaling directly in
latent space avoids that costly round-trip entirely.
- **Enable a faster generation pipeline:** generate at low resolution (far fewer latent tokens),
upscale the latent with this node, then refine at the target resolution.
It also **avoids the ghosting / double-image artifacts** that naive latent interpolation
(bilinear/bicubic) introduces, and plays a role similar to the latent upscaler in **LTX2.3**.
⚠️ This saves **time, not VRAM** — the refinement pass still runs at the target resolution, so
peak memory is comparable to generating high-res directly. The win is purely speed.
Two node variants are provided, both registered under the `video/MinimaxH3` category:
- **Minimax H3 Latent Upscaler (2D)** — a 2D ResBlock backbone with Temporal 3D-Conv layers
inserted for temporal consistency. Spatial (H×W) upscaling; the time dimension is preserved.
Lightweight and fast. Uses a simple `scale` factor (1.0×–4.0×).
- **Minimax H3 Latent Upscaler (3D)** — a fully 3D-convolution backbone (3D ResBlocks +
TemporalConv + trilinear interpolation). Processes the spatiotemporal volume jointly for
stronger temporal coherence; heavier on compute/memory. Supports **three resize modes** in one
node:
- `scale by multiplier` — classic `scale` factor (1.0×–4.0×).
- `target dimensions` — directly set target pixel `width`/`height`.
- `megapixels` — set a target total pixel count in megapixels (e.g. `1.2`); keeps aspect ratio.
Both `target dimensions` and `megapixels` modes align the output to a configurable pixel grid and
derive the effective scale automatically.
> The 3D node computes the equivalent `scale` internally for the size-based modes and feeds it to
> the same trained model, so any target between 1.0×–4.0× works.
> Both nodes support **upscaling only** (`effective scale >= 1.0`). `scale = 1.0` returns the input
> unchanged; an effective scale below `1.0` raises an error.
### MMH3 Split Upscale (combo)
> **Origin:** this combo is a **decomposed and re-optimized version of the
> Comfyui-MMH3-UltimateUpscale project**. The original monolithic node was broken into three composable nodes (temporal split /
> spatial split / main upscaler), and the enhancements below were layered on top of the original tiling
> logic to improve seam stability, color consistency, temporal coherence, usability, and footprint.
A separate three-node combo that does a **tiled, hires-fix style re-sampling upscale** directly
inside the diffusion sampler — instead of a pre-trained upscaler network. It takes the H3 **AV
latent** (nested video 24ch + audio 32ch), splits it into **temporal chunks** and **spatial tiles**,
runs the sampler on each piece, then stitches them back seamlessly with seam-denoise, two-level color
matching and temporal anchors so seams and ghosting don't appear. The two `* Split Params` nodes
configure the splitting and feed the main `MMH3 Split Upscale` node (both optional — leave them
unconnected for a single full-frame pass). It requires a `model` + `conditioning` + `sampler`/`sigmas`,
i.e. it re-runs sampling at the higher resolution.
**Key enhancements vs. the original project:**
- **🧩 More stable seams (Seam / Ghosting):** a seam-neighborhood denoise cap (`seam_denoise`) plus a probe-gated second-pass seam polish (`seam_polish`) remove seams and ghosting; even under high denoise + fast motion, moving objects are no longer sliced ("broken limbs").
- **🎨 Zero color drift (Color Zero-Drift):** spatial + temporal two-level color matching, with a global color reference pinned to the **first block** and to **every chunk** (`grade_pin`) — eliminates inter-tile flicker and the localized cyan/green tint (e.g. top-left corner).
- **⏱️ Stronger temporal continuity:** a **triple temporal anchor** — `frame-0 anchor` + `motion anchor` + `identity anchor` — automatically backs up identity consistency under high denoise, so subjects don't drift.
- **🖱️ Easier to use:** spatial parameters cut from 9 fields down to **percentages** (overlap ratio / fade ratio) that auto-snap to the latent grid; `negative` sits right next to `conditioning` for a more intuitive layout.
- **🪶 Lighter footprint:** the built-in upscale model was removed in favor of an **external pre-upscaled latent** input — more controllable VRAM, and a node that stays focused on its job.
**Modules added / optimized (relative to the original project):**
| Module | What it adds / optimizes |
| :--- | :--- |
| **Prevention (预防)** | Freeze-prefill overlap band + **triple temporal anchors** (frame-0 anchor + motion anchor + identity anchor) + cross-fade stitching — stops seams and forks from forming in the first place. |
| **Correction (校正)** | **Two-level (spatial + temporal) color matching** + first-block source reference + per-chunk global pin-source (`grade_pin`) — keeps color & brightness consistent across tiles and chunks, killing inter-tile flicker and localized cyan/green tint. |
| **Anti-forking (抗分叉)** | `seam_denoise` cap — under high denoise + fast motion, the seam neighborhood is re-sampled at *medium* denoise so moving objects aren't sliced ("broken limbs"); combined with the probe-gated second-pass seam polish, seams and ghosting are both eliminated (suggested 0.5–0.8; 1.0 = off). |
| **Fixes (修复)** | **Per-tile independent Guider** + cropped keyframes, and a **fixed probe-gated seam polish** (`seam_polish`) — each tile gets correctly-scoped conditioning/keyframes, and the polish gating no longer over/under-applies. |
| **Simplification (简化)** | `overlap` / `fade` are now **percentage parameters** (overlap ratio / fade ratio, resolution-independent) instead of absolute pixels, and auto-snap to the latent grid; `negative` sits next to `conditioning` for a more intuitive layout. |
---
## 📸 Examples
**Video upscale comparison**
**Image upscale comparison**

---
## 📁 Project Structure
```text
Comfyui_Minimax_h3_latent_Upscaler/
├── examples/
│ ├── Minimax_h3_latent_Upscaler_001.mp4
│ └── Minimax_h3_latent_Upscaler_002.jpg
├── workflow_templates/
│ └── minimax_h3_r2v_Latent Upscaler example workflow.json # example workflow for ComfyUI templates
├── nodes/
│ ├── __init__.py # merges 2D/3D/Split node mappings
│ ├── minimax_h3_latent_upscaler_2d.py # 2D backbone + Temporal 3D Conv (scale mode)
│ ├── minimax_h3_latent_upscaler_3d.py # pure 3D convolution with 3 resize modes
│ └── MMH3_Split_Upscale.py # MMH3 Split Upscale combo (decomposed from Comfyui-MMH3-UltimateUpscale)
├── README.md
├── README_zh.md
└── __init__.py
```
> The model weights are **not** included in this repo. Place them in your ComfyUI models folder
> (see Model Placement below).
---
## 🚀 Key Features
- ✅ **Learned latent upscaling** — neural network trained for Minimax H3 latents, far sharper
than bilinear/bicubic interpolation.
- ✅ **Two backbones** — pick the fast **2D** variant or the temporally-coherent **3D** variant.
- ✅ **Three ways to set output size on the 3D node** — `scale by multiplier`, `target dimensions`,
or `megapixels`, all with pixel-grid alignment and aspect-ratio lock.
- ✅ **Tiled hires-fix upscaler (MMH3 Split Upscale combo)** — re-sample the H3 AV latent at higher
resolution by splitting into temporal chunks + spatial tiles, with seam-denoise, two-level color
matching and temporal anchors to avoid seams and ghosting.
- ✅ **24-channel Minimax H3 latent** — uses the exact per-channel mean/std normalization from
training.
- ✅ **Auto architecture detection** — reads `in_channels`, block counts, temporal config and
kernel size straight from the checkpoint; no manual config needed.
- ✅ **Robust weight loader** — supports `.safetensors` and `.pth`; auto-converts FP8→FP16;
tolerates the `upscaler.` prefix in merged checkpoints.
- ✅ **Flexible precision/device** — `cuda`/`cpu` and fp32/fp16/bf16 options.
- ✅ **Plug-and-play** — standard ComfyUI node, no changes to your existing workflow.
Inference forces attention **off** (`attn=False`) for speed and stability. Loaded models are
cached by `(name, device, precision)` so repeated runs stay cheap.
---
## 📦 Installation
1. Clone this repository into ComfyUI's `custom_nodes` folder:
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/LBH-123-AI/Comfyui_Minimax_h3_latent_Upscaler.git
```
2. Required dependencies (`torch`, `einops`, `safetensors`) are already present in a standard
ComfyUI environment — no extra install needed.
3. Restart ComfyUI.
---
## 🤖 Model Placement
The nodes scan and load weights from:
```text
ComfyUI/models/latent_upscale_models/
```
Put your Minimax H3 latent upscaler checkpoint (`.safetensors` or `.pth`) there. It will appear
automatically in the node's `model_name` dropdown.
Pre-trained checkpoints are available at:
[huggingface.co/LBH-123-AI/Minimax_h3_latent_Upscaler](https://huggingface.co/LBH-123-AI/Minimax_h3_latent_Upscaler)
The loader auto-detects the architecture, so a single checkpoint works for both the 2D and 3D
nodes as long as the stored structure matches.
---
## 🧩 Usage
Add the node you need from the `video/MinimaxH3` menu, connect a `LATENT`, pick the model, set the
resize mode / scale, and decode.
**Typical workflow:**
- **Quick preview:** `[Minimax H3 Latent] → [H3 Latent Upscaler] → [VAE Decode]`
- **High quality / time-saving (recommended):** `[Low-res Latent] → [H3 Latent Upscaler] → [Refine / Re-sample] → [VAE Decode]`
Compared to the naive approach `[Latent] → [VAE Decode] → [Pixel Upscaler] → [VAE Encode] → …`,
upscaling directly in latent space skips the expensive VAE decode/encode round-trip. Minimax H3's
~5B-parameter VAE makes decode and re-encode notably slow, so this is where most of the time is
saved. It also avoids the **ghosting / double-image artifacts** that direct latent interpolation
(bilinear/bicubic) causes.
⚠️ **Saves time, not VRAM:** the refinement still runs at the target resolution, so peak memory is
roughly the same as generating high-res directly. The benefit is purely faster turnaround.
### Node Reference — 2D
| Parameter | Type | Default | Range / Options | Description |
| :--- | :--- | :--- | :--- | :--- |
| `latent` | LATENT | — | — | Input Minimax H3 latent (B,C,T,H,W) or (B,C,H,W) |
| `model_name` | dropdown | auto | scanned files | Checkpoint in `latent_upscale_models/` |
| `scale` | FLOAT | 2.0 | 1.0 – 4.0 (step 0.1) | Spatial upscale factor |
| `device` | dropdown | cuda | cuda / cpu | Inference device |
| `precision` | dropdown | fp32 | fp32 / fp16 / bf16 | Inference precision |
**Output:** `LATENT` — the upscaled latent, ready for VAE decode.
### Node Reference — 3D
| Parameter | Type | Default | Range / Options | Description |
| :--- | :--- | :--- | :--- | :--- |
| `latent` | LATENT | — | — | Input Minimax H3 latent (B,C,T,H,W) or (B,C,H,W) |
| `model_name` | dropdown | auto | scanned files | Checkpoint in `latent_upscale_models/` |
| `mode` | dropdown | `scale by multiplier` | `scale by multiplier` / `target dimensions` / `megapixels` | How the output size is chosen |
| `scale` | FLOAT | 2.0 | 1.0 – 4.0 (step 0.05) | Used when `mode` is `scale by multiplier` |
| `width` | INT | 1280 | 64 – 8192 (step 8) | Target pixel width (used by `target dimensions`) |
| `height` | INT | 704 | 64 – 8192 (step 8) | Target pixel height (used by `target dimensions`) |
| `megapixels` | FLOAT | 1.0 | 0.1 – 16.0 (step 0.1) | Target total megapixels (used by `megapixels`); keeps aspect ratio |
| `align` | INT | 32 | 1 – 512 | Pixel-grid alignment: output W/H are independently rounded to multiples of this value (e.g. 16/32/64) |
| `enable_temporal_chunking` | BOOLEAN | True | True / False | Split long videos into temporal chunks to cap VRAM; disable for short clips for full-context inference |
| `force_unload` | BOOLEAN | True | True / False | Unload model to CPU after inference to free VRAM for subsequent nodes; disable if you reuse this node repeatedly to avoid reload overhead |
| `device` | dropdown | cuda | cuda / rocm / cpu | Inference backend (ROCm needs a HIP-enabled PyTorch build) |
| `precision` | dropdown | fp32 | fp32 / fp16 / bf16 | Inference precision |
**Output:** `LATENT` — the upscaled latent.
> **Which node to pick?** Use **2D** for speed and when frames are already temporally stable; use
> **3D** when you need stronger motion/temporal coherence or prefer specifying output size by
> `target dimensions` / `megapixels`.
### Node Reference — MMH3 Split Upscale (combo)
A tiled, **hires-fix style** re-sampling upscaler for H3 video, **decomposed and optimized from the
Comfyui-MMH3-UltimateUpscale project**. Unlike the 2D/3D nodes (which use a
pre-trained upscaler network), this combo re-runs the diffusion sampler on a higher-resolution
version of the latent, split into pieces so it fits in VRAM. It operates on the H3 **AV latent**
(nested video 24ch + audio 32ch) and requires `model` + `conditioning` + `sampler`/`sigmas`.
**`MMH3 Temporal Split Params`** — how to cut the clip along time (H3's native 5+17·m frame/token grid):
| Parameter | Type | Default | Range / Options | Description |
| :--- | :--- | :--- | :--- | :--- |
| `chunk_frames` | INT | 73 | 5 – 100000 | Chunk length in frames (snapped to H3 token grid) |
| `temporal_overlap_frames` | INT | 22 | 0 – 100000 | Overlap between consecutive chunks |
| `anchor_strength` | FLOAT | 0.999 | 0.0 – 1.0 | Temporal anchor strength |
| `motion_anchor_frames` | dropdown | 22 | 0 / 5 / 22 / 39 | Motion anchor length in frames |
| `identity_anchor_frames` | INT | 24 | 0 – 240 | Spacing of identity anchors |
Output: `temporal_split_param` (custom type, feeds the main node).
**`MMH3 Spatial Split Params`** — how to cut each frame into tiles:
| Parameter | Type | Default | Range / Options | Description |
| :--- | :--- | :--- | :--- | :--- |
| `tile_width` | INT | 512 | 64 – 16384 (step 32) | Tile width in pixels |
| `tile_height` | INT | 512 | 64 – 16384 (step 32) | Tile height in pixels |
| `overlap_ratio` | FLOAT | 0.25 | 0.0 – 0.90 | Overlap as a fraction of the tile |
| `fade_ratio` | FLOAT | 0.50 | 0.0 – 1.0 | Fade band width within the overlap |
| `min_tile_size` | INT | 256 | 0 – 16384 (step 32) | Minimum tile edge; avoids tiny edge tiles |
| `seam_denoise` | FLOAT | 1.0 | 0.1 – 1.0 | Seam-neighborhood denoise cap; <1 prevents fast objects being cut at seams (suggest 0.5–0.8) |
Outputs: `spatial_split_param` (custom type) + `grid_preview` (string, shows the computed tile/overlap grid).
**`MMH3 Split Upscale`** — the main orchestrator:
| Parameter | Type | Default | Range / Options | Description |
| :--- | :--- | :--- | :--- | :--- |
| `model` | MODEL | — | — | Diffusion model used for re-sampling |
| `conditioning` | CONDITIONING | — | — | Positive conditioning |
| `negative` | CONDITIONING | — | optional | Negative conditioning |
| `latent` | LATENT | — | — | Input H3 AV latent (nested video 24ch + audio 32ch); batch 1 only |
| `noise` | NOISE | — | — | Noise source for the sampler |
| `sampler` | SAMPLER | — | — | Sampler |
| `sigmas` | SIGMAS | — | — | Sigma schedule |
| `cfg` | FLOAT | 1.0 | 0.0 – 100.0 | Classifier-free guidance scale |
| `temporal_split_param` | custom | — | optional | From `MMH3 Temporal Split Params` |
| `spatial_split_param` | custom | — | optional | From `MMH3 Spatial Split Params` |
| `seam_polish` | dropdown | off | off / auto / all | Extra de-seam pass on detected seams |
| `color_match` | BOOLEAN | True | True / False | Two-level color matching across tiles/chunks |
**Output:** `LATENT` — the upscaled H3 AV latent, ready for VAE decode.
> **Notes:** Both `* Split Params` nodes are optional — leave them unconnected for a single
> full-frame pass (no temporal/spatial splitting). The combo re-runs the sampler at the higher
> resolution, so it trades extra compute for VRAM headroom on long / high-res clips.
---
## 🧪 Model / Architecture
- **Latent format:** 24-channel Minimax H3 VAE latent, normalized per-channel with the training
mean/std before inference and de-normalized after.
- **Default detected architecture** (overridden automatically if the checkpoint differs):
`in_channels=24`, `in_blocks=12`, `out_blocks=12`, `base_channels=512`, `dropout=0.1`,
`temporal_every=2`, `temporal_kernel=5`, `attn=False`.
- **Interpolation:** the 2D node uses bilinear feature interpolation; the 3D node uses trilinear.
- **Temporal handling:** both variants preserve the time dimension (only H×W are scaled).
---
## 📊 Training Data
The upscaler was trained on **~80,000 paired samples** (a low-resolution latent paired with its
high-resolution target), balanced across modalities and scale factors to maximize generalization.
**By data modality:**
| Modality | Pairs | Share |
| :--- | :--- | :--- |
| Video clips | ~70,000 | ~87.5% |
| 2K images | ~8,000 | ~10% |
**By upscale factor (scale distribution, approximate):**
| Scale | Share | Note |
| :--- | :--- | :--- |
| 2× | 40% | Dominant factor — the most common real-world case |
| 1.5× | 10% | — |
| 2.5× | 10% | — |
| 3× | 10% | — |
| 4× | 10% | — |
| 1.0×–4.0× (arbitrary decimals) | 10% | Improves generalization to in-between / non-fixed scales |
The heavy emphasis on **2× (40%)** matches the most common practical use case, while the **10% spread
of arbitrary decimal scales between 1 and 4** prevents overfitting to the fixed 1.5×/2×/2.5×/3×/4×
buckets — letting the model handle any continuous `scale` in the 1.0×–4.0× range at inference time.
---
## 🙏 Acknowledgments
This node follows the neural-latent-upscaling approach pioneered by
[ComfyUi_NNLatentUpscale](https://github.com/Ttl/ComfyUi_NNLatentUpscale) by **Ttl**
(https://github.com/Ttl). The model architecture also draws on and references the
**LTX 2.3 Spatial Upscaler** (`ltx-2.3-spatial-upscaler-x2-1.1.safetensors`).
Thanks to both projects for the open-source foundation this work builds upon.