Caption Export
Write your captions to .txt files next to the source images
- captions
- image_paths
- status
This is where the whole pipeline actually pays off. Load a folder of images, caption them, and none of it matters for training until the captions land as text files sitting next to their images - the image.png + image.txt pair that every LoRA trainer expects. Caption Export is that last step, and it's marked as an output node in ComfyUI, meaning it's a proper endpoint your graph can terminate on.
Captioning quality is one of the most-repeated findings in LoRA training discussions - right up there with dataset curation itself - so getting this last mile right, files landing in the right place with the right names, matters as much as what the captioning model actually wrote.
How it works
It takes the captions list from Caption Generator (or Florence-2 Node) alongside the image_paths list they were generated from, and writes one text file per image, matched by position between the two lists. Get the order or length of those two lists out of sync upstream and captions will land on the wrong images - worth a sanity check with Debug Node before this step if you've been reordering or filtering lists anywhere in the graph.
The inputs and outputs that matter
captions/image_paths(LIST, both required) - parallel lists, matched by position.file_extension(optional, default"txt") - the extension for the written caption files. Kohya-style trainers expect.txt; leave it unless your specific trainer wants something else.keep_extension(BOOLEAN, defaultfalse) - controls whether the source image's own extension stays in the output filename. Off meansphoto.jpggets a caption file namedphoto.txt; on presumably keeps the image extension in there too (photo.jpg.txt). The default (off) is the one every standard trainer expects.overwrite_existing(BOOLEAN, defaultfalse) - off by default, meaning a caption file that already exists at the target path won't be touched. That's a deliberate safety net for resuming an interrupted captioning run without clobbering work you already have, but it also means a genuine re-run with fresh captions silently does nothing until you flip this on.allow_empty_files(BOOLEAN, defaultfalse) - whether to still write a file when a caption came back blank. Off by default, so an image whose caption generation failed or returned nothing simply won't get a file at all, which can leave silent gaps in a dataset that expects every image to have a matching caption.
Output is status (STRING) - a summary of what got written, and since this is the output node, it's the last thing the graph reports.
Installing it
Through ComfyUI Manager: search ComfyUI-Transformers-Pipeline, install, restart. By hand:
cd ComfyUI/custom_nodes
git clone https://github.com/mediocreatmybest/ComfyUI-Transformers-Pipeline
then restart. No downloads - this node just writes text files to disk.
Common issues & troubleshooting
Re-ran the workflow and nothing changed on disk. Check overwrite_existing - it defaults to off specifically so repeat runs don't clobber existing caption files. Flip it on for a genuine re-caption pass.
Some images are missing a caption file entirely. Either that image's caption came back empty and allow_empty_files is off (the default), or the captions/image_paths lists didn't line up one-to-one going into this node. Check both before assuming the model failed silently.
Captions landed on the wrong images. This means captions and image_paths got out of order somewhere upstream - most likely a filtering or reordering step between Caption Generator and here. Insert a Debug Node on both lists just before this node to confirm they still match before trusting the output.
Trainer doesn't pick up the caption files. Double-check file_extension matches what your trainer expects, and that keep_extension is set the way your trainer's naming convention wants - most kohya-style setups want the default (off), producing image.txt next to image.png.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| captions | LIST | — | |
| image_paths | LIST | — | |
| file_extensionopt | STRING | txt | — |
| keep_extensionopt | BOOLEAN | false | — |
| overwrite_existingopt | BOOLEAN | false | — |
| allow_empty_filesopt | BOOLEAN | false | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| status | STRING | — |