Seed List
Fifty variants, fifty seeds, one seed in your metadata
- seed
- seed_list
Generate a batch of variations with one fixed seed and you'll watch them all come out weirdly similar - same face, same pose, same lighting, just different prompts pasted on. Seed List is the fix: it takes one base seed and derives a different, deterministic seed per element of a loop, so a batch of fifty prompts gives you fifty genuinely varied images while still being reproducible.
The trick is that it never draws a random number itself. It takes a seed input - the README's suggested source is Seed (rgthree), which resolves at run time and gets written into your PNG's metadata - and mixes it with each element's title: random.Random(f"{base}:{title}"). Same base, same title, same result, every time. Because the derivation is a pure function of the base, the single base seed recorded in your image metadata is enough to recompute every variant later. Backend-generated random values don't end up in metadata, which is exactly why this node demands a base seed instead of rolling its own.
What you set
- title - the ingredient for each element. The canonical wiring is Unpack Text's
titleoutput; feeding a Loop Texts output straight in also works, since it extracts the hidden title the same way. If the title was stripped somewhere (a non-StringKit node in between), the prompt text becomes the ingredient and your seeds silently change. - mode - how the seed is made:
seed+title(default) - mix base with the element's title. Order-independent: flip a toggle or reorder slots and each titled element keeps its old seed. Edit the title and that element's seed changes (typo fixes included).seed+loop index- mix base with the element's position. Simple, but reorder anything and every seed shifts.only seed- pass the base through untouched. There when you want one seed for the whole batch.
- seed - the base. In the 0–1125899906842624 range, matching rgthree's Seed node.
Duplicate titles get a numeric suffix from the second occurrence on (smile, smile#2, …), so two identical titles don't collide, and the first one keeps its seed so existing results don't wobble.
Wiring it up
The seed output is an INT list - the sampler consumes one per loop element. There's also a seed_list STRING output, a preview block you can shove into a ShowText node to eyeball the mapping of index/title/seed. Standard layout:
Seed (rgthree) ─┬─→ your normal sampler path (so base lands in metadata)
└─→ Seed List.seed
Unpack Text ─title─→ Seed List.title
└prompt─→ CLIP encode
Seed List ─seed (INT list)─→ sampler seed
└seed_list─→ ShowText
One trap: if you're on KSampler (Efficient), seed is a widget, not a socket, so no connection point is visible. Drag the INT output over the top of the node and the socket appears; set set_seed_cfg_sampler to from node to ctx so the seed actually flows downstream. And while you're at it, set your base seed's "widget control mode" to Before so the number in the box is the one that ran - the classic control_after_generate trap bites here too, except now it silently scrambles fifty seeds at once.
Install
Part of ComfyUI-StringKit (MIT, zero dependencies, no models). ComfyUI Manager, search ComfyUI-StringKit, or:
cd ComfyUI/custom_nodes
git clone https://github.com/luku756/ComfyUI-StringKit
Full restart afterward. Under the StringKit category. If you batch-generate at all, this is the node that keeps your batches from being fifty copies of one image - and your metadata honest about it.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| title | STRING | — | |
| mode | COMBO | seed+title | 3 options: seed+title, seed+loop index, only seed |
| seed | INT | 00–1125899906842624 | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| seed | INT | — |
| seed_list | STRING | — |