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.22k stars 312 forks source link

Duplicate Data Resulting from Custom Tags #201

Open slipthebit opened 12 months ago

slipthebit commented 12 months ago

CustomTags are parsed in twice when using DecodeWith. This happens because both decodeLineOfMasterPlaylist and decodeLineOfMediaPlaylist are called in decode, and both parse the CustomTags seperatley.

This issue can be observed using the Master Manifest, https://devstreaming-cdn.apple.com/videos/streaming/examples/img_bipbop_adv_example_fmp4/master.m3u8, and CustomTag example in Issue #160 detailed by @slugalisk.

The Master Manifest includes 5 #EXT-X-MEDIA tags, but DecodeWith produces 10 Values for the CustomTag.

The go-playground link below duplicates the issue as of 9/20/2023 with v0.12.0 https://goplay.tools/snippet/e_p-kLnpqco

slipthebit commented 12 months ago

As a workaround to the issue, I filter out duplicates in the Custom Tag Decode function.

Using the example from Issue #160, I modified the Decode function to be:

func (tag *ExtXMediaTag) Decode(line string) (m3u8.CustomTag, error) {
    val := &ExtXMediaTagValue{}

         for k, v := range m3u8.DecodeAttributeList(line) {
        switch k {
        case "TYPE":
            val.Type = v
        case "GROUP-ID":
            val.GroupID = v
        case "CHANNELS":
            val.Channels = v
        case "NAME":
            val.Name = v
        case "LANGUAGE":
            val.Language = v
        case "DEFAULT":
            val.Default = v == "YES"
        case "AUTOSELECT":
            val.AutoSelect = v == "YES"
        case "FORCED":
            val.Forced = v == "YES"
        case "URI":
            val.URI = v
        }
    }

         //prevent duplication - ref: https://github.com/grafov/m3u8/issues/201
    dup := false
    for _, t := range tag.Values {
        if *t == *val {
            dup = true
            break
        }
    }

    if !dup { 
        tag.Values = append(tag.Values, val)
    }

    return tag, nil
}
slipthebit commented 12 months ago

Alternatively, if the playlist type is known, the CustomTags can be added to the playlist itself before decoding. https://goplay.tools/snippet/COz0f_dEbA9