WORK IN PROGRESS
Don't merge yet without strong confirmation that this is indeed working correctly. As mentioned in #4934, one of the mid-rolls I encountered resulted in the filtering not stopping. I don't know why, because I didn't run trace logs at the time. It's possible though that the streamer simply forgot to turn off ads. I'm saying that, because the last 8 mid-rolls or so I had on other channels were properly filtered out and the stream continued fine afterwards, hence why I'm opening this PR now. The added test fails without the modification made to the TwitchM3U8Parser. The test is derived from data I gathered earlier today.
DEBUGGING
Please apply the following diff first when testing this PR/branch and then set --loglevel=trace and --logfile=/path/to/file.log (remove the file first before running streamlink, because the log gets appended). Knowing the content of the HLS playlist when mid-roll ads occur is important, because there are lots of variations that need to be covered.
diff --git a/src/streamlink/stream/hls_playlist.py b/src/streamlink/stream/hls_playlist.py index 9f193d80..633bec54 100644 --- a/src/streamlink/stream/hls_playlist.py +++ b/src/streamlink/stream/hls_playlist.py @@ -550,6 +550,7 @@ class M3U8Parser: parse_line = self.parse_line for line in lines: + log.trace(line) # type: ignore[attr-defined] parse_line(line) # Associate Media entries with each Playlist
Btw, the branch of this PR is different from the one I posted in #4934, because I had to refactor stuff.
As explained in #4934, the issue was that when cloning the last regular segment in the playlist for generating a prefetch segment from the provided prefetch URL, timestamps were not updated. Twitch now includes ads in the prefetch data and fortunately, they include proper dateranges which can be used for filtering those prefetch ads. The bad news is that prefetch data only consists of a URL, so the program date time of the cloned prefetch segment needs to be calculated from the program date time of the last segment with its duration added to it. Since there's more than one prefetch segments, this may be an issue, but it will most likely be fine.
In #4106 I've explained that an alternative solution would be strictly caching the prefetch data and not shifting the live-edge of the HLS stream. Then all the metadata of the regular segments would always be available. However, this adds more delay, because the playlist needs to be refreshed during the runtime of the latest segment, which is two seconds.