Nodes/ComfyUI-M8nodes/M8 · 多角色编辑
ComfyUI Node

M8 · 多角色编辑

Two characters, one prompt, no swapped hair colours

By chenr5934-tech·Created 23 days ago·Updated 8 days ago· 2
M8 · 多角色编辑
    • prompt
    ◄formatregional►
    ◄use_fillfalse►
    ◄config{"format": "regional", "base": "", "global": "", "use_fill": false, "characters": [{"enabled": true, "name": "Character 1", "prompt": "", "x": 0.0, "y": 0.0, "w": 0.5, "h": 1.0, "weight": 1.0, "feather": 0, "fill": false}, {"enabled": true, "name": "Character 2", "prompt": "", "x": 0.5, "y": 0.0, "w": 0.5, "h": 1.0, "weight": 1.0, "feather": 0, "fill": false}]}►
    ◄base_prompt—►
    ◄width1024►
    ◄height1024►

    Prompt adherence is global. Describe two people in one prompt and the attributes smear - the redhead picks up the other one's jacket, the poses merge, and no amount of careful wording fixes it because the conditioning genuinely applies to the whole canvas. That's what regional prompting exists for, and M8 · Multi-Character Editor is a nice front end for the assembly step: one card per character, a canvas you drag boxes on, and a string at the end.

    What it does, honestly

    Regional prompting is not a fad and not a solved problem. It's run at a steady 20–40 threads a month since 2023, never spiking and never dying, and it gets re-implemented every time the architecture underneath changes. What's shifting in 2026 is where it sits in the workflow: newer LLM-based text encoders parse relationships between subjects much better than CLIP did, so bleeding is less of a routine annoyance. Regional prompting is drifting from "always on" toward "the fix for hard cases".

    The hard ceiling is composition. Two characters who overlap, touch, or hug cannot be cleanly separated into regions, and the blending artifacts come back no matter which node you use. Plan the frame with them apart and this works; plan it with them embracing and nothing here saves you.

    How it works

    Each character is a card holding a prompt, a region, a blend weight, a feather value, and a fill flag. A character with no region gets treated as the whole frame and logged, rather than silently dropped. Regions are stored as percentages, so resizing the canvas never moves anybody relative to the frame. The card prints the exact syntax it's going to emit, so you're not hunting through a preview box.

    Three output formats, and picking the right one is most of the job:

    | format | What comes out | What it's for | |---|---|---| | regional (default) | prompt MASK(x1 x2, y1 y2, weight), pieces joined with AND | comfyui-prompt-control (Regional Prompts) | | attn | COUPLE(x1 x2, y1 y2, weight) prompt | comfyui-prompt-control (Attention Couple) | | plain | a comma-separated prompt, region syntax dropped | anything at all |

    A FEATHER(n) suffix appears when feather is above zero, and FILL() when fill is on. There are guards doing real work here: coordinates clamp to 0–1, a minimum span of 0.01 keeps you from emitting a zero-width mask that means nothing downstream, blend weight clamps to 0.05–2.0, and feather clamps to 0–512. Bad config raises a coded error (M8-PROMPT-001, M8-PROMPT-002) instead of quietly degrading to a bare base prompt - which is the failure mode of the older node this one is a rewrite of, and the reason the rewrite exists.

    The inputs and outputs

    Required are format, use_fill and config (the JSON holding base, global and the character array). Optional are base_prompt - an input socket for the shared scenery, style or quality tokens every character lives inside - plus width and height, default 1024×1024. One output: prompt (STRING).

    width/height don't enter the prompt text. Regions are percentages, so the numbers don't participate in the maths; they set the canvas aspect so the boxes you drag sit where they'll actually land, and they get logged so you can confirm the aspect matches what you meant.

    Installing it

    Nothing special - same pack, no dependencies:

    cd ComfyUI/custom_nodes
    git clone https://github.com/chenr5934-tech/ComfyUI-M8nodes.git
    

    Restart. But the install isn't really finished until you decide about comfyui-prompt-control: the MASK(...) and COUPLE(...) syntax only means something to a node that parses it. Without it, use plain and leave regions out of the picture entirely.

    Where it bites

    The single most common mistake is pasting MASK(...) text into a plain text encoder. Nothing strips it, the model never learned that syntax, and you've just handed it literal punctuation to tokenize. If prompt-control isn't in your graph, switch format to plain and stop pretending.

    Second: the canvas aspect has to match your latent size. "Left third" drawn on a square canvas becomes a different slice when you generate 16:9.

    Third: with regional or attn and no enabled character carrying a prompt, you get M8-PROMPT-003 - a deliberate error rather than an empty string travelling downstream to confuse you later. And the panel's semantic check flags the cases where the syntax is valid but the picture won't be: overlapping regions, fill enabled in several places, feather that's oversized relative to the frame. Worth reading before you hit queue, since none of those produce an error anywhere else.

    CategoryM8/提示词

    Inputs (6)

    NameTypeDefaultDescription
    formatCOMBOregional3 options: attn, regional, plain
    use_fillBOOLEANfalse—
    configSTRING{"format": "regional", "base": "", "global": "", "use_fill": false, "characters": [{"enabled": true, "name": "Character 1", "prompt": "", "x": 0.0, "y": 0.0, "w": 0.5, "h": 1.0, "weight": 1.0, "feather": 0, "fill": false}, {"enabled": true, "name": "Character 2", "prompt": "", "x": 0.5, "y": 0.0, "w": 0.5, "h": 1.0, "weight": 1.0, "feather": 0, "fill": false}]}—
    base_promptoptSTRING—
    widthoptINT102464–8192—
    heightoptINT102464–8192—

    Outputs (1)

    NameTypeDescription
    promptSTRING—