While I really like this library there's still some functionality missing regarding the #EXT-X tags:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:5
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TWITCH-ELAPSED-SECS:39768.000
#EXT-X-TWITCH-TOTAL-SECS:39774.006
#EXT-X-START:TIME-OFFSET=0.000
#EXT-X-DATERANGE:ID="playlist-creation-1761228882",CLASS="timestamp",START-DATE="2025-10-23T14:14:42.893Z",END-ON-NEXT=YES,X-SERVER-TIME="1761228882.89"
#EXT-X-DATERANGE:ID="playlist-session-1761228882",CLASS="twitch-session",START-DATE="2025-10-23T14:14:42.893Z",END-ON-NEXT=YES,X-TV-TWITCH-SESSIONID="343209999999179748"
#EXT-X-DATERANGE:ID="stitched-ad-1761228876-15049949993",CLASS="twitch-stitched-ad",START-DATE="2025-10-23T14:14:36.102Z",DURATION=15.050,X-TV-TWITCH-AD-ADVERTISER-ID="5778044420701",X-TV-TWITCH-AD-CLICK-TRACKING-URL="https://example.com",X-TV-TWITCH-AD-AD-FORMAT="standard_video_ad",X-TV-TWITCH-AD-DSA-SS-CONTEXT="false",X-TV-TWITCH-AD-AF-ICR-CREATIVE-ID="2474283100401",X-TV-TWITCH-AD-AF-ICR-MEDIA-DURATION="14",X-TV-TWITCH-AD-CLICK-BEACON-ID="clickc8e1d76b-e410-4d1f-9bd0-e96cf832a459_fake",X-TV-TWITCH-AD-DSA-VERSION="0",X-TV-TWITCH-AD-LOUDNESS="-90.000000",X-TV-TWITCH-AD-POD-POSITION="0",X-TV-TWITCH-AD-RADS-TOKEN="...",X-TV-TWITCH-AD-CREATIVE-ID="2474283100401",X-TV-TWITCH-AD-ORDER-ID="7351234567890",X-TV-TWITCH-AD-DSA-SS-LOCATION="false",X-TV-TWITCH-AD-POD-LENGTH="1",X-TV-TWITCH-AD-POD-FILLED-DURATION="14",X-TV-TWITCH-AD-ROLL-TYPE="PREROLL",X-TV-TWITCH-AD-AD-SESSION-ID="4ed4333bb524458cb09fb83a588d8208",X-TV-TWITCH-AD-URL="https://help.twitch.tv/",X-TV-TWITCH-AD-LINE-ITEM-ID="2379251610201",X-TV-TWITCH-AD-AF-ICR-AD-ID="2379251610201"
#EXT-X-DATERANGE:ID="source-1761228876",CLASS="twitch-stream-source",START-DATE="2025-10-23T14:14:36.102Z",END-ON-NEXT=YES,X-TV-TWITCH-STREAM-SOURCE="Amazon|2474283100401"
#EXT-X-DATERANGE:ID="trigger-1761228876",CLASS="twitch-trigger",START-DATE="2025-10-23T14:14:36.102Z",END-ON-NEXT=YES,X-TV-TWITCH-TRIGGER-URL="https://euc11.playlist.ttvnw.net/trigger/..."
#EXT-X-DATERANGE:ID="quartile-1761228876-0",CLASS="twitch-ad-quartile",START-DATE="2025-10-23T14:14:36.102Z",DURATION=2.002,X-TV-TWITCH-AD-QUARTILE="0"
#EXT-X-DISCONTINUITY
#EXT-X-PROGRAM-DATE-TIME:2025-10-23T14:14:36.102Z
#EXTINF:2.002,Amazon|2474283100401
https://...
It's completely fine that the library doesn't provide a solid interface for everything (impossible anyway), but at least I should have a general access to those tags and nothing should be dropped by the parser. What comes to my mind is:
While I really like this library there's still some functionality missing regarding the
#EXT-Xtags:#EXT-X-DATERANGEis supported, while having more is valid (issue #EXT-X-DATERANGE limited to 1 per media segment #37 seems to have stalled)Here is a live example from Twitch:
It's completely fine that the library doesn't provide a solid interface for everything (impossible anyway), but at least I should have a general access to those tags and nothing should be dropped by the parser. What comes to my mind is:
dateRanges()and return a map (id to theDateRange)dateRange()becomes@DeprecatedDateRange.clientAttributes()there should also be a method to return all attributes in a map (clientAttributes()plus all known fields with values)extendedTags()that returns a list of all#EXT-Xtags with their attributes as a map (the list may include the handled and unhandled tags)Similar changes make sense for the
Builders.IMHO, the goal should be that if I use the
Builder, build the original playlist by code and then write the whole playlist as a string it should contain the entire thing again (order of the tags or attributes isn't relevant, I think, but it makes sense to have the common ones first).