Jellyfin Hue

active · since 2026

A Jellyfin plugin that drives Philips Hue lights from playback: the room goes dark when the film starts, warms back up on pause, and returns to how it was on stop.

stack
  • ▸C# / .NET 10
  • ▸Jellyfin 10.11+ / 12+ plugin
  • ▸Hue CLIP v2 API, local HTTPS
  • ▸HTML/JS config page in the dashboard
  • ▸xUnit, Moq
  • ▸GitHub Actions (tests, CodeQL, releases)
links

What it does

The film starts, the room fades down to whatever level you picked, or all the way to black. You pause, a warm light comes back up gently, enough to get up without hitting anything. You resume, it goes back down. You stop, and everything returns to the state it was in, or switches to ambient lighting, your call.

The rest is filtering, because one rule for the whole house isn't enough. A profile targets Jellyfin users, devices or client apps (the living room TV, the bedroom Apple TV), a media type (movies, shows, nothing else) and a time range, so nothing fires in the middle of the afternoon. Create as many as you have rooms or people.

On the Hue side it drives a room, a zone or a single lamp, and it handles colour bulbs, tunable whites and fixed whites, sending each one only the fields it accepts. A test button sends the transition for real to the targeted lamps, so you don't have to start a film to check.

Pairing stays in the dashboard: auto-discover the bridge, press its physical button, and the key is stored.

How it's built

A .NET 10 DLL hooked onto the server's playback events, a configuration page served in the dashboard, and a small API controller for what that page needs to ask for (the bridge's rooms, pairing, tests). Everything goes over CLIP v2, HTTPS on the local network, without going through the Hue cloud.

The part that took the most care is colour and state restoration. Hue doesn't think in RGB but in xy coordinates and colour temperature, and not every bulb accepts the same fields: sending a colour to a white bulb is an error, not an approximation. And "put it back how it was" means reading and storing each lamp's state before touching it, otherwise all you can do is switch everything back on at 100%.

An xUnit suite covers the orchestration, the colour conversion and the bridge client, with HTTP calls replaced by canned responses, so the tests run with no bridge in the room.

Why

I wanted the living room to behave like a cinema. That already exists, but as an external automation that has to guess what the player is doing. A plugin installed in the server has nothing to guess: it gets the event when playback starts, stops or resumes.

And as with Jellyfin BetaSeries , I have never written a line of .NET: I wrote the specs, an LLM wrote the code, and I read it, corrected it and asked again until it worked. This was the second one, so the specs were more complete from the start, especially on the cases where the plugin should refuse to act rather than pick for me.

← back to projects