commit aeced255c350bab7d38431993ca2485d4cfa2370
parent 598fdad5e83b6942731dd84ef231c3f8e605e5fe
Author: Oliver Lowe <o@olowe.co>
Date: Wed, 22 May 2024 14:18:22 +1000
m3u8: test parsing quoted string lists
Diffstat:
8 files changed, 173 insertions(+), 30 deletions(-)
diff --git a/m3u8/parse.go b/m3u8/parse.go
@@ -97,6 +97,8 @@ func parseVariant(items chan item) (*Variant, error) {
return nil, fmt.Errorf("missing equals after %s", attr)
}
switch attr.val {
+ case "PROGRAM-ID":
+ return nil, fmt.Errorf("parsing PROGRAM-ID attribute unsupported; removed in HLS version 6")
case "BANDWIDTH", "AVERAGE-BANDWIDTH":
it = <-items
if it.typ != itemNumber {
@@ -165,7 +167,7 @@ func parseVariant(items chan item) (*Variant, error) {
if it.typ != itemString {
return nil, fmt.Errorf("parse closed-captions: unexpcted %s", it)
}
- v.ClosedCaptions = strings.Split(it.val, ",")
+ v.ClosedCaptions = strings.Split(strings.Trim(it.val, `"`), ",")
default:
return nil, fmt.Errorf("unknown attribute %s", attr.val)
}
diff --git a/m3u8/parse_test.go b/m3u8/parse_test.go
@@ -4,6 +4,7 @@ import (
"os"
"path"
"path/filepath"
+ "reflect"
"testing"
"time"
)
@@ -64,3 +65,24 @@ func TestParseByteRange(t *testing.T) {
})
}
}
+
+func TestParseClosedCaptions(t *testing.T) {
+ f, err := os.Open("testdata/closed_captions.m3u8")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ p, err := ParsePlaylist(f)
+ if err != nil {
+ t.Fatal(err)
+ }
+ cc := p.Variants[0].ClosedCaptions[0]
+ if cc != "NONE" {
+ t.Errorf("want closed captions %q, got %s", "NONE", cc)
+ }
+ cc2 := p.Variants[1].ClosedCaptions
+ want := []string{"something", "another"}
+ if !reflect.DeepEqual(want, cc2) {
+ t.Errorf("want closed captions %s, got %s", want, cc2)
+ }
+}
diff --git a/m3u8/testdata/closed_captions.m3u8 b/m3u8/testdata/closed_captions.m3u8
@@ -0,0 +1,6 @@
+#EXTM3U
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS=NONE
+tos_1080p/index.m3u8
+## can also have quoted strings, comma-delimeted
+#EXT-X-STREAM-INF:CLOSED-CAPTIONS="something,another"
+playlist.m3u8
diff --git a/m3u8/testdata/master-with-alternatives.m3u8 b/m3u8/testdata/master-with-alternatives.m3u8
@@ -1,18 +0,0 @@
-#EXTM3U
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Main",DEFAULT=YES,URI="low/main/audio-video.m3u8"
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Centerfield",DEFAULT=NO,URI="low/centerfield/audio-video.m3u8"
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Dugout",DEFAULT=NO,URI="low/dugout/audio-video.m3u8"
-#EXT-X-STREAM-INF:BANDWIDTH=1280000,VIDEO="low"
-low/main/audio-video.m3u8
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Main",DEFAULT=YES,URI="mid/main/audio-video.m3u8"
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Centerfield",DEFAULT=NO,URI="mid/centerfield/audio-video.m3u8"
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Dugout",DEFAULT=NO,URI="mid/dugout/audio-video.m3u8"
-#EXT-X-STREAM-INF:BANDWIDTH=2560000,VIDEO="mid"
-mid/main/audio-video.m3u8
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Main",DEFAULT=YES,URI="hi/main/audio-video.m3u8"
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Centerfield",DEFAULT=NO,URI="hi/centerfield/audio-video.m3u8"
-#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Dugout",DEFAULT=NO,URI="hi/dugout/audio-video.m3u8"
-#EXT-X-STREAM-INF:BANDWIDTH=7680000,VIDEO="hi"
-hi/main/audio-video.m3u8
-#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS="mp4a.40.5"
-main/audio-only.m3u8
diff --git a/m3u8/testdata/master.m3u8 b/m3u8/testdata/master.m3u8
@@ -1,12 +1,18 @@
#EXTM3U
-#EXT-X-VERSION:3
-#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=300000
-chunklist-b300000.m3u8
-#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=600000
-chunklist-b600000.m3u8
-#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=850000
-chunklist-b850000.m3u8
-#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1000000
-chunklist-b1000000.m3u8
-#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1500000
-chunklist-b1500000.m3u8
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Main",DEFAULT=YES,URI="low/main/audio-video.m3u8"
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Centerfield",DEFAULT=NO,URI="low/centerfield/audio-video.m3u8"
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Dugout",DEFAULT=NO,URI="low/dugout/audio-video.m3u8"
+#EXT-X-STREAM-INF:BANDWIDTH=1280000,VIDEO="low"
+low/main/audio-video.m3u8
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Main",DEFAULT=YES,URI="mid/main/audio-video.m3u8"
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Centerfield",DEFAULT=NO,URI="mid/centerfield/audio-video.m3u8"
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Dugout",DEFAULT=NO,URI="mid/dugout/audio-video.m3u8"
+#EXT-X-STREAM-INF:BANDWIDTH=2560000,VIDEO="mid"
+mid/main/audio-video.m3u8
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Main",DEFAULT=YES,URI="hi/main/audio-video.m3u8"
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Centerfield",DEFAULT=NO,URI="hi/centerfield/audio-video.m3u8"
+#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Dugout",DEFAULT=NO,URI="hi/dugout/audio-video.m3u8"
+#EXT-X-STREAM-INF:BANDWIDTH=7680000,VIDEO="hi"
+hi/main/audio-video.m3u8
+#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS="mp4a.40.5"
+main/audio-only.m3u8
diff --git a/m3u8/testdata/media.m3u8 b/m3u8/testdata/media.m3u8
@@ -0,0 +1,108 @@
+#EXTM3U
+#EXT-X-VERSION:3
+#EXT-X-MEDIA-SEQUENCE:0
+#EXT-X-ALLOW-CACHE:YES
+#EXT-X-TARGETDURATION:10
+#EXTINF:10.000000,
+stream_110k_48k_416x234_000.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_001.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_002.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_003.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_004.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_005.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_006.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_007.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_008.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_009.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_010.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_011.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_012.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_013.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_014.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_015.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_016.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_017.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_018.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_019.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_020.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_021.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_022.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_023.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_024.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_025.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_026.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_027.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_028.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_029.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_030.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_031.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_032.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_033.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_034.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_035.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_036.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_037.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_038.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_039.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_040.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_041.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_042.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_043.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_044.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_045.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_046.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_047.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_048.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_049.ts
+#EXTINF:10.000000,
+stream_110k_48k_416x234_050.ts
+#EXT-X-ENDLIST
diff --git a/m3u8/testdata/resolution.m3u8 b/m3u8/testdata/resolution.m3u8
@@ -0,0 +1,3 @@
+#EXTM3U
+#EXT-X-STREAM-INF:BANDWIDTH=6725464,RESOLUTION=1920x800
+somefile.mp4
diff --git a/m3u8/testdata/tos.m3u8 b/m3u8/testdata/tos.m3u8
@@ -0,0 +1,14 @@
+#EXTM3U
+## Generated with https://github.com/google/shaka-packager version v2.6.1-634af65-release
+
+#EXT-X-INDEPENDENT-SEGMENTS
+
+#EXT-X-MEDIA:TYPE=AUDIO,URI="tos_audio/index.m3u8",GROUP-ID="audio",LANGUAGE="en",NAME="ENGLISH",AUTOSELECT=YES,CHANNELS="2"
+
+## This TTML playlist was generated by shaka-packager when converting a webvtt subtitles into bare bones TTML
+#EXT-X-MEDIA:TYPE=SUBTITLES,URI="tos_subs/index.m3u8",GROUP-ID="default-text-group",NAME="from webvtt",AUTOSELECT=YES
+## This TTML playlist is copied from Unified Streaming's DASH with segmented TTML playlist
+#EXT-X-MEDIA:TYPE=SUBTITLES,URI="tos_ttml/index.m3u8",GROUP-ID="default-text-group",NAME="ttml",AUTOSELECT=YES
+
+#EXT-X-STREAM-INF:BANDWIDTH=6725464,AVERAGE-BANDWIDTH=6296707,CODECS="avc1.4d4028,mp4a.40.2,stpp.ttml.im1t",RESOLUTION=1920x800,FRAME-RATE=24.000,AUDIO="audio",SUBTITLES="default-text-group",CLOSED-CAPTIONS=NONE
+tos_1080p/index.m3u8