KSampler + Metadata Outputs
A KSampler That Remembers What It Did
- model
- positive
- negative
- latent_image
- LATENT
- seed
- steps
- cfg
- sampler_name
- scheduler
- denoise
- width
- height
Standard KSampler is great at sampling and terrible at telling you what it did. The values you set live in widgets - they're not exposed as outputs - so when you save metadata, you're either typing them by hand or hoping your saver node guessed right. Change a widget after you wire something up and your recorded settings silently drift from what actually ran. This node fixes that by doing the sampling and then handing you the proof.
It's a near-drop-in swap for the core KSampler, and "near" is doing a lot of reassuring work: underneath, it calls ComfyUI's own common_ksampler - the exact function the built-in node uses. Same sampler list (all 44), same 9 schedulers, same conditioning, same latent in and out. You're not getting a new sampling engine, you're getting a KSampler with a receipt.
What you wire
All the inputs are the standard KSampler set - model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise. Nothing exotic.
The outputs are where it earns its keep. LATENT continues on to VAE Decode exactly as before. Then:
seed,steps,cfg,denoise- the actual values used, as INT/FLOAT outputs.sampler_name,scheduler- the names as strings.width,height- inferred from the input latent, so they reflect the real denoised resolution (it accounts for each model family's latent scaling factor, not just the naive ×8).
Wire these into Image Saver Metadata - seed → seed_value, steps → steps, cfg → cfg, and so on down the README's mapping - and the saved metadata is guaranteed to match what the sampler actually consumed. That's the whole point: the embedded workflow in the PNG stays evidence of the setup, but the explicit values can't drift.
The one thing it can't do
It can't recover your prompt strings. KSampler receives already-encoded CONDITIONING, not text, so no node downstream of it can reconstruct what you typed. The fix is to pass the positive and negative prompt strings separately - once to CLIP Text Encode as usual, and once to Image Saver Metadata's positive / negative inputs. Slightly redundant, but that redundancy is what makes the metadata complete.
Installation
Search Civitai Metadata Bridge in ComfyUI-Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/Mikaelosa/ComfyUI-Civitai-Metadata-Bridge
Then restart ComfyUI. The companion save node lives in alexopus/ComfyUI-Image-Saver; this pack adds no third-party Python dependencies of its own.
Gotchas
- Don't forget the prompts. If your saved metadata has no prompt, this node isn't broken - that's the CONDITIONING limitation above. Feed the strings to the saver directly.
modelnamesocket missing? The README recommends connecting Civitai Model Selector'spathto Load Checkpoint'sckpt_nameand Image Saver Metadata'smodelname, so the saver computes the checkpoint hash itself instead of trusting Civitai to infer the model. Ifmodelnameappears as a text widget, right-click it and convert it to an input. Same trick applies toadditional_hashesif it shows up as a box.
If you save locally with SaveImage and never inspect metadata, this node is unnecessary overhead - but if you post to Civitai and care about your generations being attributed correctly, it's the rare "metadata plumbing" node that's actually pleasant to use. It just works, and it removes a whole class of "wait, that's not the seed I used" moments.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | The model used for denoising the input latent. | |
| seed | INT | 00–18446744073709550000 | The random seed used for creating the noise. |
| steps | INT | 201–10000 | The number of denoising steps. |
| cfg | FLOAT | 8.00–100 | Classifier-Free Guidance scale. |
| sampler_name | COMBO | The sampler algorithm to use. | |
| scheduler | COMBO | The scheduler used for sampling. | |
| positive | CONDITIONING | The positive conditioning. | |
| negative | CONDITIONING | The negative conditioning. | |
| latent_image | LATENT | The latent image to denoise. | |
| denoise | FLOAT | 1.000–1 | Amount of denoising applied. |
Outputs (9)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | The denoised latent. |
| seed | INT | The seed used for sampling. |
| steps | INT | The number of steps used for sampling. |
| cfg | FLOAT | The CFG value used for sampling. |
| sampler_name | STRING | The sampler name used for sampling. |
| scheduler | STRING | The scheduler name used for sampling. |
| denoise | FLOAT | The denoise value used for sampling. |
| width | INT | The inferred image width from the latent. |
| height | INT | The inferred image height from the latent. |