Cinematic Enhancer π ReActor
ReActor's Cinematic Enhancer is the de-AI pass hiding inside a face-swap pack
- image
- depth_map
- image
You installed ReActor for face swapping and got a colorist. The pack's 0.7.2 update added ReActorCinematicEnhancer - "Cinematic Enhancer π ReActor" in the node menu - and it's the least ReActor-ish node in the whole repo. No ONNX models, no face detection, no InsightFace weights, no license landmine. It takes a finished image, runs a stack of deterministic pixel operations over it, and gives you back something that reads a bit less like a render.
That's exactly the job this layer exists for. Post-processing is the pipeline stage people skip, and the mistake it prevents is trying to fix flat color or the "AI look" with another diffusion pass. A grain pass is additive noise. A LUT is a lookup table. Millisecond ops, no seed lottery, no re-rolled face. Gourieff's README pitch is blunt: "Forget about plastic skin and boring pictures⦠make any photorealistic image more soulful."
What it does to your pixels, in order
The node runs one fixed chain, and knowing the order explains most of the weird results:
LUT β vignette β depth blur β color correction β film grain β HDR β global blend.
If lut_file isn't none, it parses the file, optionally decodes gamma (lut_gamma_correction, default on: x^(1/2.2) before the LUT, x^2.2 after - what you want for LUTs authored in log or video gamma), then mixes the result back at lut_strength. Vignette is a radial multiply. Depth blur only fires if you connect depth_map. Color correction splits into PIL brightness/contrast and OpenCV-side temperature (positive warms red, negative cools blue), gamma, HSV hue rotation and saturation. Grain comes after color, which is right. Then HDR tone-maps in LAB luminance via ImageCms, and only then does intensity blend.
That last one is the whole design in one slider: intensity is a master wet/dry mix against the original image, applied at the very end. At 0 you get your input back pixel for pixel and every other knob is wasted. It defaults to 0.5, so half your grading gets thrown away before you see it. If you want to actually evaluate a look, push it to 1 while tuning.
The knobs a beginner actually sets
intensity- the mix. Start at 1.0, dial back to taste.lut_file+lut_strength- drop.cubefiles inComfyUI/models/luts(Gourieff keeps a pile on Hugging Face) and refresh. 0.3β0.5 strength is plenty.film_grain_power- the de-AI knob, 0.05β0.15 for a whisper, and the main reason to open the node at all.film_grain_method-advancedbuilds color noise, mixes it toward mono byfilm_grain_sat, scales it byfilm_grain_scale, and masks it by luminance sofilm_grain_shadowsandfilm_grain_highscontrol how much lands in the dark and bright ends.fastis plain Gaussian noise at half amplitude and ignores those four fields. Advanced for stills, fast for video batches.
Output is a single IMAGE - wire it into SaveImage, a VAE Encode, or your video combine node. That's it. No hidden second output.
The depth_map slot
Optional, and it does one thing: fake depth of field. film_blur_strength sets the maximum blur radius (capped at 256px), film_focal_depth picks the in-focus plane (0.9 default, so near-ish), film_focus_spread controls falloff. The mask gets resized to your image if it doesn't match, and RGB depth is flattened to its first channel. No depth_map, no blur - and film_blur_strength defaults to 1 anyway, so nobody gets surprise blur.
Installing it
ComfyUI Manager β Install Custom Nodes β search "ReActor" β install β restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/Gourieff/ComfyUI-ReActor
cd ComfyUI-ReActor
install.bat # Windows - install.py for Linux/macOS
colour-science is in the pack's requirements.txt, so the install script gets it for you. If you skipped the script, install it into the Python ComfyUI actually runs:
ComfyUI\python_embeded\python.exe -m pip install colour-science
You don't need inswapper, buffalo_l, or any face model for this node. You do need something in ComfyUI/models/luts, or the dropdown is just none.
Where people get burned
The node silently does nothing. No colour-science, no cinematic effect: the module catches the import failure, logs ReActorCinematicEnhancer is not available, please install 'colour' library to the console, and returns your image untouched. The graph runs green and you blame your settings. Check the console, not the image.
Non-.cube LUTs in the dropdown. The file picker lists .cube, .spi1d, .spi3d, .spimtx and .csp, but the code only ever calls read_LUT_IridasCube. Stick to .cube or you'll get an error mid-run.
film_grain_scale's tooltip is wrong. It claims 0.1..1; the range is 0.1β10 and the code divides resolution by the value, so above 1 the noise gets coarse - the direction you want for 35mm texture. Default 1 means "don't scale". Trust the slider, not the hint.
Grain in video sparkles. Every frame gets fresh noise with no temporal coherence, so subtle grain crawls across 24fps. Drop film_grain_power to near nothing for sequences, or call the sparkle "shot on film" and move on.
A saved workflow throws on a node that used to work. This node is beta and ReActor's input signatures have moved before. Delete the node, re-add it - the README's own first advice, and still the fastest fix.
Inputs (27)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| intensity | FLOAT | 0.500β1 | 0..1, def: 0.5 |
| lut_file | COMBO | 1 options: none | |
| lut_strength | FLOAT | 0.50β1 | 0..1, def: 0.5 |
| lut_gamma_correction | BOOLEAN | true | β |
| film_grain_method | COMBO | advanced | 2 options: advanced, fast |
| film_grain_power | FLOAT | 0.100β1 | 0..1, def: 0.1 |
| film_grain_scale | FLOAT | 1.00.1β10 | 0.1..1, def: 0.1 |
| film_grain_sat | FLOAT | 0.150β1 | (advanced only) 0..1, def: 0.15 |
| film_grain_shadows | FLOAT | 0.200β1 | (advanced only) 0..1, def: 0.2 |
| film_grain_highs | FLOAT | 0.200β1 | (advanced only) 0..1, def: 0.2 |
| film_blur_strength | INT | 10β256 | (by depth_map) 0..256, def: 1 |
| film_focal_depth | FLOAT | 0.900β1 | (by depth_map) 0..1, def: 0.9 |
| film_focus_spread | FLOAT | 2.20.1β8 | (by depth_map) 0..8, def: 2.2 |
| film_vignette_intensity | FLOAT | 0.100β1 | 0..1, def: 0.1 |
| cc_temperature | FLOAT | 0-100β100 | -100..100, def: 0 |
| cc_hue | FLOAT | 0-90β90 | -90..90, def: 0 |
| cc_brightness | FLOAT | 0-100β100 | -100..100, def: 0 |
| cc_contrast | FLOAT | 0-100β100 | -100..100, def: 0 |
| cc_saturation | FLOAT | 0-100β100 | -100..100, def: 0 |
| cc_gamma | FLOAT | 1.00.2β2.2 | 0.2..2.2, def: 1.0 |
| hdr_intensity | FLOAT | 0.500β5 | 0..5, def: 0.5 |
| hdr_shadow_intensity | FLOAT | 0.250β1 | 0..1, def: 0.25 |
| hdr_highlight_intensity | FLOAT | 0.750β1 | 0..1, def: 0.75 |
| hdr_contrast | FLOAT | 0.100β1 | 0..1, def: 0.1 |
| hdr_enhance_color | FLOAT | 0.250β1 | 0..1, def: 0.25 |
| depth_mapopt | IMAGE | β |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |