A Plex Media Server update released earlier this year introduced a new webhook API that exposes media playback events, making it possible to track when Plex starts and stops playing content. I used the API to make my living room lights dim automatically when I’m watching a movie or television show.
To use the API, you create a simple web application that receives HTTP POST requests at a given URL endpoint. If you add the URL to Plex’s webhook configuration panel, it sends a POST request every time an event occurs. At the present time, the events that it sends are: play, pause, resume, stop, scrobble, and rate.
I built my webhook receiver in JavaScript with Node.js. I didn’t need to use a framework or routing library because the application only has one URL endpoint. In the request handler, I check the event type and perform the corresponding Hue API request:
const http = require("http");
const {IncomingForm} = require("formidable");
const hueGroup = 1;
const hueAddress = "...";
const hueToken = "...";
const plexPlayer = "...";
const server = http.createServer((req, res) => {
if (req.url !== "/plex" || req.method !== "POST") {
res.writeHead(404, {"Content-Type": "text/plain"});
return res.end("404");
}
res.end();
let form = new IncomingForm();
form.parse(req, (err, {payload}) => {
let {event, Player} = JSON.parse(payload);
if (Player.title !== plexPlayer) return;
let bri = ["media.stop", "media.pause"].includes(event) ? 200 :
["media.play", "media.resume"].includes(event) ? 5 : null;
if (!bri) return;
let request = http.request({
method: "put", hostname: hueAddress, port: 80,
path: `/api/${hueToken}/groups/${hueGroup}/action`
});
request.on("error", err => console.log(err));
request.write(JSON.stringify({bri}));
request.end();
});
});
server.listen(8000, () => console.log("Running Webhook Server"));
If you use the code above, be sure to fill in the four hard-coded constants:
hueAddress
is the local network IP address of the Hue base stationhueToken
is the authentication token that you include in the URL for Hue requestshueGroup
is the light group that you want to change in response to Plex eventsplexPlayer
is the name of the individual Plex client device that you want to monitor
Filtering for the specific Plex client is important, because I only want playback on my living room television to affect the living room lights. The only dependency in this example is formidable
, which I use for parsing the request body.
I’ve had this integration running for about a week. There appear to be some edge cases where Plex doesn’t emit an event when playback stops. Aside from that issue, it’s working very well.