H3 Frozen Video Cache
H3 Frozen Video Cache, explained
- model
- MODEL
The other two nodes in this pack fix MiniMax H3's audio - but each refinement step costs nearly a full model forward. On the author's RTX 5090, an audio-only refinement step took 20.7s against 23.0s for a full joint step: all ~37k frozen video tokens still run through all 50 blocks, and the output is thrown away. This node computes those frozen rows once, then lets later audio-only steps reuse them.
How it works
On the first refinement step it runs the model normally while recording each block's post-rope attention K/V (or post-norm hidden states) for the frozen rows - text, conditioning, video. On every later step it computes only the audio rows, about 1% of the sequence, attending against the cached K/V. Two honest caveats: the first step is always full price (that's the build), and it's an approximation - between rebuilds the frozen rows stop reacting to the evolving audio. refresh_interval N reopens that feedback path, at full cost per rebuild.
Wiring it up
Wiring is deliberately simple: MODEL in, MODEL out. Place it after your LoRA/patch stack and feed the patched MODEL into H3 Audio Refine Sampler (or a stock sampler fed by H3 Audio Refine Mask). It self-gates - it only activates when video is fully frozen and audio still generating, so pass-1 sampling passes through bit-for-bit. The first refinement step logs building cache | rows=... size=... backend=...; never see that line, and the cache isn't engaging.
Measured on the author's machine (one clip, cache in system RAM at hidden/int4): 5.7x per cached step (20.7s → 3.6s), 2.8x on the refinement pass, 1.4x end-to-end, with the build paying for itself after ~1.3 steps. Not a promise - the saving is compute removal, so it shrinks where weight streaming dominates.
The knobs that matter
cache_contents-hidden(default) stores post-norm hidden states and rebuilds K/V on the fly: ~2.7x smaller thankv, cached steps keep ~30% of the video matmul, ~3x faster.kvstores K/V directly: nearly free steps, but 2.7x the size.backend-auto(default) picks the first of vram/ram/disk that fits and logs why; or force one.precision-int4(default, smallest and fastest to stream),fp8(2x),bf16(4x, exact). Deviation is small against the approximation itself (int4 ~2e-3).refresh_interval- 0 = build once. Raise it if you want the frozen rows to periodically re-see the audio.verbose- per-step diagnostics so you can see where the time goes.vram_margin_gb- raise it if you hit CUDA OOM; it makes ComfyUI evict more before the cache allocates.
The disk gotcha
Now the warning, and it's the reason the defaults are what they are: disk caching is off by default, and keep it that way unless you mean it. With allow_disk on, the cache writes the whole thing to your drive on every build - around 10 GB per run on the README's clip, again on every invalidation. Thirty renders in an evening is ~300 GB written; daily, ~110 TB a year against a typical consumer NVMe's 600–1200 TBW endurance - scratch data, thrown away. It raises a clear error rather than silently falling back to disk when nothing fits. If you're memory-poor, prefer hidden/int4, or just bypass the node - refinement works without a cache, it's just slower, and exact.
Sizing: at 1344×768/24fps, hidden/int4 is roughly 1 GB per second of clip, scaling linearly with resolution and frame count; kv 2.7x, fp8 2x, bf16 4x. The exact number is printed to the console before every build - that log line is authoritative.
Do you want it?
Memory tight → skip it; the uncached pass costs nothing extra and is exact. Can spare ~10 GB and run a couple of refinement steps or more → use it. Not sure → verbose and A/B against enabled off - no rewiring.
Troubleshooting
If you hit OOM, the README's first suspect isn't the cache: ComfyUI has a known CUDA driver bug in dynamic VRAM streaming (issue #15255), and the documented workaround is a pair of startup flags:
python main.py --cuda-device 0 --disable-pinned-memory
If verbose shows 0 of 50 blocks on the cached path, the block replacement never ran and the cache can't take effect.
Installing
Install via ComfyUI Manager (search ComfyUI-H3-AudioRefine) or git clone https://github.com/Adudeguyman/ComfyUI-H3-AudioRefine.git into custom_nodes, restart. No Python dependencies, but it needs a ComfyUI with native H3 support including the AV masked path (0.33.x against master).
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | MiniMax H3 model, after the LoRA/patch stack. | |
| enabled | BOOLEAN | true | Turn the cache off without rewiring. When off, the model is passed through completely unpatched -- identical to bypassing this node, no memory allocated, refinement runs at full price per step. Handy for A/B timing against a cached run. |
| cache_contents | COMBO | hidden | What to cache per block for the frozen rows. Size scales linearly with clip length and resolution -- at 1344x768/24fps, int4 costs roughly 1 GB per SECOND of clip for hidden, ~2.7 GB/s for kv. hidden: post-norm hidden states, K/V rebuilt on the fly each step (~30% of video compute remains; ~3x faster cached steps). kv: post-rope K/V directly, cached steps nearly free but 2.7x bigger. The exact size is printed to the console before every build. |
| backend | COMBO | auto | Where the cache lives. auto picks the first of vram/ram/disk that fits (with margin) and reports the choice. disk works on any machine. |
| precision | COMBO | int4 | Cache storage precision. int4 (group-128) is smallest and fastest to stream; fp8 is 2x int4; bf16 is 4x int4, exact. See cache_contents for the per-second sizing rule; the exact size is printed before every build. |
| refresh_interval | INT | 00–100 | Rebuild the cache every N refinement steps (each rebuild costs one full-price step) so the frozen rows periodically see the current audio. 0 = build once, never refresh. |
| verbose | BOOLEAN | false | Log per-step diagnostics to the console: how many blocks took the cached / build / stock path, time spent inside the patched blocks, and time spent in the rest of the model call. Use this to find out where a refinement step is actually spending its time. |
| allow_disk | BOOLEAN | false | Allow the cache to be written to disk. OFF by default: a disk cache writes the whole thing (several GB) to your drive on every build, which is significant SSD wear over repeated runs. With this off, the node raises a clear error instead of falling back to disk when the cache does not fit in VRAM or RAM. |
| vram_margin_gb | FLOAT | 1.00–16 | Extra VRAM (GB) added to every room request made to comfy's memory manager, at build time and on each cached step. Raise this if you hit CUDA OOM during refinement -- it makes comfy evict more weights before the cache and its working buffers allocate. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |