π― NL Match
Make two image streams actually comparable
- A
- A_mask
- B
- B_mask
- A
- A_mask
- A_image_info_json
- B
- B_mask
- B_image_info_json
NL Match is the boring, essential utility of this pack: it takes two image streams, A and B, and aligns them so you can actually compare, blend, or merge them. If you've ever tried to wire two images of different resolutions or frame counts into a single node and watched it explode (or silently do the wrong thing), you know exactly why this exists.
The problem it solves is the classic pipeline mismatch: your generated render is 832Γ480, the plate is 1920Γ1080, and one of them is a batch of 10 frames while the other is 24. Diffusers and matchers choke on that. NL Match normalizes both streams to a common ground - matching resolution, batch length, and colorspace context - while keeping their masks and metadata intact. Then every downstream node gets inputs it can actually work with.
What it aligns
target- what to align against:A,B,context(the NL Workflow resolution), orcustom.match_resolution/match_batch/match_color_space- toggles for each axis, so you can align dimensions but deliberately not touch colorspace, for example.resize_mode-fit,fill, orstretchfor the resolution alignment.batch_mode-repeat_last,cycle,truncate, orpad_zerofor length matching.mask_default- what fills in for a missing mask (default 1 = solid).target_width/target_height/target_batch_size/target_color_space- used whentargetiscustom.
Inputs: A/B streams with optional A_mask/B_mask and A_image_info_json/B_image_info_json color metadata. Outputs: both aligned streams plus their masks and metadata, so the alignment is visible and inspectable.
Where it sits in a workflow
Reach for it before any NLMerge, comparison, or A/B compositing step - or before any node that needs two streams of identical shape. The pack's own manual testing treats NL Match, Fit Frame, Merge, and Shuffle as one family: size the input, align the streams, merge, and shuffle channels. The tip that saves real pain: keep match_batch on and pick repeat_last unless you've thought about what truncate will do to your tail frames.
Install
Standard pack route:
cd ComfyUI/custom_nodes
git clone https://github.com/NOLABEL-VFX/ComfyUI-NL_Nodes
or ComfyUI Manager β "ComfyUI-NL_Nodes", restart. No heavy dependencies, no models to download - it's pure tensor plumbing. The context target assumes you've configured the NL Workflow panel; if you haven't, it defaults to A's shape, which is usually a fine fallback for a first run.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| target | COMBO | context | 4 options: A, B, context, custom |
| match_resolution | BOOLEAN | true | β |
| match_batch | BOOLEAN | true | β |
| match_color_space | BOOLEAN | true | β |
| resize_mode | COMBO | fit | 3 options: fit, fill, stretch |
| batch_mode | COMBO | repeat_last | 4 options: repeat_last, cycle, truncate, pad_zero |
| mask_default | FLOAT | 1.000β1 | β |
| target_width | INT | 00β16384 | β |
| target_height | INT | 00β16384 | β |
| target_batch_size | INT | 11β4096 | β |
| target_color_space | STRING | β | |
| Aopt | IMAGE | Optional A image stream. | |
| A_maskopt | MASK | Optional A mask. Missing masks are filled from mask_default. | |
| A_image_info_jsonopt | STRING | Optional serialized color metadata for A. | |
| Bopt | IMAGE | Optional B image stream. | |
| B_maskopt | MASK | Optional B mask. Missing masks are filled from mask_default. | |
| B_image_info_jsonopt | STRING | Optional serialized color metadata for B. |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| A | IMAGE | β |
| A_mask | MASK | β |
| A_image_info_json | STRING | β |
| B | IMAGE | β |
| B_mask | MASK | β |
| B_image_info_json | STRING | β |