Skip to content

Conversation

@bastimeyer
Copy link
Member

@bastimeyer bastimeyer commented Sep 30, 2020

As mentioned in #3210 (comment), simply filtering ads by comparing each segment's title isn't good enough anymore and checking for the title not being equal to "live" can break the implementation if Twitch decides to change the title of live stream segments or if they decide to add titles to VOD segments.

So here's a better filtering approach, based on the EXT-X-DATERANGE and EXT-X-PROGRAM-DATE-TIME tags.

Example playlists can be found here:


Basic description of each commit:

  1. Adds the EXT-X-DATERANGE tag to the HLS playlist parser and makes the EXT-X-PROGRAM-DATE-TIME tag return a datetime object instead of a string. Since I couldn't find any usage of the EXT-X-PROGRAM-DATE-TIME tag in the existing code, changing its return value should be fine. Also adds support for returning a custom M3U8 class by the parser and adds a is_date_in_daterange method to the existing M3U8 class. This isn't an ideal solution, but I couldn't find a better place for this method so that it can be called when parsing is done apart from turning the Segment namedtuple into a regular class. Also worth to note is that I haven't implemented all possible attribute values of the EXT-X-DATERANGE tag, because I didn't need them (scte35 attributes).

  2. Makes the Twitch plugin filter the parsed dateranges by attributes. It tries to find "ad dateranges" by the values of the ID and CLASS attributes and key names of custom attributes by Twitch. This is the crucial part of the ad detection. If a segment is then part of this daterange, it is marked as an ad and filtered out by the existing methods.


I've added tests for all "ad daterange" values I know of, but since I still don't get any ads by Twitch, it's hard to know if my implementation is working correctly. So please go ahead and test this on live data. Thank you!

@gravyboat
Copy link
Member

gravyboat commented Sep 30, 2020

I'm still seeing the following error from a random "big" stream pulled off twitch:

