ComfyUI Node

Write

Get your frames off the browser canvas and onto the NAS, in whatever format the job wants

By FXTD-Studios·Created 8 months ago·Updated about 18 hours ago· 246
Write
  • image
  • audio
  • mask
    ◄output_path/root/radiance_output►
    ◄formatIMG │ EXR (16-bit half)►
    ◄filename►
    ◄version1►
    ◄color_spaceLinear (pass-through)►
    ◄fps0.000►
    ◄quality18►
    ◄exr_compressionZIP►
    ◄start_frame1001►
    ◄frame_padding4►
    ◄audio_source►
    ◄broadcast_safefalse►
    ◄overwritefalse►
    ◄proxy_scale0.00►
    ◄working_spaceLinear Rec.709 (sRGB)►
    ◄ocio_colorspace►
    ◄ocio_config►
    ◄hdr_reference_nits203►

    ComfyUI's Save Image node is fine right up until the moment you need a DPX, an EXR sequence, a ProRes 4444 with alpha, or a file on a network share that isn't the machine's output/ folder. Then you're writing a Python node.

    Write is the Radiance pack's delivery node - one writer covering stills, sequences, video and EXR, with format-appropriate settings. It is an output node with no graph outputs: files or nothing.

    What it accepts

    The image input is typed *, and that is not laziness. It takes a ComfyUI IMAGE tensor, a batched video frame set, a VideoHelperSuite VIDEO dict, a video file path string, or any dict/list carrying a video path. In practice you drop a decode node in front of it and stop thinking about it.

    output_path is a directory and a filename stem; the extension is appended from format. For sequences, the path becomes a folder and frames are named <folder>_<frame>.<ext> - so /out/shot gives you /out/shot/shot_1001.exr. The directory is created if missing, and network paths work as they appear on the host: /mnt/nas/renders/shot_001 on Linux, \\server\share\renders\shot_001 for a Windows UNC, Z:\renders\shot_001 for a mapped drive. Write permission on the share is required, and a failure raises rather than silently skipping.

    Inputs that matter

    • format - 22 options in two groups. IMG │ covers PNG 8-bit and 16-bit, JPEG, TIFF 16-bit and 32-bit float, DPX, WEBP, EXR 16-bit half, EXR 32-bit float and Radiance .hdr. SEQ │ does the numbered-sequence variants, and the video formats (H.264, H.265, ProRes, DNxHR) live in the same list.
    • color_space - the file encoding: transfer and primaries, derived from working_space. Linear (pass-through) writes working values unchanged. EXR and DPX record the choice in their headers; video gets primaries/transfer/matrix tags. working_space has to match what actually arrives - the pack's Read node has the same widget, so match them.
    • exr_compression - ZIP by default. ZIP, ZIPS, PIZ, RLE and Uncompressed are lossless; PXR24 is lossy on 32-bit float; B44/B44A/DWAA/DWAB are lossy. DWAA gives you small files and visible mush on gradients that you will get blamed for.
    • fps - 0 auto-detects from the source video, falling back to 24.
    • quality - CRF 18 by default for H.264/H.265 (lower is better); also remapped to JPEG quality.
    • start_frame and frame_padding - 1001 and 4 by default, i.e. shot_1001.exr. Set these to match the shot's existing numbering or your comp will not find the sequence.
    • mask - becomes the alpha channel for EXR, PNG, TIFF, DPX, WEBP and ProRes 4444. Ignored by JPEG, HDR, H.264, H.265, ProRes 422 and DNxHR, which have no alpha, and it will not warn you.
    • audio / audio_source - mux audio into the video output; the path string takes priority when both are set.
    • overwrite - off by default, and when off a unique suffix is appended instead of destroying the existing file. If you're scripting a render farm, turn this on and mean it.
    • proxy_scale, broadcast_safe, ocio_colorspace, ocio_config, hdr_reference_nits - proxy downscaling, legal-range clamping (16–235) for 8/16-bit stills only, an OCIO override that supersedes color_space, and the diffuse-white reference for PQ/HLG output (203, the BT.2408 convention, vs 100 which matches OCIO/ACES).

    Install

    ComfyUI Manager → search Radiance → install → restart → refresh. Manual:

    cd ComfyUI/custom_nodes
    git clone https://github.com/fxtd-studios/radiance.git
    cd radiance
    python -m pip install -r requirements.txt
    

    Windows portable users should use python_embeded\python.exe. This is the node that needs the I/O stack for real: OpenImageIO (DPX and fallback EXR), OpenEXR on Python below 3.14, tifffile for 16/32-bit float TIFF, and imageio-ffmpeg for video. install.py covers the first two.

    Where people get burned

    EXR doesn't invent dynamic range. This one came up in the community thread about the pack and it's correct: if you're piping 8-bit sRGB values into a 32-bit float EXR, you have an 8-bit image in an expensive container. Range has to come from somewhere - SDR → HDR, a linear Read of real camera footage, or the HDR VAE path.

    Writing frames into temp/. The Viewer's preview files are temporary. The Write node's output_path is not, and it defaults to a folder in your home directory, not to ComfyUI's output/. Point it somewhere deliberate.

    Alpha silently dropped. No error, no warning, just a JPEG with no matte because you picked the wrong format. It's listed above; it's also the single most common "where did my alpha go" moment with any writer node.

    Unreadable numbers on a render farm. start_frame and frame_padding don't inherit from anything. Wrong padding means Nuke sees a broken sequence.

    CategoryFXTD STUDIOS/Radiance/Load & Save

    Inputs (21)

    NameTypeDefaultDescription
    image*Accepts any ComfyUI output: IMAGE tensor, batched video frames, VHSor any dict/list carrying a video path.
    output_pathSTRING/root/radiance_outputOutput directory + filename stem. Extension is appended automatically based on format. For sequences: output_path becomes a folder and frames are named <folder>_<frame>.<ext> (e.g. /out/shot -> /out/shot/shot_1001.exr). Network paths are fully supported — use the path as mounted on this machine: Linux / Mac → /mnt/nas/renders/shot_001 Windows UNC → \\server\share\renders\shot_001 Windows drive→ Z:\renders\shot_001 The directory is created automatically (mkdir -p) if it does not exist. Write permissions on the share are required.
    formatCOMBOIMG │ EXR (16-bit half)Output format. Extension is appended automatically.
    filenameoptSTRINGOutput filename stem (version appended automatically). Leave empty to use output_path as the full stem.
    versionoptINT10–9999Version number appended to filename (e.g. shot_001_v0001).
    color_spaceoptCOMBOLinear (pass-through)File encoding: transfer AND primaries, from working_space. Linear (pass-through) writes the working values unchanged. EXR and DPX record it in their headers (chromaticities, oiio:ColorSpace); video gets primaries/transfer/matrix tags.
    fpsoptFLOAT0.0000–240Frame rate for video and sequence outputs. 0 = auto-detect from the source video (falls back to 24 if unavailable).
    qualityoptINT180–51CRF quality for H.264/H.265 (lower = better). Also JPEG quality 0–100 (remapped).
    exr_compressionoptCOMBOZIPEXR compression codec (EXR formats only).
    start_frameoptINT10010–99999First frame number for sequences.
    frame_paddingoptINT41–8Zero-padding width for frame numbers (e.g. 4 → 0001).
    audio_sourceoptSTRINGPath to audio file to mux into video output (optional). Takes priority over the 'audio' input when both are set.
    broadcast_safeoptBOOLEANfalse8/16-bit stills: clamp to legal range (16–235). Video is always encoded legal-range by the RGB→YUV step; float formats are never clamped.
    overwriteoptBOOLEANfalseOverwrite existing files. When disabled (default), a unique suffix is appended instead of destroying the existing file.
    proxy_scaleoptFLOAT0.000–1Downscale output by this factor for proxy preview (0 = full resolution).
    audiooptAUDIOAudio tensor from RadianceVideoLoader (muxed into video output).
    maskoptMASKOptional alpha/matte, written as the alpha channel of EXR, PNG, TIFF, DPX, WEBP and ProRes 4444. Ignored by JPEG, HDR, H.264, H.265, ProRes 422 and DNxHR, which have no alpha.
    working_spaceoptCOMBOLinear Rec.709 (sRGB)Scene-linear space the incoming IMAGE is in. color_space is encoded from here, primaries AND transfer. Match the Read node's working_space.
    ocio_colorspaceoptSTRINGAny colorspace name or alias from the OCIO config. When set it overrides color_space and OpenColorIO encodes the working space into it. Empty = use color_space.
    ocio_configoptSTRINGPath to a config.ocio or an ocio:// URI. Empty = $OCIO, else OCIO's built-in ACES 2.0 studio config.
    hdr_reference_nitsoptFLOAT20348–1000PQ and HLG only: the luminance scene-linear 1.0 (diffuse white) is written at. 203 is BT.2408 and Radiance's HDR convention; 100 matches OCIO/ACES. PQ clips at 10,000 nits, HLG at about 3.8x diffuse white.

    Outputs (0)

    No outputs