IAMCCS H3 Disk Upscale · 1 Save AV Checkpoint
Park the Latent on Disk Before You Upscale It
- latent
- native_audio
- checkpoint_path
- report
Upscaling a MiniMax H3 clip is not one job, it's two, and the two don't want to be in the same queue. The sampler needs the H3 model, the text encoder, the conditioning and a decoded batch of frames in memory. The upscaler wants the finished latent and nothing else. If you run both in one prompt you're paying for both peak memory footprints at the same time, which on a 12 GB card is how you end up staring at an OOM at 90%.
This node is the cut point. It takes what the sampler produced, writes it to disk, and gets out of the way.
What it actually does
Feed it the sampler's AV latent and the native audio, and it writes a single .safetensors holding three tensors: the H3 video latent, the matching audio latent, and the decoded waveform. Next to it goes a .json manifest with the frame counts, native canvas size, fps, join policy, and a SHA-256 of the checkpoint, so a later stage can prove it's reading the file it thinks it's reading rather than a stale leftover from an earlier run.
Everything lands under ComfyUI/output/IAMCCS/H3_DISK_UPSCALE/<render_id>/checkpoints/, named segment_00000.safetensors and its .json. Those two files are the contract: Stage 2 - Tiled Refine or Learned 3D - reads them, and Assemble Film joins the results at the end. The source docstring is blunt about the workflow shape: stage 1 and stage 2 must be queued as separate prompts, so the first generation's model, conditioning and decoded batch are actually released before the refine starts.
The inputs worth touching
latent and native_audio come straight off your sampler and its audio decode. Then:
- render_id - the folder. One id per job; keep it stable across the segments of a film.
- segment_index - your slot number, 0-based. Combined with
render_idthis is the filename. - source_frames - leave it at 0. Zero means "derive the exact decodable frame count from the AV latent" (the node computes
17*((tokens-2)//5)+5), and that's almost always what you want. Only set it if you deliberately want a shorter segment. - fps - must be 24. The node raises if it isn't, because H3's timeline is 24 fps native and every join below is frame-accurate on that assumption.
- technical_prefix_frames, join_overlap_frames, join_mode - the join arithmetic. The technical prefix is the head the assembler will trim off; the overlap and
cut/crossfadechoice decide how this segment meets the next one. If you're doing a single clip, leave them at 0 andcut.
Outputs are boring on purpose: checkpoint_path (a string - wire it into the loader or either Stage 2 node) and report, a readable summary line. It's a terminal output node, so queue it and the files appear.
Installing it
Standard pack install. ComfyUI Manager → search IAMCCS Nodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/IAMCCS/IAMCCS-nodes.git
Restart ComfyUI and hard-refresh the browser (Ctrl+Shift+R) - this pack ships frontend extensions, and a stale tab is a real source of "the node looks wrong". One copy in custom_nodes only; duplicated clones cause old node definitions and broken frontend routes.
For the disk-upscale family specifically you also want ffmpeg on PATH (the trim and concat steps shell out to it) and a current PyAV, since the frame-count validation imports av directly. The vendored MMH3Tools notes in this repo flag the classic symptom if your av drifts: ComfyUI failing to start with cannot import name 'ColorPrimaries' from 'av.video.reformatter' is fixed with pip install --upgrade "av>=17.0.0".
The pack ships no weights. And a reminder that matters more here than usual - H3's open weights are under a community licence whose grant excludes the US, EU, UK and South Korea, outputs included. That's a licensing question, not an install one, but you should know it before you build a pipeline around it.
Where people get burned
Three deliberate refusals, all of them things you'll hit at least once:
- It will not overwrite. If
segment_00000.safetensorsalready exists you get aFileExistsError, not a silent clobber. That's protection for your good take. Changesegment_index, or changerender_id, or move the old run aside. - The audio has to cover the video. The node checks the waveform length against
source_frames / fpsand refuses if the native audio is short. Silent-looking failures downstream almost always trace back to this check being skipped elsewhere. - The checkpoint must stay inside the H3 disk-upscale root. Later nodes validate the path is under
output/IAMCCS/H3_DISK_UPSCALE; move those files somewhere else and Stage 2 will refuse to load them. Keep the whole run folder together.
If you'd rather not think about any of this - you just want a bigger clip - the same pack's VAE-decode-to-disk routes are the lighter tools. This one earns its keep when the upscale is heavy enough that it needs its own queue.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| latent | LATENT | — | |
| native_audio | AUDIO | — | |
| render_id | STRING | h3_upscale_test | — |
| segment_index | INT | 00–99999 | — |
| source_frames | INT | 00–100000 | 0 = derive the exact decodable H3 frame count from the AV latent |
| fps | INT | 241–120 | — |
| technical_prefix_frames | INT | 00–10000 | — |
| join_overlap_frames | INT | 00–10000 | — |
| join_mode | COMBO | cut | 2 options: cut, crossfade |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| checkpoint_path | STRING | — |
| report | STRING | — |