Save EXR (MEC)
Save real EXR files from ComfyUI, codec choices included
- image
- aov_alpha
- info_json
PNG is where images go to lose their dynamic range. If you're doing VFX, rendering passes, or HDR work, you eventually need OpenEXR - the format that stores float pixels, multiple channels, and real metadata instead of an 8-bit approximation. Save EXR (MEC) is the pack's writer: it takes an IMAGE batch and writes proper .exr files with your choice of codec, bit depth, and embedded attributes. It's one of those nodes that quietly marks the difference between "ComfyUI for fun" and "ComfyUI for comp."
How it writes
The mechanism is a thin, careful wrapper: for each frame in the batch it writes a separate EXR (_0001, _0002 suffixes added when B > 1), converts the RGB to float32, optionally adds a named ALPHA channel from an aov_alpha mask input instead of discarding it, and embeds any attributes you pass as metadata_json (e.g. {"comment": "shot_0010", "camera": "ARRI"}). It uses OpenEXR when available with an imageio + TIFF fallback chain, per the pack's requirements. One info_json STRING output reports what got written.
Half float vs full float
Two settings deserve real attention, and the author's tooltips are the best guide you'll get. half_float (default on) writes 16-bit half instead of 32-bit float - half the file size and the norm for colour passes, but the tooltip is blunt: turn it off for data passes (depth, position, normals, motion vectors) because they "quantise visibly at half precision." If your renderer hands you a depth pass that looks like stairs, this is the first thing to check.
The codec dropdown
compression is the codec dropdown, and the tooltip reads like a facility handover note: zips (default) is lossless scanline, the safe default; zip is lossless 16-scanline blocks, slightly smaller; piz is lossless and the choice for grainy plates because it's wavelet-based and handles noise where zip bloats; dwaa/dwab are lossy but what most studios ship for non-data passes - 5–10× smaller at visually-lossless settings, and the tooltip's warning stands: never on a data pass; rle for large flat areas; none uncompressed for maximum-compatibility handoff. If you're handing files to a colorist, piz (data/grain) or dwaa (clean colour) are the ones to reach for; zips when you're not sure.
Where it lives in a workflow
Where it lives in a workflow: at the end of a render-pass graph - composite your passes in ComfyUI, then Save EXR hands the file to Nuke, Resolve, or whatever eats EXR next. The metadata_json round-trips through the pack's LoadEXRMEC, so you can write a shot and read its attributes back without losing the annotation layer - a nice nod to the KB's "the metadata is the payload" philosophy, applied to float files.
Install
Install: clone Code2Collapse/ComfyUI-CustomNodePacks into custom_nodes or Manager → "CustomNodePacks". The EXR deps are optional in requirements.txt - OpenEXR/Imath preferred, or imageio + imageio-freeimage as fallback - so if the node errors on save, that's your missing piece, not a bug. It's under MaskEditControl/IO.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| file_path | STRING | Absolute output path. Batches add _0001, _0002 suffixes. | |
| half_floatopt | BOOLEAN | true | 16-bit half vs 32-bit float. half halves the file and is the norm for COLOUR passes. Turn it OFF for DATA passes - depth, position, normals, motion vectors - which quantise visibly at half precision. |
| compressionopt | COMBO | zips | EXR codec. zips = lossless, scanline, fastest to read a single line - a safe default. zip = lossless, 16-scanline blocks, slightly smaller than zips. piz = lossless and the best choice for GRAINY plates; wavelet-based, handles noise where zip bloats. dwaa / dwab = LOSSY but what most facilities ship for non-data passes: 5-10x smaller than zip at visually lossless settings. Never use on a data pass. rle = lossless, only good for large flat areas. none = uncompressed, for maximum-compatibility handoff. |
| metadata_jsonopt | STRING | Optional JSON object of EXR attributes to embed, e.g. {"comment": "shot_0010", "camera": "ARRI"}. Round-trips through LoadEXRMEC. | |
| aov_alphaopt | MASK | Optional MASK written as a named ALPHA channel alongside RGB, instead of being discarded. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| info_json | STRING | — |