Nodes/ComfyUI-Loop/♾️ Save Any
ComfyUI Node

♾️ Save Any

One node that saves images, masks, latents, audio, and text

By Hullabalo·Created 2 years ago·Updated 8 months ago· 14
♾️ Save Any
  • input
  • mask
    path/path/to/file.ext
    save_stepsfalse
    save_metadatafalse
    previewtrue

    Every loop needs a write side, and in ComfyUI-Loop that's Save Any (SaveAny). It takes any of the pack's supported inputs - image, mask, latent, audio, text - and writes it to a file you point at. On its own that sounds like the most boring node imaginable. In context, it's the thing that makes the whole "loop" idea real: Loop Any loads a file, your pipeline improves it, Save Any overwrites that same file, and the next run starts from the improvement instead of from scratch. The README's framing is exactly right - this is a "save by overwriting" node built for iterative inpainting.

    How it works

    Save Any pattern-matches the input tensor, the same way its partner Loop Any does:

    • 4D image tensor → .png (and if you pass a mask input, it's written into the PNG's alpha channel)
    • 3D tensor (a mask) → .png
    • a latent dict → .latent
    • a {waveform, sample_rate} dict → .flac
    • str / int / float.txt

    The path input is a full file path with extension - that's how it knows the format, and it's why Loop Any hands you a ready-made path output to feed straight in. If the input type doesn't match the extension you typed, the format wins and the file just gets whatever extension the type implies.

    The inputs that matter

    • input - anything the pack understands.
    • path - full path of the saved file (default /path/to/file.ext). Set this yourself, or wire it from Loop Any's path output so the loop closes.
    • save_steps - saves a timestamped copy next to the main file on every run. This is the one I'd switch on first: in a loop that overwrites on each pass, it's your only history. Turn it on, and you can scroll through the progression afterward instead of wondering what pass three looked like.
    • save_metadata - embeds prompt/graph metadata into formats that support it (PNG). Nice-to-have for sharing; leave off if you're just iterating.
    • preview - shows the image preview in the node. Disable to shave a hair off execution and de-clutter big graphs.
    • mask (optional) - the inpainting linchpin: with an image input, this mask gets saved as the PNG alpha channel. Loop Any with loop_mask on reads it back, so a single file carries both the inpainted region and its mask.

    It's a terminal node - no outputs, just the on-node preview.

    Why you'd reach for it

    Because the default SaveImage node fights you on loops. It auto-numbers every file, so re-runs pile up and "load the previous result" has no fixed target. Save Any gives you a deterministic file: same path, overwritten every run. That determinism is what Loop Any needs to load the last iteration back. The mask-as-alpha trick is the real gem though - it's the cleanest way to keep an inpainting mask in lockstep with the image through a feedback loop, no separate mask file to drift out of sync.

    Install and gotchas

    No dependencies, no models - the whole pack installs the same way:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Hullabalo/ComfyUI-Loop
    

    Restart, done. Manager users: search "Loop" for ComfyUI-Loop.

    • It overwrites silently. That's the design, but the README's warning is mandatory reading: always work on a copy of your source file. With save_steps off, there's no undo.
    • No batch or list support - single files only, pack-wide limitation.
    • Not Nodes 2.0 compatible. Tested through ComfyUI 0.8.2 on the legacy frontend; the new Vue canvas breaks it, and the author has said it likely never gets ported.
    CategoryLOOP

    Inputs (6)

    NameTypeDefaultDescription
    input*
    pathSTRING/path/to/file.extFull path of the saved file.
    save_stepsBOOLEANfalseSave a copy next to the saved image with a timestamp as suffix.
    save_metadataBOOLEANfalseSave metadatas for compatible file formats.
    previewBOOLEANtrueDisplay the preview in node.
    maskoptMASK

    Outputs (0)

    No outputs