grafov / m3u8

Parser and generator of M3U8-playlists for Apple HLS. Library for Go language. :cinema:
http://tools.ietf.org/html/draft-pantos-http-live-streaming
BSD 3-Clause "New" or "Revised" License
1.24k stars 318 forks source link

Alternative renditions do not seem to work properly #221

Open rbroggi opened 1 day ago

rbroggi commented 1 day ago

Hello,

I've seen that the following HLS master playlist manifest does not get parsed correctly:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=10724221,AVERAGE-BANDWIDTH=6811874,RESOLUTION=1920x1080,FRAME-RATE=59.940,CODECS="avc1.64002A,mp4a.40.2",AUDIO="audio_0"
index_2.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=4567270,AVERAGE-BANDWIDTH=2961839,RESOLUTION=1280x720,FRAME-RATE=59.940,CODECS="avc1.640020,mp4a.40.2",AUDIO="audio_0"
index_3.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=1576792,AVERAGE-BANDWIDTH=1091874,RESOLUTION=854x480,FRAME-RATE=59.940,CODECS="avc1.64001F,mp4a.40.2",AUDIO="audio_0"
index_1.m3u8?start=1732270105
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_0",CHANNELS="2",NAME="und",LANGUAGE="und",DEFAULT=YES,AUTOSELECT=YES,URI="index_4_0.m3u8?start=1732270105"

Notice that the issue is that the alternative rendition in the last line does not get included in the variants after parsing the master playlist.

The parsing seems to require such line to be before every #EXT-X-STREAM-INF in order to work.

Thank you :smile:

rbroggi commented 1 day ago

check the Go test below:

func TestMasterPlaylistParsing(t *testing.T) {
    playlist, _, err := m3u8.DecodeFrom(bytes.NewReader(masterWithSeparateAudioPlaylist), true)
    require.NoError(t, err)
    for _, variant := range playlist.(*m3u8.MasterPlaylist).Variants {
        t.Logf("%+v", variant)
    }
}

I will show how the variants are decoded depending on the position of the #EXT-X-MEDIA: line:

Input/Output 1:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_0",CHANNELS="2",NAME="und",LANGUAGE="und",DEFAULT=YES,AUTOSELECT=YES,URI="index_4_0.m3u8?start=1732270105"
#EXT-X-STREAM-INF:BANDWIDTH=10724221,AVERAGE-BANDWIDTH=6811874,RESOLUTION=1920x1080,FRAME-RATE=59.940,CODECS="avc1.64002A,mp4a.40.2",AUDIO="audio_0"
index_2.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=4567270,AVERAGE-BANDWIDTH=2961839,RESOLUTION=1280x720,FRAME-RATE=59.940,CODECS="avc1.640020,mp4a.40.2",AUDIO="audio_0"
index_3.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=1576792,AVERAGE-BANDWIDTH=1091874,RESOLUTION=854x480,FRAME-RATE=59.940,CODECS="avc1.64001F,mp4a.40.2",AUDIO="audio_0"
index_1.m3u8?start=1732270105
    playlist_test.go:1573: &{URI:index_2.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:10724221 AverageBandwidth:6811874 Codecs:avc1.64002A,mp4a.40.2 Resolution:1920x1080 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}
    playlist_test.go:1573: &{URI:index_3.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:4567270 AverageBandwidth:2961839 Codecs:avc1.640020,mp4a.40.2 Resolution:1280x720 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}
    playlist_test.go:1573: &{URI:index_1.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:1576792 AverageBandwidth:1091874 Codecs:avc1.64001F,mp4a.40.2 Resolution:854x480 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}

Input/Output 2:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=10724221,AVERAGE-BANDWIDTH=6811874,RESOLUTION=1920x1080,FRAME-RATE=59.940,CODECS="avc1.64002A,mp4a.40.2",AUDIO="audio_0"
index_2.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=4567270,AVERAGE-BANDWIDTH=2961839,RESOLUTION=1280x720,FRAME-RATE=59.940,CODECS="avc1.640020,mp4a.40.2",AUDIO="audio_0"
index_3.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=1576792,AVERAGE-BANDWIDTH=1091874,RESOLUTION=854x480,FRAME-RATE=59.940,CODECS="avc1.64001F,mp4a.40.2",AUDIO="audio_0"
index_1.m3u8?start=1732270105
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_0",CHANNELS="2",NAME="und",LANGUAGE="und",DEFAULT=YES,AUTOSELECT=YES,URI="index_4_0.m3u8?start=1732270105"
    playlist_test.go:1573: &{URI:index_2.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:10724221 AverageBandwidth:6811874 Codecs:avc1.64002A,mp4a.40.2 Resolution:1920x1080 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}
    playlist_test.go:1573: &{URI:index_3.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:4567270 AverageBandwidth:2961839 Codecs:avc1.640020,mp4a.40.2 Resolution:1280x720 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}
    playlist_test.go:1573: &{URI:index_1.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:1576792 AverageBandwidth:1091874 Codecs:avc1.64001F,mp4a.40.2 Resolution:854x480 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}

Input/Output 3:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=10724221,AVERAGE-BANDWIDTH=6811874,RESOLUTION=1920x1080,FRAME-RATE=59.940,CODECS="avc1.64002A,mp4a.40.2",AUDIO="audio_0"
index_2.m3u8?start=1732270105
#EXT-X-STREAM-INF:BANDWIDTH=4567270,AVERAGE-BANDWIDTH=2961839,RESOLUTION=1280x720,FRAME-RATE=59.940,CODECS="avc1.640020,mp4a.40.2",AUDIO="audio_0"
index_3.m3u8?start=1732270105
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio_0",CHANNELS="2",NAME="und",LANGUAGE="und",DEFAULT=YES,AUTOSELECT=YES,URI="index_4_0.m3u8?start=1732270105"
#EXT-X-STREAM-INF:BANDWIDTH=1576792,AVERAGE-BANDWIDTH=1091874,RESOLUTION=854x480,FRAME-RATE=59.940,CODECS="avc1.64001F,mp4a.40.2",AUDIO="audio_0"
index_1.m3u8?start=1732270105
    playlist_test.go:1573: &{URI:index_2.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:10724221 AverageBandwidth:6811874 Codecs:avc1.64002A,mp4a.40.2 Resolution:1920x1080 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}
    playlist_test.go:1573: &{URI:index_3.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:4567270 AverageBandwidth:2961839 Codecs:avc1.640020,mp4a.40.2 Resolution:1280x720 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[]}}
    playlist_test.go:1573: &{URI:index_1.m3u8?start=1732270105 Chunklist:<nil> VariantParams:{ProgramId:0 Bandwidth:1576792 AverageBandwidth:1091874 Codecs:avc1.64001F,mp4a.40.2 Resolution:854x480 Audio:audio_0 Video: Subtitles: Captions: Name: Iframe:false VideoRange: HDCPLevel: FrameRate:59.94 Alternatives:[0xc0001be6e0]}}
rbroggi commented 21 hours ago

see also this PR that shows the issue in a repo test case