Server Version#: 1.42.2.10102
Player Version#: N/A
Tuner Make/Model: HDHomeRun
Guide/Lineup name: N/A
Using XMLTV?: Yes
Channel number/Name: N/A
Browser: Chrome-ish
Environment: Unraid/Docker (plexinc/pms-docker)
The Problem
I had issues when adding a medium-large EPG for a given channel lineup (~350 Channels). The EPG was supplied via XMLTV, and every channel has a mapping configured.
When trying to save the EPG/mapping, an error would show up: “There was a problem saving your DVR. Please try again.”
Looking at the network requests, I was seeing a preflight/CORS error, but at a glance, the more likely issue seemed to be that the EPG Mapping request (PUT media/grabbers/devices/##/channelmap) was using too large a query string for either the browser or webserver.
The URI that Plex builds up looks something like this:
PUT https://<ip>.<hash>.plex.direct:<port>/media/grabbers/devices/35/channelmap?channelsEnabled=WGBH.us%2CWCVB.us%2CWBZ.us%2CWBTS.us…&channelMappingByKey%5BWGBH.us%5D=WGBH.us&channelMapping%5BWGBH.us%5D=123&channelMappingByKey%5BWCVB.us%5D=WCVB.us&channelMapping%5BWCVB.us%5D=234&channelMappingByKey%5BWBZ.us%5D=WBZ.us&channelMapping%5BWBZ.us%5D=456&channelMappingByKey%5BWBTS.us%5D=WBTS.us&channelMapping%5BWBTS.us%5D=567
The above example is for just four channels, and you can see how the URL is already quickly growing long. In total, the PUT request for my full ~350 channel playlist was 32839 characters long. At that point, either Plex or its webserver chokes on such a massive URL, and fails to add any mappings at all.
The Workaround
There’s a few ways to work around this issue until a fix is released.
1: Live with less channels
If you add less channels, the requests will go through. If you’re experiencing this issue, try adding one channel, and then adding more after that.
If you saw the “error saving your DVR” message and it was due to the EPG mapping being too large, this won’t solve you getting your full EPG-- the request to update EPG mappings will always include every channel mapped, not just the new ones. This means that you will eventually reach the ‘cap’ of how many channels you can add, and then you will need to choose which channels to ignore or keep. To ‘forget’ a channel and make room for another, just un-tick the box next to a channel, so that it is no longer mapped to the EPG.
This solution gets you somewhere, but it still isn’t great, since you’re settling with a sacrifice.
The ‘cap’ for how many channels you can enable isn’t a set number, since it depends on the length of each of your channel/EPG IDs, since those determine the length of your total EPG mapping request.
2: Make your Channel and EPG IDs shorter
Because the issue is the overall length of the EPG mapping request, if you can make that request shorter, then you can keep more channels overall!
I use open-source middleware (called m3u-editor) that allows me to re-map my EPG’s channel names and IDs. Whether you use this or any other tool that lets you change channel IDs in your EPG, you can make it work.
I changed all of my outputted channel IDs from their original values (WGBH.us, WBTS.us, etc) to shortened values; (AA, AB, etc). With the shorter values, the full mapping URL was 22104 characters. Still massive, but about a third smaller than our original EPG mapping request. It worked!
This solution doesn’t scale forever, and some quick math says it would stop working around 500 channels, but for my case, this was enough to get around the issue.
As a bonus, Plex seemed to do much better at matching the shortened channel IDs. My guess is that this is because Levenshtein works great on equal-length keys (AA/AB/AC/etc were all just 2 characters), whereas previously Plex did some gnarly similarity matching (I think it scores with Levenshtein, but it doesn’t consider length and also scores in sort-order of channels. I have a lot of concerns with the XMLTV scoring system, but that’s best for another post).
Plex Devs: For the XMLTV similarity match, could you consider the following?
A similarity scoring system that values both length and edit distance
similarity_score = 1 - damerau(a, b) / max(lenA, lenB)
(where ‘damerau’ is the Damerau-Levenshtein distance.)
- Calculate the similarity score between each Channel and every [remaining] EPG candidate
- Map the channel with the highest similarity-score to the corresponding EPG candidate
- Remove that mapped EPG entry from the available set of candidates. (Since EPG entires can only be mapped 1:1 with Channels)
- Repeat step 1, until we run out of Channels or EPG options.
There are more efficient ways to handle that loop, but the logic should be roughly the same.
Also, check out Jaro-Winkler distances, those may work well for the typical Channel and EPG naming formats.
The Solution
To really fix this issue, the PUT request to media/grabbers/devices/##/channelmap should be using a request body rather than stuffing it all in the query string.
It’s simple, it’s clean, and it’s best practice.