Hue Correct
Recolor a specific color range, not the whole frame
- video
- video
The sky is a sickly green-cyan and you want it blue. The product's red is too orange. Everything else is fine - you don't want a global curve to wreck the rest of the shot. Hue Correct is the targeted tool: it lets you draw adjustments that apply only to a range of hues, so you can shift one color family while the rest of the frame sits untouched. In colorist terms it's a hue-vs-value / hue-vs-sat operation, and it's one of the most useful refinements in ComfyTV's color suite.
ComfyTV is jtydhr88's canvas app (~190 stages, each its own node). Hue Correct lives in the VideoFX color group next to the curves and LUT stages.
How it works
The node's core is the curves field - a JSON blob shaped like {"sat"|"lum"|"red"|"green"|"blue"|"r_sup"|"g_sup"|"b_sup"|"hue": [[x,y],...]} over hue 0..1. Each key is a channel, and each channel maps input hue position to an output value:
- sat and lum - adjust saturation or brightness per hue range.
- red / green / blue - shift the RGB balance per hue range (this is the "make the red more red" control).
- r_sup / g_sup / b_sup - secondary/suppression channels for fine control.
- hue - actually rotate hue itself, so "turn this green into teal" is a real option.
You don't hand-write that JSON - the in-node editor builds it from points you drag, same as the curves stages. Two supporting dials:
- sat_thrsh (0–1) - a saturation gate; only pixels at least this saturated get corrected, so desaturated grays stay untouched.
- luminance_mix (0–1) - how much the correction also reaches into luminance, to keep bright highlights from being yanked around.
The reason this beats a global curve: a hue-targeted change is local by construction. You can recolor the grass without touching a blue shirt that happens to sit next to it.
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. Plus the optional video input and 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 whole image shifts, not just the range - your curve points cover too much of the hue axis, or
sat_thrshis 0 so even near-gray pixels get corrected. Tighten the curve, raise the gate. - Edges of the correction banding - a hard hue range boundary causes visible steps. Give the curve soft falloff at both ends rather than a cliff.
- The colors you want are fighting each other - use the
huechannel for rotation and thesatchannel for punch separately, instead of trying to do both in one curve. - Bright areas get weirdly tinted - raise
luminance_mixto shield highlights, or lower it if it's doing the opposite.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| force_run_token | INT | 00–2147483647 | Internal — bumped on Run to invalidate ComfyUI's input cache. |
| project_id | STRING | Internal — populated by the projectStore on the frontend. | |
| parent_output_id | INT | 00–2147483647 | Internal — lineage parent set by spawn handlers on the frontend. |
| curves | STRING | JSON {"sat"|"lum"|"red"|"green"|"blue"|"r_sup"|"g_sup"|"b_sup"|"hue": [[x,y],...]} over hue 0..1 | |
| sat_thrsh | FLOAT | 0.000–1 | — |
| luminance_mix | FLOAT | 0.000–1 | — |
| videoopt | COMFYTV_VIDEO | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| video | COMFYTV_VIDEO | — |