π₯ NL Read
Read plates like a compositor, not a screenshot tool
- image
- mask
- inverted_mask
- frame_count
- resolved_path
- image_info_json
ComfyUI's built-in Load Image is fine for a single PNG. It's useless the moment your shot is a 150-frame EXR sequence, a video file with a specific in/out range, or a plate that needs to land in a specific colorspace before anything else touches it. That's the gap NL Read exists to fill. It's the node from this pack that studio folks actually build pipelines around, and once you've used it, going back to Load Image feels like going back to MS Paint.
NL Read is the "I" in the pack's color-managed IO story: read a source, normalize it into the working space (ACEScg by default), and hand the graph both the image and the metadata that says what it is. It also leans on the NL Workflow context panel - set your project, shot, resolution, and frame range there, and NL Read can pull frame ranges straight from that context instead of you typing numbers everywhere.
How it works
Point source at a path or pattern and the node figures out whether it's a still, a sequence, or a video. The controls that matter most:
range_mode-contextuses the workflow's start/end frame,customlets you type your own,offignores ranges.every_nth- sample every Nth frame, the cheap way to preview a sequence at half or quarter rate.preframes/postframes- duplicate the first or last frame, handy when you need a video model to hold on a frame.reverse_sequence- read frames backwards.force_resize- resize to context resolution or a custom size, withfit/fill/stretchstrategies.input_colorspace- auto-seeded from the source you load, and it's the actual interpretation used. Leave it alone unless you know better.output_colorspace- where the emitted tensor lives, ACEScg by default.preview_colorspace- display-only. It affects what you see in the preview, never the tensor.
Outputs worth knowing: image, mask and inverted_mask (from the source's alpha or your mask mode), frame_count, resolved_path (the actual file it resolved - great for debugging pattern mismatches), and image_info_json, which carries the colorspace and source metadata onward. Wire that string into NL Grade, NL Write, or any of the color nodes and the pipeline stays coherent.
Installing and setting up
Same pack install as everything here: ComfyUI Manager, search "ComfyUI-NL_Nodes", or clone manually:
cd ComfyUI/custom_nodes
git clone https://github.com/NOLABEL-VFX/ComfyUI-NL_Nodes
Restart, then open the top-bar NL Workflow panel and set at least a project path before you lean on context-driven reads. Video reading needs ffmpeg on the system; the color-managed path wants PyOpenColorIO and OpenEXR from requirements-color.txt.
Where people get burned
The big one is path policy. NL Read ships in guarded mode: it blocks obvious system locations like /etc, /proc, /sys, /dev, and the Windows system roots, which is a sane default for a node that can read arbitrary files. But it also blocks things that aren't malicious - your NAS mount or a studio share. If reads fail on a path you're sure exists, set NL_READ_EXTRA_ROOTS to whitelist it. The NL_READ_ALLOW_ANY=1 env var exists to restore old unrestricted behavior, but treat that as a debugging escape hatch, not a lifestyle. And if you're coming from the wider ComfyUI ecosystem, remember this pack isn't a big Reddit name - it's a studio tool, so the polish is real but the community walkthroughs you're used to just don't exist yet.
Inputs (25)
| Name | Type | Default | Description |
|---|---|---|---|
| source | STRING | Path or pattern to load. | |
| exr_source | STRING | Selected MultiEXR source. Empty keeps the automatic choice. | |
| batch_size | INT | 11β4096 | Repeat still images to this batch size. |
| every_nth | INT | 11β1000 | Sample every Nth frame for sequences and videos. |
| skip_first | INT | 00β1000000 | Trim this many frames from the start of the range (videos only). |
| preframes | INT | 00β1000000 | Duplicate the first frame this many times. |
| postframes | INT | 00β1000000 | Duplicate the last frame this many times. |
| range_mode | COMBO | Frame range source for sequences and videos. Context uses workflow start_frame/end_frame. For videos, the first video frame is treated as start_frame. | |
| range_start | INT | -1-1β1000000 | Custom start_frame when range_mode is custom. |
| range_end | INT | -1-1β1000000 | Custom end_frame when range_mode is custom. |
| mask | COMBO | from alpha | Mask source mode: alpha, solid white, RGB luminance, or custom mask file. |
| reverse_sequence | BOOLEAN | false | Read frames in reverse order (sequences and videos). |
| force_resize | COMBO | Resize to context resolution or custom size. | |
| resize_mode | COMBO | Resize strategy when resizing is enabled. | |
| resize_width | INT | 00β16384 | Custom resize width (used when force_resize is custom). |
| resize_height | INT | 00β16384 | Custom resize height (used when force_resize is custom). |
| force_proportions | COMBO | off | Force aspect ratio in custom resize mode. Height is calculated from width. |
| manual_mask_source | STRING | Custom mask image path (used when mask is custom). | |
| preview_mode | COMBO | color | Choose which preview(s) to show. |
| ocio_config_path | STRING | Optional per-node OCIO config override. | |
| input_colorspace | STRING | Source colorspace used for this read. Auto-seeded from the chosen source. | |
| output_colorspace | STRING | ACEScg | Working/output colorspace used for the emitted image tensor. |
| preview_colorspace | COMBO | Output - Rec.709 | OCIO View used only for NL Read preview rendering. |
| color_role | COMBO | auto | Treat the source as color imagery or data. |
| input_policy | COMBO | auto | Legacy colorspace assignment policy retained for old workflows. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |
| mask | MASK | β |
| inverted_mask | MASK | β |
| frame_count | INT | β |
| resolved_path | STRING | β |
| image_info_json | STRING | β |