Nodes/comfyui-timesaver/TS Color Match
ComfyUI Node

TS Color Match

Make every shot agree with one reference frame

By AlexYez·Created 2 years ago·Updated about 23 hours ago· 12
TS Color Match
  • reference
  • target
  • image
modemkl
deviceauto
strength1.0
enabletrue
match_masknone
mask_size32
compute_max_side1024
mkl_sample_points300000
sinkhorn_max_points2048
reuse_referencetrue
temporal_smoothingtrue
chunk_size4
loggingfalse

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 - mkl or sinkhorn. Video → MKL. Precision → Sinkhorn.
  • match_mask + mask_size - set to rectangle or ellipse and it samples only the border strip of width mask_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.

CategoryTS/Image/Color

Inputs (15)

NameTypeDefaultDescription
referenceIMAGEReference whose colors the target is matched to. With batch=1 the statistics can be reused across a whole video.
targetIMAGEFrames/images that get recolored toward the reference.
modeCOMBOmklmkl is faster and more stable; sinkhorn is more accurate but heavier on memory and time.
deviceCOMBOautoauto = GPU if available, otherwise CPU. In GPU mode large tensors stay on CPU to guard against OOM.
strengthFLOAT1.00–1Softly blends the original and the color-corrected result.
enableBOOLEANtrueWhen off, the node returns the input target unchanged.
match_maskCOMBOnonerectangle/ellipse sample only the image border of width mask_size, for stabilization.
mask_sizeINT320–512Used only when match_mask is rectangle or ellipse.
compute_max_sideINT10240–4096Compute A,b on a downscaled copy (e.g. 512–1024). Saves memory at 4K with almost no quality loss.
mkl_sample_pointsINT3000000–2000000200k–500k recommended. At 0 all pixels are used, which can OOM at 4K.
sinkhorn_max_pointsINT20480–65536Usually 1024–2048 for 4K. Too large a value can OOM.
reuse_referenceBOOLEANtrueSpeeds up and stabilizes video when one reference is shared across the whole batch.
temporal_smoothingBOOLEANtrueEMA 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_sizeINT40–2564–8 recommended for long 4K videos. 0 processes the whole batch at once.
loggingBOOLEANfalseWhen on, logs processing stages, chunk index and GPU memory state to the console.

Outputs (1)

NameTypeDescription
imageIMAGE