Nodes/ComfyUI-SplatKit/Save Upscaled Frames (Streaming)
ComfyUI Node

Save Upscaled Frames (Streaming)

The RAM fix for upscaling an 81-frame 8K batch

By mickmumpitz·Created about a month ago·Updated a day ago· 17
Save Upscaled Frames (Streaming)
  • images
  • meta_batch
  • images_dir
canonical_dir
out_suffix_upscaled
out_dir
filename_pattern{i:05d}.png
source_names_dir
order_names
passthrough_json
job

Push an 81-frame 8192×4096 batch through an upscaler as one video tensor and your RAM is gone before the first frame comes back - the pack's own docstring does the math: ~32 GB per node copy of the float32 batch, and the CAS pre-sharpen alone stacks it five times for a 163 GB MemoryError. Save Upscaled Frames (Streaming) is the fix: it rides a VHS Meta Batch Manager loop, receives one (or a few) frames per iteration, and accumulates them onto disk instead of ever holding the whole batch. RAM stays flat, and the loop is the only thing in flight.

Two design choices make it safe where Save Upscaled Dataset can't go. It writes to a separate folder (default <canonical>_upscaled) and never renames or touches the pristine originals - nothing to lose if it crashes. And it's idempotent: the first iteration of each run clears the target folder, so a re-run overwrites cleanly rather than appending a second copy. Output is images_dir, and it finalises on the last chunk.

Wiring and the inputs that matter

images is the required input (the upscaled frame(s) for this chunk). Then it gets clever:

  • job - wire Load Dataset Images (Ordered) → job here and this node needs nothing else configured: the target folder, the exact arrival order and the passthrough list all travel down that one link. Explicit settings still win if you set them.
  • canonical_dir + out_suffix - the separate-folder default; or out_dir to set it explicitly.
  • source_names_dir - when set, each upscaled frame is written under the original filename (lexical, matching the VHS loader) instead of the sequential filename_pattern - required for an in-place COLMAP upscale so sparse/0/images.bin keeps matching. Wire Prepare Dataset Upscale → load_dir here.
  • order_names - JSON list of filenames in exact arrival order; wire the loader's order_names whenever the stream is camera-major (a lexical listing would map frames to the wrong files). Takes precedence over source_names_dir.
  • passthrough_json - names listed here are not written from the upscaled tensor; their untouched original is copied to the output at native resolution. Frame 00000 is the real panorama with its own larger COLMAP camera, so it's passed through the model only for temporal context and the real pixels are kept.
  • meta_batch - wire the same Meta Batch Manager that drives the loader.

Install & gotchas

cd ComfyUI/custom_nodes
git clone https://github.com/mickmumpitz/ComfyUI-SplatKit
python_embeded\python.exe -m pip install -r ComfyUI-SplatKit/requirements.txt

Restart. The one thing that trips everyone: VideoHelperSuite only recognises VHS_VideoCombine as the node that keeps a meta-batch loop requeueing, so you need a throwaway VHS_VideoCombine (save_output=false, fed the cheap low-res frames) sitting on the Batch Manager just to advance the loop - this node rides along and finalises on the last chunk. And set frames_per_batch to a divisor of the per-view length so no chunk straddles a view boundary.

CategorySplatKit

Inputs (10)

NameTypeDefaultDescription
imagesIMAGEThe upscaled frame(s) for THIS chunk. Under a Meta Batch Manager this is one (or a few) frames per iteration.
canonical_diroptSTRINGWire Resolve Dataset Images -> canonical_dir. Frames are written to <canonical_dir><out_suffix> (a NEW folder next to the originals). Ignored if out_dir is set.
out_suffixoptSTRING_upscaledSuffix for the derived output folder when out_dir is blank.
out_diroptSTRINGExplicit output folder. Overrides canonical_dir+out_suffix. Absolute, or relative to ComfyUI/output.
filename_patternoptSTRING{i:05d}.pngPython format for each frame's filename; {i} is the running 0-based frame index. Sequential naming keeps temporal order. Ignored when source_names_dir is set.
source_names_diroptSTRINGOptional folder of the ORIGINAL images. When set, each upscaled frame is written under the original filename (lexical order, matching the VHS loader) instead of filename_pattern -- required for an in-place COLMAP dataset upscale so sparse/0/images.bin keeps matching. Wire Prepare Dataset Upscale -> load_dir here.
order_namesoptSTRINGJSON list of the filenames in the EXACT order the frames arrive. Wire Load Dataset Images (Ordered) -> order_names here whenever the stream is CAMERA-MAJOR -- a lexical source_names_dir listing would map the frames to the wrong files. Takes precedence over source_names_dir.
passthrough_jsonoptSTRINGWire Load Dataset Images (Ordered) -> passthrough_json. Names listed there are NOT written from the upscaled tensor: their untouched ORIGINAL file is copied to the output instead, at its native resolution. Frame 00000 is the real panorama and has its own larger COLMAP camera, so it is passed through the model only to give it temporal context -- the generated version is discarded and the real pixels are kept.
joboptSTRINGWire Load Dataset Images (Ordered) -> job and this node needs NOTHING else configured: the target folder, the exact arrival order and the passthrough list all travel down that one link. It fills in out_dir / order_names / passthrough_json, and any of those you set explicitly still wins.
meta_batchoptVHS_BatchManagerWire the SAME Meta Batch Manager that drives the loader here so this node accumulates across iterations and finalises on the last chunk. Leave unconnected for a single full-batch save.

Outputs (1)

NameTypeDescription
images_dirSTRING