BETA: Playlist Manager for Channels (SLM Add-on)

There are a lot of fantastic methods for integrating custom stations into Channels DVR, especially from FAST and similar providers like Pluto, Plex, Tubi, Samsung TV+, ESPN+, NFL+, and plenty more! The problem is, they require a fair bit of maintenance. For instance, there are whole threads and tools dedicated just to keeping track of which stations have been added and removed. And that doesn't even get into the redundancy of when each of these services have the same stations, but you have to decide which one you want to put in your Channel Collection before it inevitably disappears without you knowing it and not realizing you need to put a replacement in its spot. But what if we could make the whole process a little...easier?

Enter Playlist Manager for Channels (BETA), a custom add-on for Stream Link (+Files +Playlists) Manager for Channels!

From a high-level perspective, PLM works on the same premise as SLM. The idea is that there is some piece of content that can come from multiple sources that you have legal access to and it will "assign" which one to use based upon a priority that you set. With SLM, it takes a movie or an episode of a TV show and parses through all the streaming services you have set, sees if it is there, and assigns the appropriate Stream Link. Similarly, with PLM, it takes a "parent" station that you define and parses through all the playlists that you have set, sees if there is a matching "child" station, and assigns the appropriate info to m3u and EPG files that can be integrated into Channels DVR or any other similar tool. Still, this is just the beginning of its capabilities!

NOTE: This is a BETA release, which means there may be bugs, issues, and enhancements to deal with. Feedback is greatly appreciated to address these, and each will be dealt with accordingly. Nevertheless, please be forewarned that some fixes may require a manual intervention on your part to keep using this tool after an update.


Installation
  1. Install Stream Link (+Files +Playlists) Manager for Channels or upgrade to version 2024.10.29.1540 or later.

  2. Go to Settings and scroll down to Advanced / Experimental.

  1. Check the box for Use Playlist Manager and click save. When you do so, a lot of things will become available both in the front-end and the back-end. Most notably, you will now see Playlists (BETA) in the navigation pane.

image


Initialization
  1. Navigating to the Playlists (BETA) area, you will see something like this:

  1. In the navigation pane, select Manage Playlists. Scrolling towards the bottom, you should see the Enter Playlists section, appearing somewhat like this:

  1. Here you can add links to your m3u(s) and corresponding Electronic Program Guide(s) [EPG(s)], giving each one a unique name. Be sure the correct "Stream Format" is selected for dealing with different types of interpretation engines.

  1. You can always modify these after the fact, too, including renaming or removing them with little to no repercussions. However, if you remove all Playlists, it is considered a complete reset of the tool. Additionally, instead of removing, you can just make the playlist "inactive" by unchecking the appropriate box. Otherwise, as shown in the example image, you can add ones with only a m3u and no EPG, especially those that already have Gracenote IDs for guide data. You can even pull the m3u(s) from built-in Channels DVR lists like the ones for HDHR and TVE. Since some stations are both in either of those and on FAST providers, this gives a way to match them together, if desired.

image

  1. As another option, you can upload your own playlists and guide files.

  1. When you upload a file, it is given a link that you can use in the Enter Playlists area above.

  1. As you add each source, they are given a priority. You adjust that value in the Prioritize Playlists section. In the end, PLM will parse through each of these sources in priority order (excluding inactive playlists) to find the matches for individual stations, and this sequence will determine which one to use. For instance, CBS News is available on many providers, but based upon the order shown below, in this example it will take the one from Channels (TVE) over the ones on Plex, Pluto, etc...

image

  1. Back on the Main Page, there is a button called Update Station List. Pressing this will then read through each of the m3u playlists and gather all the stations for your assignment.

image

  1. In a later step, we will discuss automating this to get updates on a daily basis. In the meantime, you should now have a complete list of available stations to work with.


Regular Activity

