Glide Upscale Hold
Stop your upscaled H3 chain from changing texture at every join
- latent
- latent
Two ways a chained H3 clip goes wrong
MiniMax H3 gives you 4–15 seconds at a time. So you chain: render clip A, feed its tail back in, render B that continues it, splice.
H3 Studio already handles the draft version: it continues from the previous clip's own latent instead of decoding to pixels, taking 22 frames, and re-encoding. That round trip was cooking the picture.
The second only shows up when you upscale your keepers, which by now you probably do. In the upscale pass each clip is refined on its own - two refines, two independently invented fields of fine texture. Brick grain, pores, whatever the model hallucinates at the new resolution. Motion still matches. Texture doesn't, and at the join your eye catches it even if you can't name it.
Glide Upscale Hold pins the head of the clip you're refining to the refined tail of the clip before it, so the refine continues the previous clip's texture instead of starting its own.
How it works
It's a latent swap with a mask. You feed it the upscaled audio+video latent out of Concat AV Latent, right before the refine sampler. It converts your overlap into latent frames - H3's grid is 2 head frames plus 5 per 17 pictures, so it snaps the overlap down to a valid 17k+5 first - then pulls the last k latent frames of the previous clip and writes them over the first k of the current one.
Then the important half: it sets a noise_mask of 0 across those held frames, 1 everywhere else. Zero noise means the sampler won't touch them - they survive the refine exactly as the previous clip left them, and the rest refines around them. The audio half passes through untouched; this is a picture-side fix.
The "refined tail" is a file: Glide Video writes a .h3latent sidecar next to every video it encodes, and this node reads the one beside whatever source_video names. That contract is why the wiring below isn't optional.
The inputs, and the one output
latent - the upscaled AV latent from Concat AV Latent, right before the refine sampler.
source_video - H3 Studio's source_video. In an upscale pass that's the previous clip's upscaled render. Empty: pass-through. Wire-only, like overlap_frames.
overlap_frames - H3 Studio's overlap_frames, default 22: how much of the previous clip re-renders here. Wire it across instead of retyping it; the window belongs in one place per graph.
One output, latent, into your refine sampler's latent_image.
Upscaler ──> Concat AV Latent ──> Glide Upscale Hold ──> refine sampler
^ ^
H3 Studio ──source_video──────┘ │
──overlap_frames─────────┘
refine sampler ──output (LATENT)──> Glide Video (save_latent = tail)
That last line is what people skip. The refine sampler's output has to reach Glide Video's latent input with save_latent on tail, or the next clip has nothing to hold and this node passes through.
Installing it
It ships in the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/CGlide/ComfyUI-CGlide
Restart; it's under CGlide in the node menu. In ComfyUI Manager, search CGlide and take nightly.
Two traps. The Manager's registry entry lands in a folder called cglide, not ComfyUI-CGlide - not a git clone, so git pull does nothing there, and keeping both means the pack loads twice. Delete it and clone. And the pack wants PyAV, torchaudio and ffmpeg on your PATH; the first two usually ship with ComfyUI, ffmpeg is the one that bites.
Models are the Comfy-Org MiniMax H3 set plus an H3 latent upscaler, since the upscale pass needs one. On a smaller card Kijai's w4a8 build is ~11.8 GB versus 21 GB - but that path needs ComfyUI 0.31.0 or newer; older and you get a black video with sound, and no error explaining it.
When it isn't working
Read the console. Every pass-through prints a line starting [Glide Upscale Hold]. If you see "passing through", the node is doing nothing and just told you why - that's the whole debugging session:
- no refined tail beside … - the sidecar is missing. You wired the draft sampler into Glide Video instead of the refine sampler, or
save_latentisoff. Re-render the previous clip with the refine sampler wired in. - size mismatch: previous tail is AxB, this clip is CxD - the two clips were upscaled with different settings. Megapixels, tile count and upscaler model have to match across a chain.
- N latent frames do not fit - the overlap is longer than one of the clips can hold. Shorter overlap; never on the first clip of a chain.
- could not read … - stale or corrupt sidecar. Delete it and re-render.
Don't expect it to fix what the drafts already broke. The author's own two-clip test: motion perfect, no hitch, some detail still different because the drafts differed there. This holds texture across the refine; it can't align two drafts that were never identical.
Long chains still drift with or without this - the model pushes its own look at every link. Three or four is fine; for a long one-take, grade in post. And if a pack update changes this node's widgets, delete and re-add it: ComfyUI matches saved values by position and smears the old ones across the new fields.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| latent | LATENT | The upscaled audio+video latent, right before the refine sampler (Concat AV Latent's output). | |
| source_video | STRING | H3 Studio's source_video. In the upscale pass that is the previous clip's UPSCALED render; its refined tail (.h3latent) is read from beside it. Empty: pass through. | |
| overlap_frames | INT | 220–4096 | H3 Studio's overlap_frames - how much of the clip before this one re-renders here. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | — |