ComfyUI Node

Seed

Seed — The Node That Fixes the One Thing `control_after_generate` Gets Wrong

By 0xBeycan·Created 23 days ago·Updated 3 days ago· 2
Seed
    • SEED
    ◄seed0►

    The injury it prevents

    Every ComfyUI user has this scar: you get a great image on a random seed, you switch the dropdown to fixed to keep it, and the seed that made it is already gone. That's not you being slow. control_after_generate fires after the run finishes, so the number in the box is always the one that will be used next, not the one that just produced what you're looking at.

    There's a global fix (Settings → the "widget control mode" setting, switched from After to Before) that every beginner guide should lead with. This node routes around the problem entirely: a seed widget with explicit buttons, and a -1 that means "new random seed every run" without any of the after-the-fact bookkeeping.

    How it works

    One integer widget, seed, running from -1 to 0xffffffffffffffff, default 0. One output, SEED. Three buttons underneath:

    • 🎲 Randomize Each Time - sets the widget to -1. Every queued run draws a fresh seed.
    • 🎲 New Fixed Random - writes a concrete random number in. It stays fixed from then on.
    • ♻️ (Use Last Queued Seed) - puts the seed of the last queued run back in the box. Greyed out and in parentheses until a run has actually used a seed different from the widget; after a random run it reads ♻️ <seed>.

    The interesting part is what happens to -1. It never reaches the sampler. Right before the prompt is sent, the frontend swaps it for a concrete drawn seed in both the API prompt and the copy of the workflow that gets written into image metadata - which is why dropping that saved image back onto the canvas brings the real seed with it, not a -1. A prompt queued straight through the API with -1 gets the same treatment server-side, logged to the console.

    Random seeds are drawn below 2⁵³ on purpose. JavaScript numbers can't represent anything larger exactly, and a seed that drifts by one on the round trip through the frontend is a seed you can't reproduce.

    The seed itself is declared as an INT behind the SEED name, so it wires anywhere an integer goes. Node-side, control_after_generate is switched off - the buttons replace it, so you can't accidentally leave two competing mechanisms running.

    Wiring it

    Convert the seed widget on your KSampler (or whatever sampler you use) into an input, then wire SEED in. Same for the seed key in a save node's filename template, or a second sampler you want locked to the same value. One seed, several consumers - the standard argument for value nodes over typing the same number four times.

    The cache behaves sensibly: IS_CHANGED returns the seed itself when it's a real number, so a fixed seed lets the graph below it stay cached. Only -1 marks the node dirty every run, which is exactly when you need it to.

    Install

    Manager: search ComfyUI-BCNodes, install, restart. Manual:

    cd ComfyUI/custom_nodes
    git clone https://github.com/0xBeycan/ComfyUI-BCNodes
    

    No extra pip step - the pack's only dependencies (postfx, caption-audit) belong to two other nodes. The pack's nodes are all registered with BC_ prefixes so you can run it next to rgthree, which has a seed node of its own doing a similar job. Type BCNodes in the node library to find this one under BCNodes/logic.

    Where people get burned

    A fixed seed doesn't mean a reproducible image. It means the noise seed is fixed. Change the sampler, steps, CFG, model or LoRA strength and you get a different image from the same seed - same as any other seed node in ComfyUI. If you're trying to nail down which of those moved, change one at a time.

    -1 is a toggle, not a roll. Pressing 🎲 Randomize Each Time doesn't randomize once; it puts the node in random-every-run mode until you press one of the other two buttons. If you walk away and queue twenty times, you get twenty unrelated seeds, and the ♻️ button only ever remembers the last one.

    Old workflows that were saved with -1 mid-run. If you load a graph whose widgets hold -1 and run it through the API rather than the UI, the server draws a seed, uses it, logs it, and writes it into the metadata - but the copy of the workflow in the image will have the drawn value, not the -1 the widget showed you. That's the behavior you want, and it's still worth knowing when you go diff two workflow files and find they disagree.

    CategoryBCNodes/logic

    Inputs (1)

    NameTypeDefaultDescription
    seedINT0-1–18446744073709550000—

    Outputs (1)

    NameTypeDescription
    SEEDINT—