As shown at the top, PLM will give you the status for each of the stations it finds in the provided m3u(s). "Unassigned" stations are ones that need to be given a "Parent". The Parents themselves are a grouping of the stations that came from the m3u sources.

  1. Navigating to Unassigned Stations and clicking the Expand / Collapse button will show you all the stations (in alphabetical order) that are looking to have a Parent assignment. The only way a station becomes available is if it has been assigned to a Parent. There is no penalty for not assigning a station aside from not being able to see what's new.

  1. To the far right, there is a button called Make Parent. Clicking this will create a new Parent that has the same name as that station and assigns that station as a "Child" to that "Parent". For instance, if we click Make Parent for 00s Replay, we will end up with a new Parent like this in the Parent Stations area:

  1. You also have the option to create and edit parents directly. This can be especially useful when the names provided by the m3u are not clear or specific enough and you want to easily see what they are.

image image

  1. There are also several optional fields to override what may be provided by the child stations. For instance, you may have a Gracenote ID for guide data that was not provided and can plug that in here.

  1. You can even override the default priority order of the Playlists if you have a use case to make a specific source for one particular station be the first choice.

image

  1. As you add Parents through either method or en masse as described below, they become available for direct assignment. For instance, if we take the first 21 Jump Street and click Make Parent, the second one will now have that new Parent as an option for selection.

  1. After doing so, click the Set Parent button to save this selection. The same activity can also be done with the "Ignore" option. This is like the "Hidden" choice in Channels to make a station not available in the final product.

image

  1. You can also make multiple selections at a time and then click the floating Save All button to set each of them. This includes the "Make Parent" option so you can push multiple stations into new Parents all at once.

image

  1. Everything that is set for a station can always be changed and even undone in the Modify Assigned Stations section:

  1. As you make your assignments, the chart on top of the Main Page updates to let you know the status of your stations. "Assigned to Parent" means that a Parent has at least one child and will create a unique station. "Redundant" means that a Parent has additional children (i.e., repeating/same stations) and that they are available if the higher priority option goes away for any reason.

  1. At any time, you can also click the Update m3u(s) and XML EPG(s). This is the process that will parse through all of these parent-child assignments and create the playlists and guide links that you will load into Channels DVR or other tools. It should be noted that when PLM processes a station, if a certain field does not have a value in the higher priority playlist, it will take that field from a lower priority one. For instance, if your preferred playlist does not have a "description", but a lower priority one does, it will get that "description" and make it available in the final output.

image

  1. As before, this process can be automated and is discussed later. At this point, though, you will now have fully active m3u and EPG files that you can integrate. The links will be visible at the top of the page:

  1. "Gracenote" m3u files do not have XML EPG data because the guide information comes from the loaded Gracenote ID. On the other hand, all the "Non-Gracenote" m3u(s) do require their own corresponding XML EPG. Either way, each is split between "HLS" and "MPEG-TS" options since those are interpreted by Channels DVR differently. Also, depending on circumstances described below, you may end up with multiple of these lists.

  1. At this point, you have everything you need and can continue using PLM as a regular function. However, there are several settings and automated routines to consider before proceeding.

Settings and Automation
  1. Back in the Settings area under Advanced / Experimental, at the spot where you turned on PLM, there are two additional inputs. One is the station number you would like to start at, with a default of 10000. Each new Parent that is added will increase this value by one.

image

  1. The other choice is the Max Stations per m3u, with a default of 750. This is the number of stations that will be in an m3u file before it splits into a new file, 750 being the maximum Channels DVR allows at the time of this writing. This can be set to any positive integer. It should be noted the XML EPG data is split by the same stations in the end-result m3u(s).

  2. Further up under the Scheduler section are two more things for you to set. The first is the equivalent of the Update Station List button. Turning this on will run a process once per day at the time you set to update the station list, thus giving you an automated way to handle changes and get new selections in the Unassigned Stations section.

image

  1. When stations are updated, there are notices that are also made available in the Notifications pane in the Home area. You will get info on "Added", "Removed", and "Modified" stations, the latter meaning there has been a change in at least one field of provided data.

image

  1. In the same vein, you can also turn on the process to update the m3u and EPG files at regular intervals.

image

  1. Unlike the updating the station list, this one allows you to make a selection to how frequently you want the action to happen based upon a starting time. For instance, if we leave the time at 02:01 PM and select Every 6 hours, it will run at 02:01 PM, 08:01 PM, 02:01 AM, and 08:01 AM.

image

  1. As with the previous automation, this one will also give you notifications. In all cases, there is additional detail available in the Logs area.

  1. With these in place and set, the process will take care of itself and you should be good to go!

To see a short demonstration, watch the video here:


