Nodes/BrainDead Nodes/BD Save File
ComfyUI Node

BD Save File

The save node that speaks every type the pack uses

By BizaNator·Created 9 months ago·Updated 10 days ago· 15
BD Save File
  • data
  • alpha_mask
  • data
  • file_path
  • status
◄filenamesaved_file►
◄skip_if_existstrue►
◄name_prefix►
◄extension►
◄context_id►
◄suffix►
◄custom_vars►
◄save_alpha_separatelyfalse►
◄invert_alphafalse►
◄save_workflow_sidecartrue►
◄embed_workflowfalse►

ComfyUI's built-in SaveImage only speaks IMAGE. BD Save File speaks everything the BrainDead pack actually produces - IMAGE, MASK, AUDIO, LATENT, STRING, TRIMESH - and it's the node that ties the pack's file discipline together. Whether you're caching a mesh, dumping a PBR map, or parking a prompt string next to your renders, one node does it, and it slots into the BD Save Context system so filenames stop being a mess.

What it is

A universal save node: wire in data of almost any type, it picks the right native format and writes it to disk, then hands you back the file_path as a STRING (and passes the data through unchanged). It's the same "save" node the README builds the whole caching/iteration story on.

How it works

The type determines the format - IMAGE → PNG, MASK → PNG, LATENT → safetensors, AUDIO → WAV, STRING → TXT, TRIMESH → PLY. You don't pick the format; it detects it. Where it gets interesting is context integration:

  • With a BD Save Context registered and context_id matched, the path resolves from the context's template plus this node's suffix / filename / name_prefix / custom_vars. One context, N save nodes, all consistent.
  • Without a context (or with zero/multiple contexts registered and an empty context_id), it falls back to legacy behavior: filename + optional name_prefix into the output folder.

The inputs that matter

  • data - the any-type input. This is the whole reason to use it.
  • filename - with a context it overrides %name%/%filename% in the template; without one it's the literal filename.
  • context_id + suffix - _albedo, _shoes, _head. The README suggests wiring suffix from BD For Each Run.label or an iterator's tag for per-iteration filenames.
  • skip_if_exists (default true) - don't clobber existing files; report the existing path instead.
  • extension - override the auto-detected one, for the rare case you want a different container.
  • alpha_mask / invert_alpha / save_alpha_separately - bake a mask into the saved file's alpha channel (white = opaque), and optionally write a sidecar _alpha.png. Conventions matter here: white = opaque, black = transparent, and ComfyUI's LoadImage mask output is the inverse of the subject - flip invert_alpha if your mask has white=background.

Outputs: data (passthrough, so you can chain), file_path (absolute path as a STRING - wire it into anything that wants a path), and status.

Where it shines

The README's example says it best: [BD Prompt Iterator] → [BD Qwen Character Edit] → [BD Save File] with name_prefix: MyCharacter - iterate through a character sheet and land clean, sequentially-named files. And in the PBR pipeline, five maps out of BD Derive PBR Maps all funnel into one context-aware save. If you've ever hunted through output/ for the file that SaveImage_0001 actually wrote, you'll appreciate getting a real path back.

Installing it

ComfyUI Manager: search "BrainDead" → install. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/BizaNator/ComfyUI-BrainDead
cd ComfyUI-BrainDead
pip install -r requirements.txt

Restart, find it under 🧠BrainDead/Cache. No extra dependencies beyond what ComfyUI already has - trimesh (for TRIMESH saves) ships with modern ComfyUI, and the audio/latent paths use native ComfyUI formats.

Category🧠BrainDead/Cache

Inputs (13)

NameTypeDefaultDescription
data*—
filenameSTRINGsaved_fileWith context: overrides %name% / %filename% in template if set (non-'saved_file'). Without context: legacy filename.
skip_if_existsBOOLEANtrue—
name_prefixoptSTRINGWith context: exposed as %name_prefix% in template. Without context: legacy prefix prepended to filename.
extensionoptSTRINGOverride auto-detected extension.
context_idoptSTRINGIf set AND a BD_SaveContext with this id is registered: path is resolved from the context's template + this node's suffix/filename/name_prefix. If empty AND exactly ONE context is registered, that one is auto-used. If empty AND zero or multiple contexts: legacy filename-based behavior.
suffixoptSTRINGPer-save suffix appended after filename (e.g. '_albedo', '_shoes', '_head'). Wire from BD_ForEachRun.label or Iterator.tag for per-iteration filenames. With context: also exposed as %suffix% in the template. Without context: appended literally to filename — caller controls separator (convention: leading underscore).
custom_varsoptSTRINGPer-save extra variables, one per line as key=value. Layered ON TOP of the context's custom_vars (this node's keys override context for matching names). Examples: subfolder=textures materials=metal pass=normal These become %subfolder%, %materials%, %pass% in the template. Empty values resolve cleanly (// → /). Undefined vars stay as %var% literals so you spot typos.
save_alpha_separatelyoptBOOLEANfalseAlso write the alpha channel as a standalone greyscale PNG alongside the main file, named with the same suffix + '_alpha'. Source of the alpha pixels: • alpha_mask wired → uses the mask (after invert_alpha) • no mask wired, image has 4 channels (RGBA) → extracts the embedded A channel • no mask wired, image is RGB (3ch) → no alpha to extract; this output is skipped NOTE: the _alpha.png is a RAW greyscale representation — white pixel = opaque area, black pixel = transparent area. It is NOT a composited preview; open the main RGBA PNG in a viewer that supports transparency to see the actual cut-out.
alpha_maskoptMASKBake this mask into the saved file's alpha channel before writing. Convention: WHITE (1.0) = OPAQUE, BLACK (0.0) = TRANSPARENT. Face mask (white face, black background) → face is opaque, background is cut out. Background mask (white background, black face) → use invert_alpha=True. If you already have an RGBA image (4-channel), you do NOT need to wire alpha_mask — the embedded alpha is preserved automatically when saving. The upstream image tensor is NOT modified — transparency is baked only in the saved file. Accepts batched masks (B, H, W); single (H,W) or (1,H,W) applies to all frames.
invert_alphaoptBOOLEANfalseFlip the mask polarity before baking as alpha. Use when your mask has white=background / black=subject and you want the subject opaque.
save_workflow_sidecaroptBOOLEANtrueWrite a <filename>.json sidecar next to the saved image containing the workflow + prompt graph (same data ComfyUI's stock SaveImage embeds into the PNG itself). The image file is never touched — this only adds a companion .json. Set False to save with no metadata at all.
embed_workflowoptBOOLEANfalseAlso write the workflow + prompt into the PNG's own text chunks, exactly as ComfyUI's stock SaveImage does, so the image opens by drag-and-drop. OFF by default: embedding a large graph into every delivered product is waste, and the sidecar already carries the same data. Turn it on for the one image per run you want to reopen. PNG only -- JPEG cannot carry text chunks.

Outputs (3)

NameTypeDescription
data*—
file_pathSTRING—
statusSTRING—