2020/08/25/The Plex API

From Woozle Writes Code
Jump to navigation Jump to search
Codeblog

Background

We've been watching a lot of video content lately, here at Hypertwin Manor, using Plex -- a web service which lets individuals offer libraries of media for remote streaming.

One recurring problem has been that the bandwidth between our network and the remote server is, somehow, often inadequate, and videos will freeze and "buffer" (wait for a certain amount of material to be received before attempting to resume playing) for anywhere between seconds and minutes at a time. More than once, we've ended up taking a whole hour to watch a half-hour video, or abandoning the session altogether because watching video in 2-second increments with 5-minute gaps just isn't very enjoyable.

The obvious solution is to download the next video beforehand -- but Plex's web interface, at least, does not offer this option.

So I've been trying to figure out how to talk to the Plex server directly from code, so that I can download things ahead of time. (Also, their web UI is kind of awful in a lot of ways -- even though it's much better than the Roku, which was omgterrible -- and it would be nice not to have to deal with that.)

The API is, however, not officially documented, so I'm having to rely on other people's reverse-engineering -- which is often incomplete, not well explained, and may be out of date.

Progress So Far

Using Arcanemagus's API documentation, I've been able to log in with our account credentials and obtain an authorization token. Yay! Basically you send a bunch of specific X-Plex- data to https://plex.tv/users/sign_in.xml via POST, and you get back a wodge of XML which includes the auth code.

The problem now is, how do I use that token to get information about what's available?

According to Arcanemagus, there are then a dozen or so URLs at which further information can be obtained if one is logged on ("Must be logged in (web/cookie) or pass basic auth") -- but the docs don't say what information you need to pass in order to establish that you're logged in, much less how to do so. Presumably the auth code should be used -- but what's the key name? Should it be passed via POST, GET, cookie? Is anything else needed?

So I tried a few obvious things on the first item in the list, https://plex.tv/devices.xml -- but I always get an HTTP 404 error. I'm pretty sure that the URL is correct, though, because when I access it from a logged-in browser I get this other wodge of XML -- where the information returned for the device "hypertwins.org/SamEagle" matches the POST data I sent, and the "token" value matches the auth code I got back from logging in (while the "token"s for the other devices do not).

I do see some references to a session ID, but I think that must happen when the client connects to the media server; the login output XML doesn't include anything with the word "session" in it.

Leads

As well as Arcanemagus's links, I have a couple of code examples to look at:

  • Plex-API, a PHP wrapper
    • For reverse-engineering: it seems to assume you know the remote server's IP address, and can connect directly. I could probably ask the server's owner for the IP address via social media, but what if it changes? It seems to me I should be able to get that information from the Plex home server before attempting a connection. Also, there may be other servers I'll want to download from. I don't want to spend the time getting this link in the chain working if I can't be sure of being able to reach it reliably first.
  • plexdownloader, a Python interactive script
    • For use as a downloader utility: It works until I get to the point of telling it to start downloading, and then it crashes.
      • ...and loses everything I've entered, so I have to start over in order to try again. And I really have no idea how to fix it.
    • For reverse-engineering: The problem is (a) I don't know Python, so I'm having to guess at a lot; (b) it seems to use some external library somewhere for a lot of the actual Plex interaction.

I'm kinda reaching the point of diminishing returns on this -- so I'm probably going to drop it until/unless more leads come in, or some brilliant idea hits me. I did consider using Wireshark to see what the web client sends, but... diminishing returns, and this is holding up other more urgent projects.