Commit Diff


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