Known Issues

  • Sometimes, while retrieving an m3u or EPG, PLM will give up after just a few seconds instead of waiting for it to load. It is inconsistent behavior and hard to track down as the same link can work and an hour later not work. It seems particularly prevalent with with Samsung TV+ and, to a lesser extend, DistroTV.

  • When there are a lot of stations (like a thousand), Unassigned/Assigned Stations can take a while to load and may appear like PLM is just spinning its wheels.

1 Like

Dude. . . DUDE!!!! dude. Do you sleep. I haven't tested. But im excited.

1 Like

I see the same problem with Samsung TV+ just using it as intended with Channels.
So far this month (updating playlist/xml hourly)

2024/10/05 12:15:09.694490 [ERR] Unexpected m3u response for SamsungTVPlus: 500 Internal Server Error
2024/10/05 13:15:13.406329 [ERR] Failed to request m3u for SamsungTVPlus: Get "http://192.168.1.3:8182/playlist.m3u8": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
2024/10/07 09:15:11.719993 [ERR] Unexpected m3u response for SamsungTVPlus: 500 Internal Server Error
2024/10/24 11:15:14.031980 [ERR] Failed to request m3u for SamsungTVPlus: Get "http://192.168.1.3:8182/playlist.m3u8": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
2024/10/26 03:15:13.382200 [ERR] Failed to request m3u for SamsungTVPlus: Get "http://192.168.1.3:8182/playlist.m3u8": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
2024/10/26 15:15:13.825703 [ERR] Failed to request m3u for SamsungTVPlus: Get "http://192.168.1.3:8182/playlist.m3u8": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

The container takes too long to respond to Channels which leads to an exception in the container
BrokenPipeError: [Errno 32] Broken pipe

The container log usually looks like this
2024-10-26T22:15:21.774874689Z Including channels from regions: ['us']
2024-10-26T22:15:21.775205252Z 192.168.144.1 - - [26/Oct/2024 15:15:21] "GET /playlist.m3u8 HTTP/1.1" 200 -
2024-10-26T22:15:21.777449328Z 192.168.144.1 - - [26/Oct/2024 15:15:21] "GET /playlist.m3u8 HTTP/1.1" 500 -
2024-10-26T22:15:21.777787699Z ----------------------------------------
2024-10-26T22:15:21.777908451Z Exception occurred during processing of request from ('192.168.144.1', 44480)
2024-10-26T22:15:21.779876350Z Traceback (most recent call last):
2024-10-26T22:15:21.780945769Z   File "/usr/src/app/./app.py", line 48, in do_GET
2024-10-26T22:15:21.781204142Z     routes[func]()
2024-10-26T22:15:21.781378660Z   File "/usr/src/app/./app.py", line 96, in _playlist
2024-10-26T22:15:21.781524574Z     self.wfile.write(f'#EXTINF:-1 channel-id="{channel_id}" tvg-id="{key}" tvg-logo="{logo}" group-title="{group}"{chno},{name}\n{url}\n'.encode('utf8'))
2024-10-26T22:15:21.781676874Z   File "/usr/local/lib/python3.12/socketserver.py", line 840, in write
2024-10-26T22:15:21.781803555Z     self._sock.sendall(b)
2024-10-26T22:15:21.781905473Z BrokenPipeError: [Errno 32] Broken pipe
2024-10-26T22:15:21.782009662Z 
2024-10-26T22:15:21.782094622Z During handling of the above exception, another exception occurred:
2024-10-26T22:15:21.782198372Z 
2024-10-26T22:15:21.782279478Z Traceback (most recent call last):
2024-10-26T22:15:21.782994632Z   File "/usr/local/lib/python3.12/socketserver.py", line 692, in process_request_thread
2024-10-26T22:15:21.783216446Z     self.finish_request(request, client_address)
2024-10-26T22:15:21.783465992Z   File "/usr/local/lib/python3.12/socketserver.py", line 362, in finish_request
2024-10-26T22:15:21.783672885Z     self.RequestHandlerClass(request, client_address, self)
2024-10-26T22:15:21.783819644Z   File "/usr/src/app/./app.py", line 23, in __init__
2024-10-26T22:15:21.783932717Z     super().__init__(*args, **kwargs)
2024-10-26T22:15:21.784028259Z   File "/usr/local/lib/python3.12/socketserver.py", line 761, in __init__
2024-10-26T22:15:21.784128136Z     self.handle()
2024-10-26T22:15:21.784226555Z   File "/usr/local/lib/python3.12/http/server.py", line 436, in handle
2024-10-26T22:15:21.784396009Z     self.handle_one_request()
2024-10-26T22:15:21.784528152Z   File "/usr/local/lib/python3.12/http/server.py", line 424, in handle_one_request
2024-10-26T22:15:21.784892417Z     method()
2024-10-26T22:15:21.785022207Z   File "/usr/src/app/./app.py", line 50, in do_GET
2024-10-26T22:15:21.785133745Z     self._error(e)
2024-10-26T22:15:21.785230833Z   File "/usr/src/app/./app.py", line 27, in _error
2024-10-26T22:15:21.785374280Z     self.end_headers()
2024-10-26T22:15:21.785496450Z   File "/usr/local/lib/python3.12/http/server.py", line 538, in end_headers
2024-10-26T22:15:21.785606428Z     self.flush_headers()
2024-10-26T22:15:21.785697012Z   File "/usr/local/lib/python3.12/http/server.py", line 542, in flush_headers
2024-10-26T22:15:21.785800081Z     self.wfile.write(b"".join(self._headers_buffer))
2024-10-26T22:15:21.785899353Z   File "/usr/local/lib/python3.12/socketserver.py", line 840, in write
2024-10-26T22:15:21.785999264Z     self._sock.sendall(b)
2024-10-26T22:15:21.786087818Z BrokenPipeError: [Errno 32] Broken pipe
2024-10-26T22:15:21.786179593Z ----------------------------------------

