Dude. . . DUDE!!!! dude. Do you sleep. I haven't tested. But im excited.
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 ----------------------------------------
See my post in Samsung TV Plus for Channels - #35 by chDVRuser
This is... WOW !!

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 

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!
This fixed my issue! Turns out I needed to switch from using "localhost" to "[computer-name].local".
First, awesome job!
Second, what would be the best way to handle this scenario. I have 4 HDHR's, TVE, and Frndly. I prefer stations like metv and mvies on Frndly because they are higher quality than OTA. Right now i put all of the ota stations i want to keep and the frndly replacements in a channel collection. The problem (or annoyance) is that the channels go like 4.1, 4.2, 5592, 4.4, 5388 etc. I am loving the prospect of using this tool to renumber some of my channels easily and use the OTA equivalent as a backup. However, I'm not grasping how to use this with OTA and TVE. Would i just need an intermediate Channels server that would house my 4 HDHR's and TVE, then that would feed my main Channels server via m3u? Then the only source in my main DVR would be the PLM playlists?
Im just not grasping how to do this without a middleware DVR (which is no problem)
Another thing that might work is this:
Just use host.docker.internal in place of localhost, the machine name, or IP address. You can also use the the Test button in the Channels URL setting and make sure the link works first. Shouldn't harm anything unless you click Save!
For anything that Channels doesn't create innately (i.e., OTA, TVE), I'd just use the direct links you are already putting in. Like for the EPlusTV (Linear Channels), I'd just use the same links in PLM as what you put in Channels; Channels doesn't have to be the middleman for everything.
The end-goal is to only need to put PLM links into Channels, so those other ones should go away. Obviously, I'm not there yet, either, but damn close!
Here's what I'm thinking:
-
Get the 4 HDHR and TVE links from your main Channels setup
-
Get the Frndly links directly from that container
-
Make sure METV and MVIES are not clicked as favorites for the OTA and TVE
-
In PLM, create a Parent for each version you want to keep. So "METV (Frndly)", "METV (TVE)", "METV (4.1)", etc... and assign the children accordingly
-
If you create them in order or preference, by default they will end up with Channel numbers in that order. So, if those I listed above were the 12th, 13th, and 14th parents you created, and you kept the default starting station number of 10000, they would be 10012, 10013, 10014.
-
Conversely, you could manually assign them any number in any order you want
-
Either way, put your favorite in Channels on the PLM Frndly one so it will be the default for recording
-
Also make the PLM source higher priority than all the other sources in Channels.
-
These actions combined together should be able to get you the order you want to see. So you'll end up with something like 10012, 100013, 10014, 4.1, 4.2, 5592, etc...
Just a heads up, too, with Channels-based OTA and TVE stations (or any stations that you pull the playlists from Channels): when you run a PLM station, it will also run the equivalent Channels station. So for me, if I tune to this PLM station:
![]()
Channels also tunes to the internal HDHR station:

For that reason and that reason alone, I might consider setting up an intermediate Channels server so it is not pulling double-duty while watching/recording. I'm also thinking about pulling my HDHR directly and doing the Gracenote mapping function.
I've been messing with PLM...and yeah...I got a lot of channels in there and it's sluggish. Tough to mass ignore a lot of the channels I don't want. I wonder if it's just the limitation of python... 
I second that, this sound very interesting.
This is an amazing, gamechanger of a utiliity. It will take me awhile to get there, but I'm going through a combined list of about 2000 FAST channels and hope to end up with tight, clean list.
My first question is about channels that I only have a single version of. They are "unassigned" by default, and therefore aren't included in the final output, along with any I've "ignored." So do I need to make each of those a "parent" too (but without any child versions) to include them in the final list? Is there an easier way to handle this? I'm scrolling for duplicates and triplicates but there are also hundreds that are singles so making them all childless parents doesn't seem like the best answer here. Am I wrong?
I also have three "quality of life" improvements that I think would make this curation a lot easier.
-
with the channels that have descriptions, the field is so small that I can only read the first 4-5 words. A pop-up that reveals the entire description when hovering or clicking, would be greatly appreciated
-
How about a search/filter field, so we can type a few characters like "21 jump" to quickly see the channels that match?
3). when I am clicking "make parent" it refreshes the page and then brings me back up to the top of the page, then I have to scroll down and find the children to assign. This would be a lot easier if the scroll position persisted we could continue with the assignments, and not have to scroll down all the way down back to where we just were.
Thanks again for this fantastic and thoughtful utility. It’ll supercharge and streamline the Channels interface with our previously-overwhelming list of available channels, allowing us to “clean it up” in a way I hadn't conceived possible. It’ll certainly make selecting what to watch when channel surfing easier too!
This seems pretty awesome, just trying to get my head around it. Would it be accurate to think of "Playlist Manager" as a list of what Channels DVR currently refers to as "Sources?"
Most likely not the Python because it's returning what's necessary in microseconds, but really the html/javascript, or at least how I'm using it. I probably need to invest some time into lazy/partial loading so it doesn't try to render all several thousand cells at once and just does them in batches of 100 or something. There was an earlier version where everything was one page instead of four and it took forever to load. Separating them made the pages without thousands comes back pretty instant. In the background, though, the Python is preparing all the PLM pages at once, so I'm quite confident its on the html-side.
Yes, Parents are the the final list of stations, so they need at least one child to show up. When you are going through the list, just choose the Make Parent option on those single ones:

The new Parent will be created and the child will be assigned to that Parent. You can do that en masse, so just do all hundreds of them at once and you'll be all set!
Just a heads up that you can click into them and scroll over.

But I'll look into being able to put pop-up hovers on all fields like this. Could be good on the SLM side, too!
Maybe... this isn't a table (even though it looks like one), so not as easy, but might be a possibility.
Hmmmm... dynamic anchoring, sounds tricky...
It would be more accurate to say that PLM is a "Custom Channels" "Source" for Channels DVR, but as a replacement from needing to have many disconnected "Sources" to only having one or a few streamlined integrated "Sources".
I noticed in the YouTube video that you had brought Channels (OTA) into PLM as a "custom channel" as you call it. Does that preclude having the HDHR OTA tuner as a standard source in the Channels DVR server setup? Does that basically mean that there are no "sources" at all in the standard Channels DVR server setup?




