Niutonian: ComfyUI Hue Edge Bar
Your generated image, but it sets the room's lighting
- image
- image
- edge_bar_json
- average_rgb
ComfyUI ships its output into the physical world and, for once, the promise is exactly what the README says it is. Feed this node an image, and it reads the colors along the image's edges and changes your Philips Hue lights to match. No cloud service, no Hue account, no API key from Philips - it talks to your bridge directly over your LAN. The vibes-only part is that it works.
This is the advanced node in the Niutonian_Comfyui_Philips_Hue pack, the full-control version with a knob for everything. If you just want the lights to look good with zero fiddling, the README points you at the "Hue Edge Bar simple" sibling instead. This one is for when you've got taste and the simple node's taste isn't yours.
How it works
There's real machinery here, not a gimmick. The node takes a band of pixels edge_width thick from each side of the image (top, right, bottom, left) and averages each band. Then it splits that perimeter into led_count chunks - default 24 - to build what the author calls a "virtual LED bar": the same thing a physical strip of LEDs behind your monitor would show if it were driven by the image. That's a nice mental model and worth keeping.
From the LED bar it picks a single color using color_pick_mode (average, weighted_average, dominant, or brightest), runs it through saturation and vibrance shaping, decides brightness, and converts RGB to the format the Hue bridge wants. Then it's a plain PUT to the Hue v1 API: /api/{key}/lights/{id}/state for one light, /groups/0/action for all, and /groups/{id}/action for group:<id>. Standard Hue v1 lights take one active color per light, so one color gets sent - the node isn't trying to drive 24 separate bulbs.
The inputs that matter
bridge_ip- the node's default isauto, which scans and picks your bridge. Once you've done setup once, paste the exact IP in (like192.168.1.100);autogets confused with multiple bridges.api_key- leave blank after setup. The node loads the key it saved tohue_config.jsonitself.light_id- the numeric ID from the setup node'slist_lights, orall, orgroup:<id>.mode- note this issend_averageon the advanced node (notsendlike its siblings), pluspreview_onlyandturn_off.color_api-xyby default and generally the better match;hue_satfor older color lights.color_pick_mode-weighted_averageis the sweet spot if colors feel off;dominantgives punchier single-hue results.edge_width- how many pixels of border to sample. Crank it if black image borders are dragging the color toward nothing.ignore_dark_below/ignore_bright_above- filter out near-black and blown-out pixels so a black frame doesn't win.crop_percent,saturation_boost,vibrance, and the four side*_weightinputs - fine-tune what color actually wins.transitiontime- fade time in tenths of a second.6= 0.6s.
Outputs are image (a pass-through, handy for chaining), edge_bar_json (the virtual LED bar plus debug data like raw_rgb vs shaped_rgb), and average_rgb - the final r,g,b string that actually went out.
Installing it
Via ComfyUI Manager, search "Niutonian" and install the pack, or clone it manually:
cd ComfyUI/custom_nodes
git clone https://github.com/Niutonian/Niutonian_Comfyui_Philips_Hue
Restart ComfyUI. That's it - the pack has no requirements.txt and no model downloads; it only needs numpy, which ComfyUI already ships. After install, you still have to do the one-time Hue setup (press the physical bridge button, register a key) with the pack's "Hue Setup" node - that's unavoidable with Hue, not a bug.
Common issues
- "No API key" - run
Niutonian: Hue Setupwithaction = register_newwhile the physical bridge button is pressed, then leaveapi_keyblank. - Colors look gray - black borders from the image padding. Raise
edge_width, or setignore_dark_belowto ~8, or bumpvibrance. - Light doesn't change - check
modeissend_average, the light ID matches, andtest_flashworks from the setup node first. - Too jumpy - increase
transitiontime. The default 0.6s is snappy on purpose.
Keep hue_config.json private - it's the key to your whole Hue setup, and the repo's .gitignore already excludes it.
Inputs (27)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| bridge_ip | STRING | auto | — |
| api_key | STRING | — | |
| light_id | STRING | 1 | — |
| mode | COMBO | send_average | 3 options: send_average, preview_only, turn_off |
| color_pick_modeopt | COMBO | average | 4 options: average, weighted_average, dominant, brightest |
| color_apiopt | COMBO | xy | 2 options: xy, hue_sat |
| light_modeopt | COMBO | auto | 5 options: auto, color_xy, hue_sat, white_temperature, brightness_only |
| brightness_modeopt | COMBO | fixed | 3 options: fixed, from_image, from_image_clamped |
| led_countopt | INT | 241–300 | — |
| edge_widthopt | INT | 321–512 | — |
| crop_percentopt | FLOAT | 0.00–45 | — |
| ignore_dark_belowopt | INT | 00–255 | — |
| ignore_bright_aboveopt | INT | 2550–255 | — |
| brightnessopt | INT | 1801–254 | — |
| min_brightnessopt | INT | 401–254 | — |
| max_brightnessopt | INT | 2201–254 | — |
| saturation_boostopt | FLOAT | 1.150–3 | — |
| min_saturationopt | FLOAT | 00–100 | — |
| max_saturationopt | FLOAT | 1000–100 | — |
| vibranceopt | FLOAT | 0.200–2 | — |
| transitiontimeopt | INT | 60–6000 | — |
| top_weightopt | FLOAT | 1.00–10 | — |
| right_weightopt | FLOAT | 1.00–10 | — |
| bottom_weightopt | FLOAT | 1.00–10 | — |
| left_weightopt | FLOAT | 1.00–10 | — |
| batch_indexopt | INT | 00–999 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| edge_bar_json | STRING | — |
| average_rgb | STRING | — |