Zura · Include On-screen Text in Removal Mask
Making the model repaint the captions too
- performer_mask
- text_mask
- text_boxes
- clip_details
- tracking_segments
- MASK
- GENJ_CLIP
You've masked the performer. You run the render. And the storefront sign behind them, the subtitle burned in by the original camera app, and the chyron in the corner all come back unchanged - because the model was only allowed to touch the pixels inside your mask. GenjTextRemovalMask ("Zura · Include On-screen Text in Removal Mask") is how you fold detected text into the mask without hand-painting a rectangle per frame.
It's the mask half of Zura Studio's "Remove on-screen text" option. The other half is H3's LaMa-based background repair, which needs ComfyUI-ArtVenture and ComfyUI-KJNodes installed and may download a ~196 MB big-lama.pt on first use.
How it combines the two masks
Required inputs: performer_mask (MASK), text_mask (MASK), text_boxes (BOUNDING_BOX), clip_details (GENJ_CLIP), padding (INT, 0–32, default 5).
Optional: hold_regions (BOOLEAN, default true - the tooltip is the honest description: Keep detected text panels editable through each tracking segment. Moving text can create a wider removal area.) and tracking_segments (GENJ_TRACK_SEGMENTS).
The pipeline, in order:
- Frame counts and the raster must line up with the performer mask:
Text detection and the performer mask must cover the same frames.orTracking segment frame count and raster must match the performer mask. - The text mask is nearest-resized to the performer raster and thresholded at 0.5.
- Each detection box is painted into its frame with your padding grown around it, so the anti-aliased edge of a letter is inside the editable area rather than half-outside. Then a max-pool dilation by the same padding cleans up the boundary.
- Connected components are filled per frame -
_fill_frame_component_bounds- so a detection that came back as a wide rectangle from the detector doesn't drag extra pixels into the mask. That's an explicit design decision with a comment: "These rectangles must never be used to create editable pixels." - Text is held across time. With segments connected, the union is computed per shot, so text stays editable through a tracking segment but never leaks across a cut. Without segments,
hold_regionsunions the whole clip (or, switched off, shares detections across a seven-frame window). - The result is combined with the performer mask by
torch.maximum, and a pile of metadata is written intoclip_details:remove_text, detection and frame counts, text pixel count, compactedtext_regionsrectangles, the raster, and whether the regions were held.
Outputs: MASK (the combined edit mask) and GENJ_CLIP (the details with the text metadata attached).
The cleanest way to think about it: the mask is now "performer or captions", and the metadata says which regions were captions, so the downstream H3 background repair can try to fix the background-only ones in one pass instead of making the video model hallucinate over a sign.
Install
ComfyUI Manager → search Zura Nodes → install → restart. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/ZURAVFX/ComfyUI_zura_nodes
python -m pip install -r ComfyUI/custom_nodes/ComfyUI_zura_nodes/requirements.txt
Mask arithmetic uses OpenCV, which ComfyUI already ships with. The text detection upstream is SAM 3.1 (checkpoints/sam3.1_multiplex_fp16.safetensors), driven by a prompt like text:20 - that's the pack's own convention in its graphs. For the repair pass on H3 you need ComfyUI-ArtVenture and ComfyUI-KJNodes, and ffmpeg on PATH for the rest of the pack.
Gotchas
hold_regionson moving text inflates the mask. If a caption slides across the frame, holding the union means the editable region becomes the swept path. That's the trade the tooltip warns you about; turn it off and you'll get a seven-frame window instead, which flickers less widely but can leave ghost text on slow pans.- The mask grows, so the render does more work. More editable pixels is more hallucination opportunity. If the background behind a caption is busy, expect H3 to invent something there; review the take.
- No segments connected = no cut awareness. Wire
tracking_segmentsfrom the tracking nodes if your clip has cuts, or a caption before the cut stays editable after it. - Empty detection. A caption at very low contrast, or a prompt that didn't match the style of text, gives you an empty text mask and a
MASKthat's identical to your performer mask. Checktext_boxes_detectedinclip_detailsbefore assuming the option worked.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| performer_mask | MASK | — | |
| text_mask | MASK | — | |
| text_boxes | BOUNDING_BOX | — | |
| clip_details | GENJ_CLIP | — | |
| padding | INT | 50–32 | — |
| hold_regionsopt | BOOLEAN | true | Keep detected text panels editable through each tracking segment. Moving text can create a wider removal area. |
| tracking_segmentsopt | GENJ_TRACK_SEGMENTS | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |
| GENJ_CLIP | GENJ_CLIP | — |