Save EXR (Multi-Layer)
Get float EXRs out of ComfyUI, passes and all
- image
- depth
- normal
- mask
- diffuse
- specular
- emission
- path
This is the node people install the pack for. Save EXR (Multi-Layer) takes a float IMAGE and writes a real .exr - 16-bit half-float or 32-bit float, lossless ZIP or wavelet PIZ compression, and optionally a whole stack of extra passes (depth, normal, mask, diffuse, specular, emission) into a single multi-layer file. If you've ever tried to hand an AI-generated element to a Nuke comp or a DaVinci grade, you know the pain this removes: an 8-bit sRGB PNG treats linear light like gamma-encoded values and every blend goes wrong. A float EXR is what a VFX pipeline actually speaks.
The killer use case, and one people keep rediscovering: depth maps. ComfyUI depth estimators usually hand you an 8-bit-ish image, which is useless as a displacement map. This node lets you write a proper float depth pass to depth.Z in a real EXR - the difference between "a grayscale picture" and "data you can displace geometry with."
How it works
The main image becomes the beauty pass (R, G, B, plus A if it has alpha). Each optional input becomes a named layer with convention-correct channel names, which is the detail that makes the file drop into Nuke cleanly:
depth→depth.Z(single channel; an RGB input is luma-weighted down)normal→normal.X,normal.Y,normal.Zmask→mask.Adiffuse,specular,emission→layer.RGB
Passes are auto-resized to match the beauty pass if their dimensions differ, so a depth map at a different resolution doesn't break the write. If the OpenEXR python package isn't installed, it degrades to a flat single-image EXR via OpenCV, and then tifffile - workable, but you lose the layers and the compression choices. Install openexr.
The settings that matter
output_dir- defaults to ComfyUI'soutputfolder (and writes are confined there)filename- a template,render_%04dby default; each frame in a batch gets its number filled inbit_depth-16f (half-float)or32f (float). Half-float at half the file size is the right default for almost everything; go 32f only when you genuinely need the headroomcompression-ZIPis the recommended default (lossless, universally readable);PIZis the wavelet option for big files;DWAAif you're writing video sequences and want speedstart_frame- offsets the frame counter on the filename
It's an output node (it returns a path string and stops the graph), so it always runs.
Install
Manager: search "ACES EXR Toolkit". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/azhagurajpandians/ComfyUI-ACES-EXR-Toolkit.git
python -m pip install -r ComfyUI-ACES-EXR-Toolkit/requirements.txt
Restart ComfyUI. It sits under image/ACES + EXR with the rest of the pack.
Gotchas
The main trap is skipping the dependency: without the openexr pip package you still get a file, but it's a flat beauty-only EXR and the multi-layer + compression features silently vanish. Check pip list for OpenEXR if your "multi-layer" file opens as one layer. Also remember this is a save, not a preview - to check an HDR result before committing bytes to disk, route it through the pack's Nodex HDR Viewer first.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| output_dir | STRING | /tmp/ComfyUI/output | — |
| filename | STRING | render_%04d | — |
| bit_depth | COMBO | 16f (half-float) | 2 options: 16f (half-float), 32f (float) |
| compression | COMBO | ZIP (lossless, recommended) | 8 options: ZIP (lossless, recommended), ZIPS (lossless, scanline), PIZ (lossless, wavelet), PXR24 (lossy, 24-bit), RLE (lossless, run-length), B44 (lossy, fixed ratio), +2 |
| depthopt | IMAGE,MASK | — | |
| normalopt | IMAGE | — | |
| maskopt | MASK | — | |
| diffuseopt | IMAGE | — | |
| specularopt | IMAGE | — | |
| emissionopt | IMAGE | — | |
| start_frameopt | INT | 10–99999 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| path | STRING | — |