Save Image with Custom Metadata (Dynamic)
Twenty label slots for real parameter sweeps
- images
- meta_value_0
- meta_value_1
- meta_value_2
- meta_value_3
- meta_value_4
- meta_value_5
- meta_value_6
- meta_value_7
- meta_value_8
- meta_value_9
- meta_value_10
- meta_value_11
- meta_value_12
- meta_value_13
- meta_value_14
- meta_value_15
- meta_value_16
- meta_value_17
- meta_value_18
- meta_value_19
Twenty numbered pairs instead of ten. That's the entire difference between this node and its sibling MetaSaver - same mechanism, same install, same everything, just double the label slots. If ten fields felt cramped the first time you tried to log seed, both prompts, CFG, sampler name, model hash, and a couple of LoRA weights all on one image, this is the version you actually want.
What it's doing
ComfyUI already embeds the entire workflow graph into every PNG it saves - drag the file back onto the canvas and the whole pipeline reconstructs, which is the reason "workflow included" became a community expectation rather than a nice-to-have. MetaSaverDynamic runs alongside that, not instead of it. It gives you named, human-readable fields you choose yourself, for the handful of values you actually want to glance at without reopening the graph - a seed to reproduce a happy accident, a model name to compare two checkpoints, notes on a batch run. It's a label, not a replacement for the graph.
The mechanism
Same as the standard node, just scaled up: meta_name_0 through meta_name_19, each paired with a meta_value_N that accepts absolutely anything (wildcard-typed), because the field is meant to take whatever you wire into it - a sampler's seed int, a text encode's prompt string, a float widget, even a raw string constant you type by hand. Leave any pair blank and it's dropped, silently, no errors, no half-written entries. Everything you do fill in lands twice: as one structured JSON object under a custom_metadata key (grab it all at once with a script) and as individual flat fields (grab just one with exiftool).
Inputs and outputs that matter
images(IMAGE, required) - your generated batch, same as any Save Image node.filename_prefix(STRING, defaultComfyUI) - the filename stem.meta_name_0…meta_name_19/meta_value_0…meta_value_19- twenty optional label/value pairs. Fill in three, fill in all twenty, doesn't matter - empty ones cost nothing.
No output socket. This is a terminal save node, same as the stock one - nothing downstream to wire it into.
Installing it
Through ComfyUI Manager: search "MetaSaver", install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/SorenWeile/ComfyUI_MetaSaver
then restart ComfyUI. The image nodes in this pack don't pull in anything beyond Pillow, which ComfyUI already depends on - no model weights, no extra Python packages, no first-run download to wait on.
Where it trips people up
The one detail specific to this variant, straight from the author's own troubleshooting notes: when you go to read the fields back individually (not the JSON blob), the Dynamic node's tags come out prefixed with meta_ - so a field you named seed shows up as meta_seed in an exiftool dump, not bare seed. If you wrote a script that expects the exact name you typed, that prefix will bite you; parse the custom_metadata JSON blob instead if you want the literal names back.
Beyond that, the usual gremlin is the same as the standard node: a name typed with no value wired in (or a value wired in with no name typed) just gets silently skipped, so if a field goes missing, check both halves of that pair, not just one. And twenty fields is a lot of canvas real estate - if you're not actually using more than ten, the plain MetaSaver node is the same thing with less scrolling.
Inputs (42)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| filename_prefix | STRING | ComfyUI | — |
| meta_name_0opt | STRING | — | |
| meta_value_0opt | * | — | |
| meta_name_1opt | STRING | — | |
| meta_value_1opt | * | — | |
| meta_name_2opt | STRING | — | |
| meta_value_2opt | * | — | |
| meta_name_3opt | STRING | — | |
| meta_value_3opt | * | — | |
| meta_name_4opt | STRING | — | |
| meta_value_4opt | * | — | |
| meta_name_5opt | STRING | — | |
| meta_value_5opt | * | — | |
| meta_name_6opt | STRING | — | |
| meta_value_6opt | * | — | |
| meta_name_7opt | STRING | — | |
| meta_value_7opt | * | — | |
| meta_name_8opt | STRING | — | |
| meta_value_8opt | * | — | |
| meta_name_9opt | STRING | — | |
| meta_value_9opt | * | — | |
| meta_name_10opt | STRING | — | |
| meta_value_10opt | * | — | |
| meta_name_11opt | STRING | — | |
| meta_value_11opt | * | — | |
| meta_name_12opt | STRING | — | |
| meta_value_12opt | * | — | |
| meta_name_13opt | STRING | — | |
| meta_value_13opt | * | — | |
| meta_name_14opt | STRING | — | |
| meta_value_14opt | * | — | |
| meta_name_15opt | STRING | — | |
| meta_value_15opt | * | — | |
| meta_name_16opt | STRING | — | |
| meta_value_16opt | * | — | |
| meta_name_17opt | STRING | — | |
| meta_value_17opt | * | — | |
| meta_name_18opt | STRING | — | |
| meta_value_18opt | * | — | |
| meta_name_19opt | STRING | — | |
| meta_value_19opt | * | — |
Outputs (0)
No outputs