Nodes/ComfyTV/Light Graffiti
ComfyUI Node

Light Graffiti

Paint with moving lights without a long exposure

By jtydhr88·Created 3 months ago·Updated about 15 hours ago· 725
Light Graffiti
  • video
  • video
force_run_token0
project_id
parent_output_id0
threshold0.900
sum_threshold2.20
decay0.000
gain1.00

Light Graffiti is the effect that turns a person waving a sparkler - or a car's headlights cutting through a dark frame - into glowing trails of light. The real-world version needs a long exposure and a dark room; this node does it per-frame on video that's already been shot, which means you can apply it to footage you'd never have gotten right in camera. Think of it as a temporal accumulation effect: bright pixels leave a fading echo as they move.

ComfyTV is the canvas-style app layer on ComfyUI where every operation is its own node. Light Graffiti is one of the VideoFX stages, and it's another pure-math stage - no models, no downloads, just accumulation over time on your GPU.

How it works. For each frame, the stage finds pixels brighter than a threshold and keeps them; everything else falls back to a decayed version of the previous frame. The result is that anything bright that moves leaves a trail that fades at the rate decay dictates - set decay to 0 and the trails never fade (you get a full light-painting freeze); raise it and you get short comet streaks. sum_threshold is the clever part: it gates the accumulation on the sum of recent frames, so it can distinguish "a bright pixel that was also there last frame" from transient flash. gain just brightens the accumulated light.

The inputs that matter. The force_run_token, project_id and parent_output_id inputs are internal plumbing - ignore them. The four real knobs:

  • threshold - 0.5–1, default 0.9. The brightness cutoff for "this pixel is light to be painted."
  • sum_threshold - 0–3, default 2.2. How much accumulated light is needed for a pixel to persist. This is the anti-noise dial: too low and sensor noise builds up into fog; too high and genuine trails get clipped.
  • decay - 0–1, default 0. 0 = trails never fade (classic long-exposure freeze); higher = faster fade (comet tails).
  • gain - 0.1–4, default 1. Brightness boost on the accumulated light.

The video input is the upstream clip (optional but effectively required - there's nothing to accumulate otherwise); the output is a video for the rest of the FX chain.

Install. Install the pack once:

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

Restart ComfyUI (full restart, not a browser refresh) and the stage appears under ComfyTV → VideoFX. ComfyUI Manager - search "ComfyTV" - works too. Zero Python dependencies (empty dependencies in pyproject.toml), no model files. Desktop/multi-install users: clone into the running instance's path from the startup log, or the node never registers.

Where people get burned. The number one miss is forgetting that this needs bright pixels - on a normal daytime clip almost nothing crosses a 0.9 threshold and the output looks unchanged, which reads as "broken." Feed it dark footage with a bright moving source (sparkler, headlights, flashlight, LED wand) and the magic appears. Second: sum_threshold too low turns the whole frame into glowing fog because noise accumulates frame after frame; if you see haze, raise it. And decay at 0 with a fast-moving bright object leaves a full frame of trails that can blow out highlights - back gain down to around 0.5 if the trails clip. One genuinely fun trick: chain this before a Kaleidoscope or Lens Flare stage - light trails are exactly the kind of structured motion those effects love.

CategoryComfyTV/VideoFX

Inputs (8)

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.
thresholdFLOAT0.9000.5–1
sum_thresholdFLOAT2.200–3
decayFLOAT0.0000–1
gainFLOAT1.000.1–4
videooptCOMFYTV_VIDEO

Outputs (1)

NameTypeDescription
videoCOMFYTV_VIDEO