TS Color Match
Make every shot agree with one reference frame
- reference
- target
- image
Ever shot two videos on different cameras, or generated a batch where every frame has its own white balance? TS Color Match fixes that without touching a sampler. You feed it a reference image whose colors you like and a target batch that doesn't match it, and it transfers the palette over. Same idea as Photoshop's "Match Color," except it runs inside the graph, handles whole video batches, and doesn't lose its mind over the borders.
This is the color-grading node you actually reach for when the job is consistency, not look: harmonizing clips from different sources, matching CG into live-action plates, or grading a video to one keyframe you already approved. It's deterministic pixel math, not a model, so it's fast and it never rewrites your image - the post-processing layer's whole trick is doing in milliseconds what a diffusion pass would gamble a seed on.
How it works
Two algorithms, and the choice is a real trade, not marketing. MKL (the default) solves a fast linear color transfer and adds a temporal_smoothing flag that EMA-smooths the transform between frames - that's the one you want for video, because it kills flicker. Sinkhorn is optimal-transport based: slower, hungrier, but noticeably more precise when you're matching a dramatic grade. Start with MKL, and only reach for Sinkhorn when the MKL result looks off and you can afford the wait.
It works by computing a color transform from the reference image's statistics, then applying it to the target batch. To keep 4K sane it computes on a downscaled copy - compute_max_side (default 1024) is where you save VRAM, and dropping it to 512 costs almost nothing visually. There's also chunk_size for processing long videos in chunks rather than all at once, and a logging toggle if you want to watch it work.
The inputs that matter
reference/target- the two IMAGE inputs. Reference is one image (or a batch where each frame gets its own stats); target is everything that gets recolored.mode-mklorsinkhorn. Video → MKL. Precision → Sinkhorn.match_mask+mask_size- set torectangleorellipseand it samples only the border strip of widthmask_size. Counterintuitive, but this is the stabilization trick for video: sampling the edges keeps the transform from swinging when the subject moves through the frame.reuse_reference- with a single reference and a whole batch, it computes the stats once and reuses them. This is the video-speed button.strength- blends the corrected result back into the original. 1.0 is full transfer; 0.5 gives you half the grade. Great for when the reference is close but not that close.
The single output is image - the recolored batch - which wires straight into a preview, saver, or the next node in the chain.
Installing it
It's part of comfyui-timesaver (search "Timesaver" in ComfyUI Manager), or:
cd ComfyUI/custom_nodes
git clone https://github.com/AlexYez/comfyui-timesaver
cd comfyui-timesaver
python -m pip install -r requirements.txt
Then restart ComfyUI. No model files - this node is pure math, so it works the moment the pack loads.
Where people get burned
The OOM trap is mkl_sample_points. At 0 it uses every pixel, which at 4K is a lot of matrix; the tooltip recommends 200k–500k for a reason. Same story with sinkhorn_max_points - keep it at 1024–2048 for 4K input. And if you're on a Mac, don't panic when you see CPU activity: the README notes this node quietly does two small linear-algebra solves on the CPU on Metal machines, because PyTorch doesn't implement linalg.eigh/linalg.lstsq on the GPU there. Everything else stays on the GPU, and the result is identical.
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| reference | IMAGE | Reference whose colors the target is matched to. With batch=1 the statistics can be reused across a whole video. | |
| target | IMAGE | Frames/images that get recolored toward the reference. | |
| mode | COMBO | mkl | mkl is faster and more stable; sinkhorn is more accurate but heavier on memory and time. |
| device | COMBO | auto | auto = GPU if available, otherwise CPU. In GPU mode large tensors stay on CPU to guard against OOM. |
| strength | FLOAT | 1.00–1 | Softly blends the original and the color-corrected result. |
| enable | BOOLEAN | true | When off, the node returns the input target unchanged. |
| match_mask | COMBO | none | rectangle/ellipse sample only the image border of width mask_size, for stabilization. |
| mask_size | INT | 320–512 | Used only when match_mask is rectangle or ellipse. |
| compute_max_side | INT | 10240–4096 | Compute A,b on a downscaled copy (e.g. 512–1024). Saves memory at 4K with almost no quality loss. |
| mkl_sample_points | INT | 3000000–2000000 | 200k–500k recommended. At 0 all pixels are used, which can OOM at 4K. |
| sinkhorn_max_points | INT | 20480–65536 | Usually 1024–2048 for 4K. Too large a value can OOM. |
| reuse_reference | BOOLEAN | true | Speeds up and stabilizes video when one reference is shared across the whole batch. |
| temporal_smoothing | BOOLEAN | true | EMA smoothing of the color transforms between frames. Enable for video (suppresses flicker); disable for a batch of UNrelated images, otherwise per-frame corrections bleed into each other. |
| chunk_size | INT | 40–256 | 4–8 recommended for long 4K videos. 0 processes the whole batch at once. |
| logging | BOOLEAN | false | When on, logs processing stages, chunk index and GPU memory state to the console. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |