MiniMax H3 Pixel Continuity • Keep Boundary Sources
Hoard 17 pre-upscale frames so you can fix a join later
- state
- video
- options
- video
- status
This is a plumbing node, and the honest pitch is narrow: it is the node that makes the boundary-refinement experiment possible by saving the frames that would otherwise be thrown away.
Here's the problem it solves. In a chained H3 run, every scene after the first repeats the previous scene's tail as visual context, and the saved take is trimmed back to just its own new frames. When you pixel-upscale those scenes with USDU, the join between the previous scene's high-quality tail and the new scene's upscaled opening can drift - different sharpening decisions on either side of a cut that's supposed to be invisible. The refinement experiment redraws a short window across that join. To do that it needs each side of the join as it looked before the upscaler touched it, because the pre-USDU pixels still carry the generator's own detail.
So MiniMaxH3PixelBoundaryCapture sits between DLSS and Protect Tail in the deferred-upscale workflow and keeps exactly that: a small pre-USDU fragment per marked boundary. If the experiment is off, the node does no I/O at all - no decode, no allocation, video comes straight back out.
What it does with your frames
Inputs are state (the upscale chain's state), video (the incoming video for this scene) and options (the settings object from MiniMax H3 Pixel Continuity • Boundary Experiment). Nothing else.
A scene can be on both sides of marked joins, so the node works out its roles first: tail if it's the scene before a marked join, head if it's the scene after one. No roles, no work - status just reports that nothing was marked. With roles, it probes the video and cuts the last frames_per_side frames before the boundary for a tail role, and the first frames_per_side frames of the delivered scene for a head role, writing each as its own file under the child profile's boundary_sources/ directory, named with a hash of the source take and the recipe. Publication is atomic - temp file, then os.replace - so an interrupted run can't leave a half-file that the export would later trust.
The cached samples are then read back by MiniMax H3 Pixel Continuity • Experimental Boundary Export after assembly.
Install and prerequisites
ComfyUI Manager, search MiniMax H3 Contex Loop, or:
cd ComfyUI/custom_nodes
git clone https://github.com/seitanism/ComfyUI-H3-Motion-Context-MultiRef.git
git clone --branch main https://github.com/ethanfel/ComfyUI-MiniMaxH3-Context-Loop.git
Restart ComfyUI. No pip dependencies, but this node rides the same file-backed VIDEO transport the example's DLSS and USDU nodes use, which comes from ComfyUI-ContextAnchoredTile-videopath. Drop that pack and you'll get a Pixel continuity VIDEO requires ComfyUI-ContextAnchoredTile-videopath for file-backed transport error at the first marked boundary. The rest of the pixel-continuity workflow also expects ComfyUI-DLSS5-Enhancer and ComfyUI_UltimateSDUpscaleGuider_H3. The H3 model files themselves aren't in the repo.
Traps worth knowing before you queue
Turn the switch on before upscaling into a new profile. The options object has to match the recipe the Upscale Adapter recorded, and it won't: you'll get Connect Boundary Experiment recipe_json to the Upscale Adapter. Enable the experiment, then start a fresh upscale profile. A profile that already completed has no pre-USDU fragments, so you can't retro-fit this onto it - you re-run the pixel upscale, not the generation.
Frames come in 17s. frames_per_side is clamped to 17, 34 or 51 because it has to line up with H3's temporal grid. Only the default 17-frame configuration has GPU validation, and larger windows cost more sampling memory.
Give it a real disk. The fragments are small, but they live in the profile directory alongside everything else the pixel upscale writes, and the refinement export later wants a fast local SSD for its canvas. Blank canvas settings fall back to ComfyUI's temp directory, which is usually fine and occasionally not.
A short scene is silently skipped - if the delivered frame count is under frames_per_side, status says so and no samples are kept for that boundary. The export will then skip that join too, which is the behavior you want, but it's easy to miss in a status line you didn't read.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| state | H3_CHAIN_UPSCALE_STATE | — | |
| video | VIDEO | — | |
| options | H3_PIXEL_BOUNDARY_OPTIONS | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| video | VIDEO | — |
| status | STRING | — |