Nodes/ComfyTV/Histogram Equalize
ComfyUI Node

Histogram Equalize

Drag flat, hazy footage up by spreading its tones

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
Histogram Equalize
  • video
  • video
force_run_token0
project_id
parent_output_id0
strength0.50
clip_limit0.000

The tell of cheap or overcast footage is a histogram humped in the middle - no real blacks, no real whites, everything a foggy gray. Histogram equalization is the classic fix: it stretches the tonal distribution so the dark pixels get darker and the bright ones brighter, and a washed-out frame suddenly has contrast. It's the algorithmic cousin of cranking contrast, but smarter - it doesn't just lift one end, it re-spreads the whole histogram for maximum range.

ComfyTV is jtydhr88's canvas app (~190 stages, each its own node). Histogram Equalize sits in the VideoFX color suite, and it's a good first move on any AI-generated or phone-camera clip that looks "thin." Like the other color stages it's deterministic and previews live.

How it works

Equalization rebuilds each output pixel's brightness from where it sat in the input histogram, spreading the crowded middle into the empty ends. Two controls temper the classic problem with it:

  • strength (0–1, default 0.5) - how much of the equalization to apply. Full-strength equalization is aggressive and can look harsh or noisy, which is why the default is half. This is the dial you actually live on.
  • clip_limit (0–0.1, default 0, "cap per-bin fraction, 0 = off") - this is the "CLAHE" trick. Instead of letting a few over-full histogram bins dominate, it caps each bin's share and redistributes the overflow, which stops equalization from exaggerating noise in large flat areas. 0 turns the cap off; a small value like 0.01–0.02 is the "controlled" setting most people end up wanting.

The short version: leave strength where you can see the result but not the artifacts, and reach for clip_limit the moment the sky or a wall starts looking splotchy.

The hidden inputs, explained once

Every ComfyTV stage carries force_run_token, project_id, and parent_output_id - all marked "Internal" in the schema and populated by the frontend's projectStore for per-node Run. There's also the optional video input and a single video output. You never set the internals by hand.

Installing it

Same pack, same steps:

cd ComfyUI/custom_nodes
git clone https://github.com/jtydhr88/ComfyTV

or ComfyUI Manager ("ComfyTV"), full backend restart, then ComfyTV → VideoFX. The one gotcha that bites people: on ComfyUI Desktop, macOS, or multiple installs, clone into the running instance by absolute path and confirm custom_nodes/ComfyTV/__init__.py exists (not nested), then fully restart. The pack declares no pip deps, but video stages lazily import PyAV - pip install av if a video node errors.

Common issues

  • The frame now looks noisy, especially in flat areas - that's un-capped equalization amplifying sensor noise. Add a small clip_limit (0.01–0.02) and drop strength.
  • Skin tones go weird - equalization operates on luminance here, but pushed hard it can still blow highlights. Back strength down; this node is a starting point, not the whole grade.
  • No visible change - strength is very low, or the clip already spans a full tonal range (in which case equalization has little left to do).
CategoryComfyTV/VideoFX

Inputs (6)

NameTypeDefaultDescription
force_run_tokenINT00–2147483647Internal — bumped on Run to invalidate ComfyUI's input cache.
project_idSTRINGInternal — populated by the projectStore on the frontend.
parent_output_idINT00–2147483647Internal — lineage parent set by spawn handlers on the frontend.
strengthFLOAT0.500–1
clip_limitFLOAT0.0000–0.1cap per-bin fraction, 0 = off
videooptCOMFYTV_VIDEO

Outputs (1)

NameTypeDescription
videoCOMFYTV_VIDEO