H3 Repair Plan (alpha)
'Frames 45 to 47 are wrong' → the whole arithmetic of a repair pass
- images
- hold_map
- ranges
- regen_mask
- plan
- report
Sometimes a finished clip is fine except for half a second of it. Repair is the bilateral sibling of the extension nodes: extension asks what comes after a clip, repair says these frames are wrong, render them again, and hand back the same clip with only those frames different. H3 Repair Plan does the arithmetic so you don't have to - you type the bad frame range, it emits everything a repair pass needs, and H3 Repair Splice reassembles.
How it works
Give it the clip length, a bad frame range, and a hold, and it returns four things:
hold_map- for H3 Time Smear (set itsdilationto the sameholdvalue, and turn itsexpand_to_endOFF - the plan says so in its report if you get it wrong, because an end-expansion rewrite moves every dilated coordinate it computed).regen_mask- a time-varying regenerate mask for H3 V2V Init, in dilated coordinates, wired in withtime_varyingon.plan- the JSON that goes to H3 Repair Splice.report- prices the pass before you run it.
Two rules run through it, and they pull in opposite directions:
- Masks snap to tokens. A latent time token can't be half regenerated, so the regenerate mask covers whole tokens. Frames group in 17s, each group is 5 tokens covering (1,4,4,4,4) frames - so "frames 45 to 47 are wrong" becomes "regenerate 43 to 50". The node snaps your
bad_start/bad_endoutward to whole tokens. - Splices are free. Reassembly is pure frame selection and can cut anywhere. So extend the mask where the grid forces it, then choose the splice points for picture reasons: enter in quiet motion, exit on a shot cut whenever one is near.
The cut rule is the one that earns its keep. On the pack's validation clip, the token snap pushed the regenerated span across a hard cut and the model reinvented the first frames of the next shot (the exit seam popped at 2.6x the clip's median frame delta). Extending the mask through the cut didn't fix it. Handing back to the original AT its own cut did. So shot_cuts takes a comma list of 0-based indices of each new shot's first frame, and cut_reach (8) decides how many frames past the snapped span a cut still counts as "near".
Inputs that matter
length,bad_start,bad_end- required.bad_start/bad_endare 0-based and inclusive: a file-numbered frame 46 is 45 here.hold(3) - de-rope hold on the regenerated span only; everything else stays real time.shot_cuts,cut_reach- the cut-exit behavior above.images- optional, for the report only: it computes per-frame luma deltas so the plan can tell you whether the entry frame is quiet, and supplies width/height when those are 0.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/matlowai/ComfyUI-MAINodes
or ComfyUI Manager → ComfyUI-MAINodes, restart. Category MAINodes/alpha.
Common gotchas
Audio is still a work in progress for the repair verb - the video splice is frame-exact, but don't expect the node to solve a repaired line of dialogue yet; repair the picture and keep your original track. And the two H3 Time Smear settings (dilation = plan's hold, expand_to_end off) are load-bearing; the report warns if it detects the mismatch.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| length | INT | 9022–3600 | frames in the SOURCE clip being repaired (world clock, not dilated) |
| bad_start | INT | 00–3599 | first bad frame, 0-BASED and inclusive. A file-numbered frame 46 is 45 here |
| bad_end | INT | 00–3599 | last bad frame, 0-based and inclusive |
| hold | INT | 31–8 | de-rope hold count on the regenerated span only; everything else stays real time. Set H3 Time Smear's dilation to the same number |
| fps | INT | 241–120 | — |
| shot_cuts | STRING | comma list of 0-based indices of the FIRST frame of each new shot, e.g. '53'. A cut near the span becomes the exit: the splice hands back to the original AT the cut | |
| cut_reach | INT | 80–68 | how many frames past the snapped span a cut still counts as 'near' and gets used as the exit |
| imagesopt | IMAGE | the source clip, for the REPORT only: per-frame luma deltas, so the plan can say whether the entry frame is quiet. Also supplies width/height when those are 0 | |
| widthopt | INT | 00–16384 | 0 = take it from images if wired, else the mask comes out 1x1 (H3 V2V Init resamples it to the latent grid anyway) |
| heightopt | INT | 00–16384 | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| hold_map | STRING | — |
| ranges | STRING | — |
| regen_mask | MASK | — |
| plan | STRING | — |
| report | STRING | — |