MiniMax H3 Tiled Sampler
MiniMax H3 Tops Out at 768p — This Sampler Tiles Around It
- model
- positive
- negative
- latent
- LATENT
MiniMax H3 is the 33B open-weights video model that generates picture and audio in a single pass, and that design is exactly why it eats your card alive. Video and audio are packed into a single attention sequence, so the cost is driven by the video token count, and the DiT's trained canvas stops at 1344x768. Ask for 1080p-ish output - a 15-second clip at about 2 megapixels - and you are simply outside the field of view the model was trained on.
This node is one answer to that. It denoises the H3 audio-video latent in overlapping spatial tiles: each tile is a full pass over a crop that still fits inside the native canvas, so peak VRAM is tied to the tile instead of the whole frame. The author's own benchmark is a 15-second upscale to ~2MP on a 16GB RTX 4060 Ti, peaking around 12GB and taking 70 minutes. Slow, but completely runnable. (And before you spend an evening on it: H3's community licence excludes the US, EU, UK and South Korea, where the hosted Hailuo API is the licensed path rather than the local weights.)
How it actually works
It isn't a new sampler, and that's the point: the node clones your model, attaches a DIFFUSION_MODEL wrapper through ComfyUI's patcher extensions, then calls the stock sampling path - same samplers, schedulers, seed and denoise behaviour as KSampler. Per model call, the wrapper:
- Cuts the video latent into tiles aligned to the DiT's 2x2 patch grid, pulling the last tile of each axis back so every tile ends up the same size.
- Runs one forward per tile. Text, audio, keyframe and reference rows ride along in every tile, which keeps the audio global and the guides working.
- Gives each tile's video rows the position ids they hold in the full packed layout, so RoPE coordinates stay absolute. Rebuild the layout at tile size instead and the spatial grid gets renormalized - the model would read your tile as a whole frame.
- Blends the tile velocities with linear ramps across the overlap - fade in over the head cells, fade out over the tail, weighted average - and averages the audio velocities. That blending is how overlap hides seams.
A PREPARE_SAMPLING wrapper also shrinks the VRAM estimate to one tile's worth of video cells, so the model isn't offloaded for a sequence length that never gets built.
The inputs that matter
Most of the widget row is stock KSampler - model, positive, negative, latent, seed (with control_after_generate), steps, cfg, sampler_name, scheduler, denoise. Three extra fields are the whole story:
tile_width/tile_height- default 1344 and 768, the model's native canvas, rounded down to 32 pixels. Don't lower these out of habit: attention can't cross tile borders, so smaller tiles mean weaker global spatial coherence.tile_overlap- default 192 pixels. More overlap hides seams and costs you more tiles, hence more time.
latent has to be an H3 AV latent - the 24-channel video stream plus the audio stream - from Empty MiniMax H3 AV Latent, MiniMax H3 Image to Video or MiniMax H3 Reference to Video. There's a single output: LATENT, the same dict with new samples, which you wire straight into your H3 decode/save path. It is not an output node. And when your canvas already fits in one tile, the node samples it whole - so it drops into an existing H3 workflow in place of KSampler without doing anything surprising.
Installing it
Through ComfyUI Manager, search the pack title "MiniMax H3 Tiled Sampler". Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/fr0nky0ng/comfyui-h3-tiled-sampler-fr0nk
# restart ComfyUI
Nothing to pip install - no requirements.txt, no declared dependencies - but it does need a ComfyUI new enough to ship H3 and the V3 node API: it imports comfy.ldm.minimax.model.PackedLayout and registers through comfy_api.latest, so an older build just won't load it.
The model files are the real download: an H3 checkpoint (the example loads a pruned int8 "convrot" build), a Qwen3-VL 32B text encoder, and separate video and audio VAEs. Expect to run a quantized build. The bundled example workflow also leans on low-VRAM attention and chunked-feedforward nodes, plus KJNodes, rgthree, VHS and a video/audio latent concat node - the sampler itself needs none of them.
Where people get burned
The trade is blunt: much slower than a whole-canvas pass, far less VRAM - the same deal video upscalers have been taking for a couple of years. The failures you'll actually hit are narrow:
- Error: "expects a MiniMax H3 AV latent." You fed it a plain video latent. It wants the nested AV latent with the 24-channel video stream.
- Error: "needs a latent whose width and height are multiples of 32 pixels." Every H3 latent node already guarantees this, so if you hit it you hand-rolled the latent somewhere.
- Seams or drifting detail. Keep tiles at the native 1344x768. Global coherence weakens as tiles shrink, so the fix is more overlap, not smaller tiles.
- "It did nothing." Check the console; on a canvas that fits one tile it deliberately runs whole. Batch size is 1, as with H3 itself.
Start from the shipped example's numbers for an upscale pass: denoise 0.2, 4 steps, cfg 1, euler / simple, tiles at 1344x768 with 64 pixels of overlap, driven by a 4-step turbo LoRA whose filename literally says 768p. Distilled LoRAs like that are trained at the native canvas - one more reason to leave your tile size alone.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| latent | LATENT | — | |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 201–10000 | — |
| cfg | FLOAT | 8.00–100 | — |
| sampler_name | COMBO | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 | |
| scheduler | COMBO | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 | |
| denoise | FLOAT | 1.000–1 | — |
| tile_width | INT | 134464–16384 | Tile width in pixels, rounded down to 32. The default is the model's widest native canvas. |
| tile_height | INT | 76864–16384 | Tile height in pixels, rounded down to 32. The default is the model's native short edge. |
| tile_overlap | INT | 1920–16384 | Overlap between neighbouring tiles in pixels. More overlap hides tile seams and costs more tiles. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |