⬡ Polyhedron Save
The output node that writes stills, video, audio and masks from one place
- image
- video
- audio
- mask
- path
- fps
The Polyhedron Save is the counterpart to this pack's Media Loader, and it does something most save nodes don't: it picks the writer from what you actually wire into it. Feed it a VIDEO and it writes a video; an IMAGE and it writes stills; an IMAGE plus audio and it muxes a clip; a MASK alone and it writes grayscale stills. media_kind is set to auto and infers all of that, so you don't swap nodes when a job changes shape - you rewire.
Two details make it genuinely useful. First, it embeds the workflow into whatever it writes (PNG text / MP4 metadata), so a file can be dragged back into ComfyUI to restore the graph. And second, when it writes a clip it drops a still frame beside it as a control image - because an .mp4 can't carry a workflow, but a PNG can. That little habit has saved more "which run was this again?" moments than any log.
The inputs
image- stills or frames.video- native VIDEO. This is where the loader pairing shines:video_audiofrom the Media Loader carries its trimmed companion track along, muxed into the written clip. A wiredaudioreplaces a video's audio.mask- alpha, kept for png/webp stills and alpha-capable presets (ProRes 4444).- Outputs:
path(full path of the written file) andfps(the rate it was written at) - thefpsoutput is handy for wiring Interpolate's output into a Save that builds video from an image batch.
Naming is a path, not a label
filename_prefix is the sleeper feature. Every / creates a subfolder under ComfyUI/output/, and tokens expand before the path is built: %date:yyyy-MM-dd%, %date:hhmmss%, %width%, %height%, even %KSampler.seed% (ComfyUI core expands other nodes' widgets). So %date:yyyy-MM-dd%/PH_%date:hhmmss% gives you one folder per day with files stamped to the second. The one trap: uppercase MM is the month, lowercase mm is the minute. A counter is always appended, so files never overwrite.
Video presets
video_preset spans delivery to archive: H.264 MP4 (small, universal, ComfyUI's own tested writer), H.265 MP4 (10-bit, grain-tuned so particles don't smear), ProRes 422 HQ and ProRes 4444 masters for editing, FFV1 lossless .mkv, WebM VP9, and animated WebP/GIF with a loop_count (0 = forever). The masters encode through bundled PyAV with a 16-bit intermediate, so the diffusion float precision reaches the encoder - less banding. quality is crf-style for the lossy presets (~17–20 is visually lossless); ProRes and FFV1 ignore it.
The levers
image_format picks png (lossless, embedded workflow) / webp / jpg (no alpha). frame_rate is only used when a video is built from an IMAGE batch - a wired VIDEO keeps its own rate. pingpong appends the reversed frames for a seamless boomerang loop; trim_to_audio cuts the longer of clip and audio so they end together; save_output off writes to a temp dir - preview only - which keeps output/ clean while you iterate.
Installing it
Part of the Polyhedron Suite pack:
cd ComfyUI/custom_nodes
git clone https://github.com/PolyhedronAI/ComfyUI-PolyhedronLoRAStack.git
# restart ComfyUI
or Manager, search "Polyhedron Suite". The masters need PyAV - recent ComfyUI builds ship it; if a preset errors, pip install "polyhedron-lora-stack[media]". The one thing that trips people: save_output defaults to writing real files, but if you're iterating a workflow you'll want it off, or you'll spend an afternoon emptying output/.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| filename_prefix | STRING | Polyhedron | Name under ComfyUI/output/. A '/' makes a subfolder. Optional tokens are expanded here: %date:yyyy-MM-dd% / %date:hhmmss%, %width%, %height% (illegal path characters are stripped so a token can never break the path). A counter keeps files unique. |
| media_kind | COMBO | auto | auto: infer from what's wired (VIDEO -> video; IMAGE+audio/fps -> video; IMAGE alone -> image; AUDIO alone -> audio). Or force 'image' / 'video'. |
| image_format | COMBO | png | Still format. png = lossless + embedded workflow (drag back to reload). webp = smaller / optional lossless. jpg = no alpha. |
| image_quality | INT | 1001–100 | webp / jpg quality (100 on webp = lossless). png ignores this (it uses lossless compression). |
| video_preset | COMBO | H.264 MP4 (delivery) | Delivery (small, universal) vs Master (edit/archive). H.264 uses ComfyUI's own tested writer; the masters use our bundled-PyAV encoder (10-bit via a 16-bit intermediate, intra keyframes). |
| quality | INT | 170–100 | crf-style quality for the lossy presets (lower = better/larger; ~17-20 is visually lossless). ProRes/FFV1 ignore it. |
| frame_rate | FLOAT | 24.000–240 | fps when a video is built from an IMAGE batch. A wired VIDEO keeps its own rate (this is ignored then). Convertible to an input -- wire Interpolate's fps output here so interpolated frames keep their true duration. |
| autoplay | BOOLEAN | false | In-node video preview: off = show first frame with play controls (a single-frame clip never jumps). On = play automatically (muted); loops only when the clip has >1 frame. |
| pingpong | BOOLEAN | false | Append the reversed frames (forward then back) for a seamless boomerang loop. |
| loop_count | INT | 00–1000 | GIF / animated-WebP loop count (0 = loop forever). |
| trim_to_audio | BOOLEAN | false | Match the clip length to the wired audio (trim the longer of the two) so video and sound end together. |
| save_metadata | BOOLEAN | true | Embed the workflow + prompt (PNG text / MP4 metadata) so the file can be dragged back into ComfyUI. |
| save_output | BOOLEAN | true | On: write to ComfyUI/output/. Off: temp dir (preview only, keeps output/ uncluttered while iterating). |
| imageopt | IMAGE | Still(s) or video frames [N,H,W,3|4]. | |
| videoopt | VIDEO | Native VIDEO (frames + audio + fps ride through). Takes the Media Loader's `video` or `video_audio` output alike -- a `video_audio` wire carries its trimmed companion track along and it is muxed into the written clip. | |
| audioopt | AUDIO | Optional audio to mux with image frames, or to replace a wired video's audio. | |
| maskopt | MASK | Optional alpha [N,H,W] (opaque->0). Wired ALONE, the mask itself is saved as grayscale stills. Kept for png/webp stills and alpha-capable video presets (ProRes 4444). |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| path | STRING | — |
| fps | FLOAT | — |