Nodes/ComfyUI-Apt_Preset/IO_Save_Tensor
ComfyUI Node

IO_Save_Tensor

Bookmark the middle of a pipeline, not the end of it

By cardenluo·Created 2 years ago·Updated about 19 hours ago· 356
IO_Save_Tensor
  • data
  • bridge_path
◄fold_name►
◄unload_modelsfalse►
◄free_memorytrue►

Save Image is where a ComfyUI pipeline usually ends, which is annoying, because the interesting part is often in the middle. The latent after the first sampler. The mask you spent an hour dialing in. The upscaled pass you don't want to redo. IO_Save_Tensor writes any of those to disk as a tensor - no VAE round-trip, no re-encoding, no loss - and IO_Load_Tensor picks it up later, in this session or next week's.

How it works

You hand it data and it figures out what it's holding. The detection is mechanical and worth knowing, because it's the source of every surprise here: a video object (get_components()) is a video; a dict with samples is a latent; a dict with waveform is audio; a 4-D tensor whose last dimension is 1, 3 or 4 is an image; a 3-D tensor is a mask; anything else is dumped as JSON. Everything gets moved to CPU and written into a single .safetensors, with a JSON descriptor of the payload shape stuffed into the file's metadata under the key stage_payload.

The write is atomic - it saves to clip_00001_.safetensors.tmp and then renames - so an interrupted run doesn't leave you with a corrupt file that the loader will happily try to open.

Filenames are less clever. The prefix is hardcoded to clip, and the number comes from ComfyUI's standard save counter, which is why you'll find clip_00001_.safetensors, clip_00002_.safetensors and so on rather than anything describing the contents. To find a specific one later you read the number, not the name.

Inputs and outputs that matter

  • data - wildcard, and lazy. Anything tensor-ish will go in. Note the lazy flag: if data isn't available the node doesn't force the branch, which keeps it from dragging a dead branch into existence.
  • fold_name - the folder relative to output/Apt_brigeTensor/. The tooltip says so directly. Blank means the root of that folder. Paths are confined to it; anything that escapes is rejected.
  • unload_models - default off. Sets the same prompt-queue flag the ComfyUI menu has, applied at the end of the run. Leave it off unless you're genuinely done and want the weights out of VRAM.
  • free_memory - default on. Frees the cache at the end of the run. Useful when you're saving at the tail of a big graph and then walking away; mildly irritating when you save mid-graph and a later node was relying on the cache. Turn it off if a save in the middle of a graph makes the rest of the queue feel slow.

One output, bridge_path (STRING) - the actual file it wrote. It's not decoration: it's the confirmation the save happened, and it's what you'd print to the console or feed into a filename string. The node is registered as an output node, so it always executes even when nothing downstream consumes it, which is exactly what you want from a saver.

Install

Manager → search Apt_Preset, or:

cd ComfyUI/custom_nodes
git clone https://github.com/cardenluo/ComfyUI-Apt_Preset.git
cd ComfyUI-Apt_Preset && pip install -r requirements.txt

Windows: install-ComfyUI-Portable.bat (or the aki variant) in the pack root, then restart. Be a little patient with that install - this pack pulls OpenCV, scipy, matplotlib, soundfile, scenedetect and more, plus optional gguf / onnxruntime / transparent-background. The failure mode people actually report is the pack landing in custom_nodes and every node in it turning red with IMPORT FAILED in the console because one dependency didn't build. Re-run the requirements in the correct Python (the embedded one, on a portable install) before you go hunting for a bug in the node.

Three things that catch people out

The files are the pack's own format, and only IO_Load_Tensor reads them. IO_Save_Tensor always writes the stage_payload descriptor - core ComfyUI's Load Latent node expects a latent_tensor key and will not open them. It works in one direction only: IO_Load_Tensor does read core Save Latent files. If you want something the rest of the ecosystem can open, save an IMAGE instead of a latent and decode first.

Save the latent, not the image, when you plan to keep sampling. An image is decoded pixels - feeding it back means a VAE encode, which is lossy and slow. A saved latent goes straight back into a KSampler with the denoise you choose, and it's a fraction of the file size. Save the image only when a human or another node needs to look at it.

The type was guessed, not declared. A plain 2-D tensor lands in the JSON path and will not come back the way you expect, and the image check is strictly 1, 3 or 4 channels in the last dimension. If a save-and-load round trip is behaving oddly, check what you actually connected.

CategoryApt_Preset/IO_Port

Inputs (4)

NameTypeDefaultDescription
data*—
fold_nameSTRING文件夹路径在 output/Apt_brigeTensor/。保存文件以 clip 为固定前缀并自动递增命名。
unload_modelsBOOLEANfalse—
free_memoryBOOLEANtrue—

Outputs (1)

NameTypeDescription
bridge_pathSTRING—