Save Media ⤵️
Save Media ⤵️ writes real video from inside the graph
- images
- audio
The default way ComfyUI "exports video" is a folder of PNGs and a prayer. Save Media ⤵️ is the fix: wire your IMAGE tensor (and an optional AUDIO tensor) into it, pick a format, and it writes an actual mp4, mov, webp, gif, or apng straight to ComfyUI's output folder. No API, no key, no separate ffmpeg binary - this is the encoder half of the tiny ComfyUI Unified Media Suite, and it pairs with Load Media ⤴️ to form a video round-trip you can run any image processing between.
How it works
Under the hood it's PyAV - Python bindings for ffmpeg's libav - which is why the pack's only dependency is the single av package. Your float image tensors get clipped and converted to uint8 via torchvision, encoded frame by frame, and muxed into the container you chose. Audio takes a slightly comedic path: it's written to a FLAC buffer with torchaudio, then read back in through a second PyAV container and muxed in. Whatever gets the job done.
Files land in ComfyUI's output folder with an auto-incrementing prefix, so Video + mp4 gives you Video00001.mp4, then Video00002.mp4, and so on. The node has no outputs - it's an output node, and it hands the result back to the UI so you can preview it.
The inputs that actually matter
- format - 14 popular choices: mp4, mov, webp, gif, apng, avi, mkv, mpeg, mjpeg, flac, mp3, aac, and more. mp4 with libx264 is the boring, correct default.
- video_codec / audio_codec - the dropdowns are populated from what your PyAV build actually supports.
libx264andaacdefaults work everywhere. - crf - the one number you'll actually fiddle with. 0 is lossless (8-bit), 51 is terrible, 23 is the default. Lower it when your video looks crunchy, raise it to shrink files.
- preset / tune - x264 dials:
veryslow/mediumfor quality,fastdecodeif a player chokes. Ignored when not applicable. - fps (default 24) - internally stored as a fraction with 8 decimal digits of precision, so 23.976 survives. If your video plays at the wrong speed, pipe the
fpsoutput from MediaLoad straight into this socket instead of typing it. - width / height (default 0) - 0 means "match the incoming frames"; set them to resize on save.
- save_metadata (default on) - the sleeper feature. It embeds the prompt + workflow JSON into the file. mp4 and mov tuck it into the Comment EXIF field (check with exiftool or VLC), and a saved flac can be dragged back into ComfyUI to auto-reload the whole workflow. Format support is patchy, but it works on the big ones.
It also auto-picks a transparent pixel format (rgba for png/apng, yuva420p for webp) when your frames carry an alpha channel, so transparency survives the trip.
Installing it
Same steps as every node in this pack - it's the whole suite in one repo:
cd ComfyUI/custom_nodes
git clone https://github.com/fat-tire/comfyui-unified-media-suite
or install via ComfyUI Manager by searching for "ComfyUI Unified Media Suite". Either way, make sure the av package lands in the same Python environment ComfyUI runs in, then restart. There are no model files to download - the only heavyweight dependency is PyAV.
Common issues
No module named 'av'- the classic.pip install avwent into the wrong Python (a bare terminal, not ComfyUI's venv/embed). Install it where ComfyUI's Python lives, or let Manager handle dependencies.- Wrong playback speed - pipe
fpsfrom MediaLoad instead of guessing. - Codec won't fit the container - ffmpeg's eternal turf war. Just pick another codec and retry.
- No nvenc/av1_nvenc codecs in the list - GPU encoding requires PyAV 14.1.0+ built with hardware support; on many distros pip still ships without it. See the pack README for a from-source build (Ubuntu build commands included). If the list is short, this is why.
- Try to save 100 images as a single png and "bad things" happen, per the author. Don't.
One honest caveat: this is a Preview Beta from a single maintainer (GitHub: fat-tire), and it shows - 44 impressions on this page is "basically nobody has tried it yet" territory. For plain frame output, VideoHelperSuite is the battle-tested default. This pack's pitch is alpha support, audio, and zero ffmpeg install friction. Oh, and the acronym spells "UMS", which the author insists is "entirely unintentional." Sure it is.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| filename_prefix | STRING | MediaOut | — |
| format | COMBO | mp4 | 14 options: aac, apng, avi, flac, gif, mjpeg, +8 |
| video_codec | COMBO | libx264 | 30 options: av1, av1_amf, av1_nvenc, av1_qsv, dirac, ffv1, +24 |
| audio_codec | COMBO | aac | 23 options: aac, ac3, ac3_fixed, alac, eac3, flac, +17 |
| pix_fmt | COMBO | yuv420p | 99 options: amf, argb, bgr0, bgr24, bgra, cuda, +93 |
| crf | INT | 231–51 | — |
| preset | COMBO | medium | 8 options: ultrafast, superfast, veryfast, faster, fast, medium, +2 |
| tune | COMBO | none | 7 options: film, animation, grain, stillimage, fastdecode, zerolatency, +1 |
| fpsopt | FLOAT | 241–1000 | — |
| audio_sample_rateopt | INT | 480000–192000 | — |
| imagesopt | IMAGE | — | |
| audioopt | AUDIO | — | |
| widthopt | INT | 0 | — |
| heightopt | INT | 0 | — |
| input_image_shapeopt | COMBO | B-H-W-C | 2 options: B-H-W-C, B-C-H-W |
| save_metadataopt | BOOLEAN | true | — |
Outputs (0)
No outputs