commit 2be3531b0dcadd5c29adc1fff94844876de00afe from: Luiz Henrique Rapatao via: Oliver Lowe date: Tue Apr 22 22:57:07 2025 UTC m3u8: add support for parsing media sequence from playlist commit - b3f3a7ccc95f08e87b4df8d758c035e4ef5e0fc5 commit + 2be3531b0dcadd5c29adc1fff94844876de00afe blob - 5c26bc7a91e5e7d4594e8c07fe98576ce77709ac blob + d73bcc7147293cce0ea0a9a55185cccc5f9abd7d --- m3u8/parse.go +++ m3u8/parse.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io" + "regexp" "strconv" "strings" "time" @@ -85,6 +86,12 @@ func Decode(rd io.Reader) (*Playlist, error) { p.Segments = append(p.Segments, *segment) case tagEndList: p.End = true + case tagMediaSequence: + val, err := parseSequence(lex) + if err != nil { + return p, fmt.Errorf("parse media sequence: %w", err) + } + p.Sequence = val } } } @@ -381,3 +388,14 @@ func parseByteRange(s string) (ByteRange, error) { } return ByteRange{n, nn}, nil } + +func parseSequence(lex *lexer) (int, error) { + re := regexp.MustCompile(`#EXT-X-MEDIA-SEQUENCE:(\d+)`) + + match := re.FindStringSubmatch(lex.input) + if len(match) > 1 { + return strconv.Atoi(match[1]) + } + + return 0, fmt.Errorf("invalid sequence number") +} blob - 6bb8bfd37387985be64fc852d33b9ec94ea90fa6 blob + 8614b5d3dff6b87a4b67ccf09b7e89a9543f3348 --- m3u8/parse_test.go +++ m3u8/parse_test.go @@ -135,3 +135,18 @@ func TestFrameRate(t *testing.T) { } } } + +func TestParseSequence(t *testing.T) { + f, err := os.Open("testdata/sequence.m3u8") + if err != nil { + t.Fatal(err) + } + defer f.Close() + plist, err := Decode(f) + if err != nil { + t.Fatal(err) + } + if plist.Sequence != 91240 { + t.Errorf("want %d, got %d", 91240, plist.Sequence) + } +} blob - /dev/null blob + 91a14211a3b092ea9087af322cac7f159a7be05e (mode 644) --- /dev/null +++ m3u8/testdata/sequence.m3u8 @@ -0,0 +1,11 @@ +#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-TARGETDURATION:3 +#EXT-X-MEDIA-SEQUENCE:91240 +#EXT-X-DISCONTINUITY-SEQUENCE:0 +#EXTINF:2.002, +media-seg_91240.ts +#EXTINF:2.002, +media-seg_91241.ts +#EXTINF:2.002, +media-seg_91242.ts