Nodes/Fantastic H3 Prompt Builder/Fantastic H3 Object Mask (SAM 3.1)
ComfyUI Node

Fantastic H3 Object Mask (SAM 3.1)

The SAM 3.1 node you never place yourself

By Adudeguyman·Created 3 months ago·Updated 7 days ago· 303
Fantastic H3 Object Mask (SAM 3.1)
  • model
  • clip
    ◄video►
    ◄text►
    ◄points►
    ◄start0.000►
    ◄end0.000►
    ◄threshold0.50►
    ◄max_objects4►
    ◄modereplace►
    ◄base►
    ◄every_framefalse►
    ◄subjectfalse►
    ◄max_frames0►
    ◄pictures►

    If you looked at your queue and found a node you never added, this is why. Fantastic H3 Object Mask is the worker behind the Media Loader's Auto Mask layer: you click what you want masked, type what it is, press ▶ Run Auto, and the loader quietly builds a two-node prompt - a CheckpointLoaderSimple for SAM 3.1 plus this node - and sends it to the queue. It has no outputs to wire. It runs, saves a mask file next to your clip, and reports back to the panel.

    So the honest framing is: you don't use this node, you trigger it. But it's worth understanding, because every "Auto Mask found nothing / grabbed the wrong thing" complaint is a question about what it does with your dots and your words.

    How it works

    It imports core ComfyUI's SAM 3 nodes (comfy_extras.nodes_sam3) and drives them two ways, which is exactly the point of SAM 3 over the older detect-then-segment stack.

    Give it points and it uses your green dots as seeds, runs SAM on each marked frame, then tracks - forward from the first dot, and backwards too when there's only one. Each additional marked frame re-seeds the tracking from there, which is how you fix a mask that goes wrong halfway through the clip.

    Give it text only and it's concept segmentation: the phrase goes through SAM's text encoder and every matching instance is found, on every frame. Combine the two and the name narrows what's under your dots - "green jacket" while pointing at a person masks the jacket, not the person. That's the local replacement for the old GroundingDINO-plus-SAM pipeline.

    Then it merges the result with the layer's existing mask (replace, add, subtract), saves it beside the clip at one bit per pixel, and prints how many frames it hit.

    The inputs that matter

    Only two are yours in practice:

    • text - what to find. Commas for several things.
    • every_frame - the fix for a mask that dies after a cut. With dots and a name, it re-finds the named object wherever tracking lost it. The tooltip warns it can pick up look-alikes, and it will.

    The rest is the panel filling things in: model and clip (SAM 3.1 from Load Checkpoint), video (a Media Loader path like minimax_h3/clip.mp4 [input]), points (your clicks as JSON, coordinates 0–1 on the source frame, green positive and red negative), start/end for the kept span, threshold (0.5), max_objects (4), and mode/base for accumulating layers. You get a RuntimeError telling you to update ComfyUI if the installed version predates SAM 3 support.

    There are no outputs. It's an output node, so it queues and lands in your history even with nothing wired to it.

    Install

    Part of the Fantastic H3 pack: search Fantastic H3 Prompt Builder in Manager, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Adudeguyman/ComfyUI-Fantastic-MiniMaxH3-PromptBuilder
    

    Then restart ComfyUI completely. Auto Mask additionally needs the SAM 3.1 checkpoint - sam3.1_multiplex_fp16.safetensors from Comfy-Org/sam3.1 - dropped in models/checkpoints. The pack never downloads it, and the loader will tell you it found no SAM 3.1 checkpoint rather than failing mysteriously. Worth knowing what you're pulling: SAM 3 is not Apache-licensed like SAM 1 and 2 - it's Meta's own SAM License, permissive for this kind of work but share-alike and revocable.

    Where it goes wrong

    "SAM found nothing at the dots." Your click landed on background, or on a shadowed sliver of the object. Click somewhere unambiguous - on the object itself, not its edge.

    It masks the whole person when you wanted the jacket. Type the part as well. A click alone is a whole-object proposal; the name and the dot together restrict it.

    The mask drifts after a few seconds. Add a dot on a frame where the object is clear and run again - each marked frame re-seeds tracking from there. If it dies at a cut entirely, turn on every_frame.

    Finding the object is slow. It's a real queue job competing with your renders, on real SAM weights, over the clip's frames. A queued generation finishes first. That's expected, not a hang.

    Categoryconditioning/video_models

    Inputs (15)

    NameTypeDefaultDescription
    modelMODELSAM 3.1, from Load Checkpoint.
    clipCLIPSAM 3.1's text encoder, from the same Load Checkpoint.
    videoSTRINGA Media Loader file, e.g. minimax_h3/clip.mp4 [input].
    textSTRINGWhat to find, e.g. phone. Commas for several.
    pointsSTRINGClicked points as JSON: {"frames": [{"time": seconds, "positive": [{"x", "y"}], "negative": [...]}]}, x and y from 0 to 1 on the source frame.
    startFLOAT0.0000–36000Trim start in seconds: only the kept span is masked.
    endFLOAT0.0000–36000Trim end in seconds; 0 is the end of the clip.
    thresholdFLOAT0.500.05–0.95—
    max_objectsINT41–16—
    modeoptCOMBOreplaceWhat to do with the clip's current mask: replace it, add what's found to it, or take what's found out of it.
    baseoptSTRINGThe layer's current mask file, for add and subtract.
    every_frameoptBOOLEANfalseWith dots and a name: also look for the name on every frame, and use what it finds wherever tracking lost the object (after a cut, say). Can pick up look-alikes.
    subjectoptBOOLEANfalseFor the RefMod Create tab: the mask goes to the cache, kept only until the RefMod is made, and finding nothing is reported instead of failing the run.
    max_framesoptINT00–100000Frames masked from the trim start; 0 masks the whole trim.
    picturesoptSTRINGPictures to find the subject in, instead of the clip, as JSON: [{"file", "rotate", "mirror", "positive", "negative"}], dots from 0 to 1 on the picture as turned and mirrored. With max_objects 1, only the largest match is kept.

    Outputs (0)

    No outputs