This is... WOW !!

:exploding_head: :astonished:

Oh yes. This is gonna be very, very useful for the FAST sources. A lot of the same channels are found there so I may have a use case for this :rofl::joy:

This seems like it'll be phenomenal!

...That said, I can't for the life of me seem to get it working. Each playlist I try gives me the same message. For example, when I tried the PBS bridge:
WARNING: m3u URL not found for 'PBS'. Skipping...

I've yet to have a single m3u work so far. I'm copying the playlist links directly to add them in, so I'm not quite sure what to do if I want to actually experience any of this. Any help would be greatly appreciated.

I'm getting the same warning message with all the sources I added.

2024-10-29 22:50:17.984083:  Starting combination of playlists...
[DEBUG | 2024-10-29 22:50:17,992] - Starting new HTTP connection (1): 127.0.0.1:8089

2024-10-29 22:50:17.994250:  WARNING: m3u URL not found for 'DirecTV (TVE)'. Skipping...
[DEBUG | 2024-10-29 22:50:17,995] - Starting new HTTP connection (1): 127.0.0.1:8089

2024-10-29 22:50:17.995509:  WARNING: m3u URL not found for 'EPlusTV (Linear Channels)'. Skipping...
[DEBUG | 2024-10-29 22:50:17,995] - Starting new HTTP connection (1): 127.0.0.1:8089

2024-10-29 22:50:17.996207:  WARNING: m3u URL not found for 'Frndly TV (Gracenote EPG)'. Skipping...
[DEBUG | 2024-10-29 22:50:17,997] - Starting new HTTP connection (1): 127.0.0.1:8089

2024-10-29 22:50:17.997295:  WARNING: m3u URL not found for 'Frndly TV (No Gracenote)'. Skipping...
[DEBUG | 2024-10-29 22:50:17,997] - Starting new HTTP connection (1): 127.0.0.1:8089

2024-10-29 22:50:17.997831:  WARNING: m3u URL not found for 'PBS (VLC Bridge)'. Skipping...

2024-10-29 22:50:17.997856:  WARNING: No data to compare, skipping adding and removing rows in PlaylistManager_Combinedm3us.csv.


2024-10-29 22:50:17.997956:  Finished combination of playlists.

FYI, for each source, I got the URLs from Settings > Sources:

Change the first part of the URL to have your local IP, not the remote access one.

That would be http://localhost:port/
or
http://<serverIP>:port/

These are working for me:

This is a phenomenal development. Thanks once again @babsonnexus. You're the real MVP!