Nodes/ComfyUI-BCNodes/Save Image With Caption
ComfyUI Node

Save Image With Caption

Building a LoRA Dataset Out of Your Outputs

By 0xBeycan·Created about a month ago·Updated 13 days ago· 2
Save Image With Caption
  • images
  • filename
◄filename_prefixComfyUI►
◄output_folderoutput►
◄caption_file_extension.txt►
◄caption—►

A LoRA training set isn't images. It's image/caption pairs that share a basename - 0001.png next to 0001.txt, cat_on_sofa.jpg next to cat_on_sofa.txt - because that's how every trainer walks the folder: it looks for a same-name text file and reads the caption from there. Kohya requires .txt; ai-toolkit and OneTrainer follow the same sidecar convention.

So building a dataset out of ComfyUI normally means saving a batch, then captioning it with JoyCaption or Florence, then matching the filenames up by hand and hoping nothing shifted. This node skips the matching step: give it images and a caption and it writes the pair.

What it does

Each image goes out as a PNG with ComfyUI's standard naming - prefix_00001_.png - and, when caption is connected, the caption lands next to it as prefix_00001_.txt. Same stem, guaranteed. That's the entire feature, and it's the reason to install it: no post-processing script, no off-by-one between your images and your caption list.

The counter is derived from the files already in the folder and never overwrites: a name whose image or caption file exists is passed over and the next number is used. Queue it twice and you get two sets, not one overwritten set. That's exactly the behaviour you want when you're iterating on a dataset over an evening.

Prompt and workflow are embedded in the PNG metadata as usual, unless you run ComfyUI with --disable-metadata. Nothing is drawn under the node, so it doesn't eat canvas space.

The inputs

  • images - the batch.
  • filename_prefix - default ComfyUI. It takes the same grammar as ComfyUI's own save node: %date:yyyy-MM-dd%, %Node.widget% filled in by the frontend at queue time, %year% through %second%, %width%, %height%, %batch_num% (the image's index in the batch), and sub/ folders. my_dataset/%date:yyyy-MM-dd%/img is a legal prefix, and the folders get created.
  • output_folder - default output. output is ComfyUI's output folder; output/my_dataset or plain my_dataset is a folder inside it; an absolute path is any folder on the machine, created if missing. A relative path that tries to climb out of the output folder is refused.
  • caption (optional input) - the string saved beside each image. Not connected: images only, no sidecars.
  • caption_file_extension (optional) - default .txt. Also accepts .caption, .json, .yaml, .yml, .md, .csv, .tsv, .xml, .log, .ini, .toml. Anything else is an error rather than a file with a weird name.

Output: filename, the name of the last image saved. It's an output node, so the graph executes it.

Where it fits

The clean pattern is a captioner feeding this node. Wire a vision model's caption output - JoyCaption is still the community favourite for training captions - into caption, and you're generating a captioned dataset directly. If you're captioning by hand instead, keep %batch_num% in the prefix so you can tell which generation a row came from when you go back to fix it.

One caption per image, note: the caption input is a single STRING for the batch. If you want different captions per image, you batch size 1 or you do a second pass. It's a small node, deliberately - the pack's bigger BC_SaveImage is the one with the name grammar, formats and job data, and this is the dataset-shaped subset.

Install

Manager, search ComfyUI-BCNodes, or:

cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-BCNodes
pip install -r ComfyUI-BCNodes/requirements.txt

Restart and search BCNodes in the node library. The requirements file installs opencv-python, postfx and caption-audit, none of which this node needs (caption-audit is a separate dataset-checking tool, not a captioner). Delete a leftover ComfyUI-AutoBypass folder from the pack's old name.

Gotchas

The overwrite protection is the feature and also the surprise: if you save into a folder full of ComfyUI_00001_.png from an earlier session, your new run starts at 00002 (or wherever the counter finds) rather than restarting. That's correct, and it means a re-run never clobbers yesterday's dataset - but it also means you can't easily "redo" a folder without clearing it or changing the prefix.

Second: .txt is the safe extension across trainers. .caption is accepted by some tools, not all; kohya warns on images with no caption file and requires the .txt name. If you don't know your trainer's preference, leave it alone.

Third: writing into an absolute path outside ComfyUI/output/ works, which is great for a training folder on another drive, and terrible for a workflow you share - the recipient's path won't exist and will be silently created on their disk. Keep dataset paths local to your own copies.

CategoryBCNodes/image

Inputs (5)

NameTypeDefaultDescription
imagesIMAGEThe images to save, as PNG.
filename_prefixSTRINGComfyUIThe file name before the counter (prefix_00001_.png). May hold %date:yyyy-MM-dd% or %Empty Latent Image.width% for values from nodes, %year% %month% %day% %hour% %minute% %second% %width% %height%, %batch_num% (the image's index in the batch), and `sub/` folders.
output_folderSTRINGoutputWhere to save: `output` is ComfyUI's output folder; `output/my_dataset` or `my_dataset` a folder inside it; an absolute path any folder (created when missing).
caption_file_extensionoptSTRING.txtThe caption file's extension, a plain-text format: .txt, .caption, .json, .yaml, .yml, .md, .csv, .tsv, .xml, .log, .ini, .toml.
captionoptSTRINGSaved next to each image under the image's name. Not connected: images only.

Outputs (1)

NameTypeDescription
filenameSTRINGThe file name of the last image saved.