[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.8.4
[cli][debug] Streamlink: 1.4.1+106.gb763839
[cli][debug] Requests(2.24.0), Socks(1.7.1), Websocket(0.57.0)
[cli][info] Found matching plugin twitch for URL twitch.tv/ludwig
[cli][debug] Plugin specific arguments:
[cli][debug]  --twitch-disable-ads=True (disable_ads)
[cli][debug]  --twitch-low-latency=True (low_latency)
[plugin.twitch][debug] Getting live HLS streams for ludwig
[utils.l10n][debug] Language code: en_US
[cli][info] Available streams: audio_only, 160p (worst), 360p, 480p, 720p, 720p60, 1080p60 (best)
[cli][info] Opening stream: 1080p60 (hls)
[plugin.twitch][info] Will skip ad segments
[plugin.twitch][info] Low latency streaming (HLS live edge: 2)
[stream.hls][debug] Reloading playlist
[cli][error] Try 1/1: Could not open stream <HLSStream('https://video-weaver.sea01.hls.ttvnw.net/v1/playlist/CvYDDa8jpsj0O4WIuxVoyqoFIsNEiviJF8kXq3hUYyg64iYDqWQJDhL7oYZ6yXrR3uspl3W0OnTNamBOQyJsO9PBATuRSGNP4Xwti83CN80DPz8btENMIa2DlLrlt5hVpHZZJsqifMBSPaBUT_hN7RfPwTSJw0J6qn-8qkT-IyMDi4MOXfdoWTMBMj92IxaHzWNfvsBNBmWZ339jjFSvOUnef_LmYyfAbNuvLY4M5uYvg6pZT1duvaX5inBuRXBgoMzDfcTpkzZuKoo1f7wuq7iEObzoWCgKpEJXtf8iKrbZQWoW3D2KyLMQAWDHTysf58m4ncA7VeF4dCok11OxO3w3klOlisk4NZxWyRfqzf2yjKnIHxWsxB2GFXGUP5kxGrCFGipO0qb5ISfXAiPf_FlXzpZOaOyeyMiPvgfYg6ryFvX13PZ-7PSXPuwn19A2ytPo4W1DyW2gsveKwRp_B5lahBpyBwYvbFdi2jVqWwFAzqHKipb9J1YAxJvFvfLj1ZCsy6dptorPXeF1p6VmPvSwJVOEW0VbrT_sbkIAQnMEoEUft-SERUAZ_xmOOxyUlcwpE3rtNBEg4OlNFCOEa38aJbGqPg5LsKG2LeqTxc-uOBGmRwUwrEkkp6uxGgKbDii26YkzJ20Cv0ACuC6k-wZ68_ep6JyaBRIQkzv9Y1XKKEIWC_nNvJ7j1hoMBlUQEp8X74lZfI9_.m3u8')> (Could not open stream: invalid literal for int() with base 10: '15.183')
error: Could not open stream <HLSStream('https://video-weaver.sea01.hls.ttvnw.net/v1/playlist/CvYDDa8jpsj0O4WIuxVoyqoFIsNEiviJF8kXq3hUYyg64iYDqWQJDhL7oYZ6yXrR3uspl3W0OnTNamBOQyJsO9PBATuRSGNP4Xwti83CN80DPz8btENMIa2DlLrlt5hVpHZZJsqifMBSPaBUT_hN7RfPwTSJw0J6qn-8qkT-IyMDi4MOXfdoWTMBMj92IxaHzWNfvsBNBmWZ339jjFSvOUnef_LmYyfAbNuvLY4M5uYvg6pZT1duvaX5inBuRXBgoMzDfcTpkzZuKoo1f7wuq7iEObzoWCgKpEJXtf8iKrbZQWoW3D2KyLMQAWDHTysf58m4ncA7VeF4dCok11OxO3w3klOlisk4NZxWyRfqzf2yjKnIHxWsxB2GFXGUP5kxGrCFGipO0qb5ISfXAiPf_FlXzpZOaOyeyMiPvgfYg6ryFvX13PZ-7PSXPuwn19A2ytPo4W1DyW2gsveKwRp_B5lahBpyBwYvbFdi2jVqWwFAzqHKipb9J1YAxJvFvfLj1ZCsy6dptorPXeF1p6VmPvSwJVOEW0VbrT_sbkIAQnMEoEUft-SERUAZ_xmOOxyUlcwpE3rtNBEg4OlNFCOEa38aJbGqPg5LsKG2LeqTxc-uOBGmRwUwrEkkp6uxGgKbDii26YkzJ20Cv0ACuC6k-wZ68_ep6JyaBRIQkzv9Y1XKKEIWC_nNvJ7j1hoMBlUQEp8X74lZfI9_.m3u8')>, tried 1 times, exiting

@Billy2011
Copy link
Contributor

Every answer to any question about this I've found is "use python-dateutil", but I can't just add a dependency here, so a custom parser had to be written

Why don’t you use the isodate module for parsing, which is also used for the dash manifest parser?

@azizLIGHT
Copy link
Contributor

azizLIGHT commented Sep 30, 2020

I'm getting same errors as gravyboat, but it did work once (line 62) but I might be doing this wrong but here's my output. Let me know if I should adjust something: https://gist.github.com/azizLIGHT/0fce5e83961a007fbae03dbd39eb6a0b

@bastimeyer bastimeyer force-pushed the plugins/twitch/embedded-ads-2020-09-29 branch from 40af3f4 to f02d419 Compare September 30, 2020 15:02
@bastimeyer
Copy link
Member Author

@Billy2011 Thanks... Don't ask how I've missed that. 😞
@azizLIGHT Regarding the error, you could try it again with the new changes. I will check this later, since I have to go now.

@azizLIGHT
Copy link
Contributor

@azizLIGHT Regarding the error, you could try it again with the new changes. I will check this later, since I have to go now.

I got the latest version and tried again but got same errors about Could not open stream <HLSStream.
I will try again when there's more changes added

And add support for the parser to return a custom M3U8 class
@bastimeyer bastimeyer force-pushed the plugins/twitch/embedded-ads-2020-09-29 branch from f02d419 to c907c73 Compare September 30, 2020 15:54
@bastimeyer bastimeyer added the plugin enhancement A new feature for a working Plugin label Sep 30, 2020
@gravyboat
Copy link
Member

gravyboat commented Sep 30, 2020

@bastimeyer Most recent changes look good on a quick test. I get the pre-roll notification on the CLI then the stream opens correctly once they're done.

@gravyboat
Copy link
Member

@bastimeyer Yes there anything else you want to add here? Otherwise I want to squash and merge.

@bastimeyer
Copy link
Member Author

anything else you want to add here?

No, that should be pretty much it. As said in the OP, some tag attributes haven't been implemented, but that doesn't matter.

One thing to note though is that I've also ignored the END-ON-NEXT attribute in the is_date_in_daterange method, which technically isn't 100% correct. That attribute basically says that if there's a second daterange with the same class name as the first one and that second one starts later than the first one, the first one ends at the start of the second one, regardless its own end or duration attributes. For filtering out ads on Twitch, this isn't a problem, because it doesn't matter which ad-daterange (of a similar kind) a segment is in if they overlap.

But before merging, I would prefer if we could get some feedback from other users as well, because I still don't get ads on Twitch from my IP address and have basically implemented something purely on the HLS spec and the reported playlist contents, and therefore don't know if I have missed anything in regards to the ad-daterange detection.
https://github.com/streamlink/streamlink/pull/3213/files#diff-195bebeb65dac1f6a8e94f1957a95ec1R143-R147

I want to squash and merge

Don't squash. Both commits change two different components and therefore shouldn't be squashed (and they also have proper commit messages). Either rebase onto master or create a merge commit.

@bastimeyer bastimeyer force-pushed the plugins/twitch/embedded-ads-2020-09-29 branch from c907c73 to 6f89477 Compare October 1, 2020 21:50
@bastimeyer
Copy link
Member Author

bastimeyer commented Oct 3, 2020

@gravyboat I think we can merge this. Should be fine. Don't squash (two commits affecting two different components)

@gravyboat gravyboat merged commit 6525762 into streamlink:master Oct 3, 2020
@bastimeyer bastimeyer deleted the plugins/twitch/embedded-ads-2020-09-29 branch January 19, 2021 23:21
snorkelopstesting2-coder pushed a commit to snorkel-marlin-repos/streamlink_streamlink_pr_3213_1bb44f03-ae5c-495c-adca-c722ede50178 that referenced this pull request Oct 22, 2025
snorkelopstesting3-bot added a commit to snorkel-marlin-repos/streamlink_streamlink_pr_3213_1bb44f03-ae5c-495c-adca-c722ede50178 that referenced this pull request Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

plugin enhancement A new feature for a working Plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants