Load Reviewed Mask Sequence
Stop re-running SAM on a mask you already approved
- images
- expanded_person_mask
- raw_person_mask
- provenance
Masking a video is the part of a character-swap or person-removal job that never ends. You describe the subject, SAM tracks it, you review forty frames, you fix the three where it drifted, and then - because you changed a sampling seed - the graph re-runs the mask chain and you're back to tracking forty frames to get an identical result.
Load Reviewed Mask Sequence is the escape hatch. It reads a .npz mask sequence you saved and already approved, and hands you the same two masks the live chain would have produced.
What it does with the file
It looks for mask_file inside ComfyUI's input directory - path traversal is refused, so it's genuinely "a file in input," not any path on disk. Inside the archive it expects a mask array: one frame per source frame, boolean-ish, at your prepared resolution.
Then it's strict in ways that matter. If the archive has a present array with any false entries, it refuses: that's the record that says some frames were never reviewed, and loading it would be pretending otherwise. If the frame count doesn't match source_frames exactly, it refuses. Non-finite values, refused. If the mask resolution differs from your images, it nearest-neighbour resizes rather than bilinear-blurring the edges - the right call, since a soft mask edge here just becomes an ambiguous instruction to the sampler.
After that it runs the identical Euclidean expansion as the live path, tail-pads to the padded frame count, and returns both masks plus a provenance JSON string: file path, SHA-256 of the file, source frame count, prepared frame count, dimensions, expansion radius, the metric used, and an explicit anchor_auto_expansion: false. That JSON is the closest thing to an audit trail in this pack, which is a nice touch for anyone reusing masks across runs.
The provenance string also does quiet load-bearing work: the node's change-detection hashes the file contents, so editing the NPZ invalidates downstream caches properly instead of returning a stale render.
Inputs and outputs
Required: mask_file (default person-mask.npz, relative to ComfyUI's input folder), images (prepared frames - for resolution matching and to know how far to pad), source_frames (unpadded count), expansion_px (0–256, default 64 - applied at load time, so you can experiment without re-saving).
Three outputs: expanded_person_mask (what you wire into Window Inputs' mask, or preview with an overlay), raw_person_mask (the unexpanded mask, useful for a clean preview or a different pipeline), and provenance.
Install
Manager → H3 Relay → restart. Manual:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/akatz-ai/h3-relay.git
Needs numpy, scipy and Pillow - undeclared in the pack's pyproject.toml (which lists zero dependencies), but present in most ComfyUI environments. ComfyUI 0.37.0+. No models required for this node; the file has to come from somewhere, though, and the intended source is Save Mask Sequence or the app's own reviewed-mask export.
Where people get burned
Saved mask has unreviewed missing frames is the error that confuses people most, because the file opens fine in numpy and looks plausible. It means the present array isn't all true - the export knew about frames it couldn't mask. Go fix them (Recover Empty SAM Frames, Refine Mask) and re-export; don't try to patch the NPZ by hand, since the same file is what the cache identity hashes.
Mask and real source timeline must match exactly is the other one. source_frames here is the unpadded count from Prepare Source. Passing h3_length gives you a mask that claims to cover tail frames that were never tracked, and the node rightly calls it a mismatch.
And one expectation to set: this node doesn't review anything. It's a loader for a mask you already reviewed. If the file is wrong, the render is wrong, and the errors you'll get downstream are H3's about a subject disappearing, not this node's about a bad file.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| mask_file | STRING | person-mask.npz | — |
| images | IMAGE | — | |
| source_frames | INT | 124 | — |
| expansion_px | INT | 640–256 | Outward Euclidean radius at the prepared video resolution. No automatic anchor-based expansion. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| expanded_person_mask | MASK | — |
| raw_person_mask | MASK | — |
| provenance | STRING | — |