Nodes/comfyui-timesaver/TS Film Emulation
ComfyUI Node

TS Film Emulation

Cinematic film looks without leaving the graph

By AlexYez·Created 2 years ago·Updated a day ago· 12
TS Film Emulation
  • image
  • IMAGE
enabletrue
film_preset
lut_choice
lut_strength1.00
gamma_correctiontrue
film_strength1.00
contrast_curve1.00
warmth0.00
grain_intensity0.02
grain_size0.5
fade0.00
shadow_saturation0.80
highlight_saturation0.85
grain_speed1.00
grain_seed0

AI images have a tell, and it's usually not the hands - it's the color. Perfect, sterile, no grain, everything evenly lit and evenly graded. TS Film Emulation is the one-stop fix: pick a Kodak Portra, Fuji, or Cineon-style preset, and your render suddenly has a memory of having been shot on film.

It's the kind of node you bolt onto the end of a pipeline and forget about. Wire IMAGE in, get a graded IMAGE out, no model download, no API, works on every frame of a video batch. If you've ever gone down the rabbit hole of hunting .cube LUTs on random forums, this also gives you a clean home for them.

How it works

The node does three deterministic things, all pure pixel math:

  1. A film preset or a LUT. The film_preset dropdown has built-in analog looks (Kodak, Fuji, Cineon-style), or you can flip to "External LUT" and pick any .cube file from the models/luts/ folder - drop the file in there, and it appears in lut_choice after a refresh. That folder is where your own downloaded LUTs go, and the node reads them at runtime.
  2. Gamma + contrast. gamma_correction applies the LUT in sRGB space (keep it on - that's the recommended path for most .cube files), and contrast_curve is a mid-gray pivot where 1.0 is unchanged, above 1.0 is punchier.
  3. Grain. grain_intensity and grain_size add film grain, which is the single cheapest move for killing the AI look - the post-processing doc makes the point that film grain is where the community's strongest "how to break the plastic look" arguments live.

There's also warmth (positive warms, negative cools) if the preset is close but the white balance isn't, and film_strength / lut_strength to blend any of it back toward the original.

The inputs that matter

Honestly, for most people: film_preset, and then film_strength if you want the look dialed down to 50%. Everything else is refinement. grain_intensity at its 0.02 default is subtle; crank it if you want it visible, or set it to 0 for a clean-but-graded image. contrast_curve around 1.1–1.2 is the usual "punch it up" range - don't chase 3.0, you'll just crush your shadows.

One output, IMAGE, which drops straight into a preview or saver.

Installing it

Part of comfyui-timesaver - install via ComfyUI Manager (search "Timesaver") or:

cd ComfyUI/custom_nodes
git clone https://github.com/AlexYez/comfyui-timesaver
cd comfyui-timesaver
python -m pip install -r requirements.txt

Restart ComfyUI and it's there. No weights to download. If you want external LUTs, create models/luts/ and drop .cube files in.

Gotchas

The biggest surprise is that LUTs only show up in the dropdown if they're in the right folder - a .cube sitting in input/ is invisible to this node. And remember the LUT folder resolution: the pack looks in its own bundled luts/ directory first, then models/luts/, so when you drop your own files in, put them in ComfyUI/models/luts/ where extra_model_paths.yaml and the rest of ComfyUI expect them. Other than that, it's a fire-and-forget node - the kind you install once, use in every workflow, and eventually stop noticing, which is exactly the compliment a color node wants.

CategoryTS/Image/Color

Inputs (16)

NameTypeDefaultDescription
imageIMAGEImage to apply the film look to.
enableBOOLEANtrueIf disabled, the image passes through unchanged.
film_presetCOMBOBuilt-in analog film look. Choose 'External LUT' to use a .cube LUT from lut_choice instead.
lut_choiceCOMBOExternal .cube LUT file (from the luts folder) applied when film_preset is 'External LUT'. 'None' = no LUT.
lut_strengthFLOAT1.000–1Blend amount of the external LUT. 0 = original, 1 = full LUT.
gamma_correctionBOOLEANtrueApply the LUT in sRGB space (recommended for most .cube LUTs).
film_strengthFLOAT1.000–1Blend amount of the selected film preset. 0 = original, 1 = full preset.
contrast_curveFLOAT1.000–3Contrast around mid-gray. 1 = unchanged, >1 = more contrast.
warmthFLOAT0.00-1–1Warm/cool shift. Positive warms (red up, blue down), negative cools.
grain_intensityFLOAT0.020–0.5Strength of added film grain. 0 = no grain.
grain_sizeFLOAT0.50.5–5Scale of the grain particles. Higher values give coarser grain.
fadeFLOAT0.000–0.5Lifts blacks toward gray for a faded, matte film look. 0 = off.
shadow_saturationFLOAT0.800–2Color saturation in the shadows. 1 = unchanged, <1 = desaturated.
highlight_saturationFLOAT0.850–2Color saturation in the highlights. 1 = unchanged, <1 = desaturated.
grain_speedoptFLOAT1.000.05–1For clips: how often the grain pattern is redrawn. 1.0 = a new pattern every frame (lively, digital). 0.5 = one pattern held for two frames, 0.25 for four — closer to scanned film, where the grain does not race the action. No effect on a single image.
grain_seedoptINT00–4294967295Seed for the grain. The same seed gives the same grain on the same frames, so a re-render matches the take you graded.

Outputs (1)

NameTypeDescription
IMAGEIMAGE