Skip to content
This repository has been archived by the owner on Dec 8, 2024. It is now read-only.

EXT-X-MEDIA audio missing from VariantParams.Alternatives for master playlist decode #160

Open
elv-peter opened this issue Mar 17, 2020 · 1 comment · May be fixed by #180
Open

EXT-X-MEDIA audio missing from VariantParams.Alternatives for master playlist decode #160

elv-peter opened this issue Mar 17, 2020 · 1 comment · May be fixed by #180

Comments

@elv-peter
Copy link

For the master playlist below, the MasterPlaylist object (after decoding) is missing the audio stream with GROUP-ID="audio-aacl-128". That is, MasterPlaylist.Variants[9].VariantParams.Alternatives is nil.

Also, only the first variant's Alternatives is populated, which I believe is this ticket: #96. However, I can't work around this by accessing the audio-aacl-128 stream using the first variant, because it specifies AUDIO="audio-aacl-64".

#EXTM3U
#EXT-X-VERSION:5
## Created with Unified Streaming Platform(version=1.9.5)

# AUDIO groups
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-64",NAME="English",LANGUAGE="en",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="2",URI="avc_decrypted_global-stream_audio_eng_64000=64000.m3u8"

# variants
#EXT-X-STREAM-INF:BANDWIDTH=202000,AVERAGE-BANDWIDTH=184000,CODECS="mp4a.40.2,avc1.42C01E",RESOLUTION=192x108,FRAME-RATE=25,AUDIO="audio-aacl-64",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=112000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=407000,AVERAGE-BANDWIDTH=370000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=480x270,FRAME-RATE=25,AUDIO="audio-aacl-64",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=288000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=631000,AVERAGE-BANDWIDTH=574000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=640x360,FRAME-RATE=25,AUDIO="audio-aacl-64",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=480000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1051000,AVERAGE-BANDWIDTH=956000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=960x540,FRAME-RATE=25,AUDIO="audio-aacl-64",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=840000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1821000,AVERAGE-BANDWIDTH=1655000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=960x540,FRAME-RATE=25,AUDIO="audio-aacl-64",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=1499968.m3u8

# AUDIO groups
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio-aacl-128",NAME="English",LANGUAGE="en",AUTOSELECT=YES,DEFAULT=YES,CHANNELS="2",URI="avc_decrypted_global-stream_audio_eng_128000=128000.m3u8"

# variants
#EXT-X-STREAM-INF:BANDWIDTH=2824000,AVERAGE-BANDWIDTH=2568000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=1280x720,FRAME-RATE=25,AUDIO="audio-aacl-128",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=2299968.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3641000,AVERAGE-BANDWIDTH=3310000,CODECS="mp4a.40.2,avc1.4D401F",RESOLUTION=1280x720,FRAME-RATE=25,AUDIO="audio-aacl-128",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=3000000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=5273000,AVERAGE-BANDWIDTH=4794000,CODECS="mp4a.40.2,avc1.640020",RESOLUTION=1280x720,FRAME-RATE=50,AUDIO="audio-aacl-128",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=4400000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=7722000,AVERAGE-BANDWIDTH=7020000,CODECS="mp4a.40.2,avc1.640020",RESOLUTION=1280x720,FRAME-RATE=50,AUDIO="audio-aacl-128",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=6499968.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=9471000,AVERAGE-BANDWIDTH=8610000,CODECS="mp4a.40.2,avc1.640020",RESOLUTION=1280x720,FRAME-RATE=50,AUDIO="audio-aacl-128",CLOSED-CAPTIONS=NONE
avc_decrypted_global-video=8000000.m3u8

# keyframes
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=17000,CODECS="avc1.42C01E",RESOLUTION=192x108,URI="keyframes/avc_decrypted_global-video=112000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=42000,CODECS="avc1.4D401F",RESOLUTION=480x270,URI="keyframes/avc_decrypted_global-video=288000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=70000,CODECS="avc1.4D401F",RESOLUTION=640x360,URI="keyframes/avc_decrypted_global-video=480000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=123000,CODECS="avc1.4D401F",RESOLUTION=960x540,URI="keyframes/avc_decrypted_global-video=840000.m3u8"
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=336000,CODECS="avc1.4D401F",RESOLUTION=1280x720,URI="keyframes/avc_decrypted_global-video=2299968.m3u8"
@slugalisk
Copy link

#EXT-X-MEDIA tags can be parsed using custom tags ex:

type ExtXMediaTagValue struct {
	Type       string
	GroupID    string
	Channels   string
	Name       string
	Language   string
	Default    bool
	AutoSelect bool
	Forced     bool
	URI        string
}

type ExtXMediaTag struct {
	Values []*ExtXMediaTagValue
}

func (tag *ExtXMediaTag) TagName() string {
	return "#EXT-X-MEDIA:"
}

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
		}
	}

	tag.Values = append(tag.Values, val)

	return tag, nil
}

func (tag *ExtXMediaTag) SegmentTag() bool {
	return false
}

func (tag *ExtXMediaTag) Encode() *bytes.Buffer {
	b := bytes.NewBuffer(nil)

	for i, val := range tag.Values {
		if i != 0 {
			b.WriteByte('\n')
		}
		b.WriteString(tag.TagName())
		writeStringTagAttr(b, "TYPE", val.Type, false)
		b.WriteRune(',')
		writeStringTagAttr(b, "GROUP-ID", val.GroupID, true)
		if val.Type == "AUDIO" {
			b.WriteRune(',')
			writeStringTagAttr(b, "CHANNELS", val.Channels, true)
		}
		b.WriteRune(',')
		writeStringTagAttr(b, "NAME", val.Name, true)
		b.WriteRune(',')
		writeStringTagAttr(b, "LANGUAGE", val.Language, true)
		b.WriteRune(',')
		writeBoolTagAttr(b, "DEFAULT", val.Default)
		b.WriteRune(',')
		writeBoolTagAttr(b, "AUTOSELECT", val.AutoSelect)
		if val.Type == "SUBTITLES" {
			b.WriteRune(',')
			writeBoolTagAttr(b, "FORCED", val.Forced)
		}
		b.WriteRune(',')
		writeStringTagAttr(b, "URI", val.URI, true)
	}

	return b
}

func (tag *ExtXMediaTag) String() string {
	return tag.Encode().String()
}

func writeStringTagAttr(b *bytes.Buffer, k string, v string, quote bool) {
	b.WriteString(k)
	b.WriteRune('=')
	if quote {
		b.WriteRune('"')
	}
	b.WriteString(v)
	if quote {
		b.WriteRune('"')
	}
}

func writeBoolTagAttr(b *bytes.Buffer, k string, v bool) {
	b.WriteString(k)
	b.WriteRune('=')
	if v {
		b.WriteString("YES")
	} else {
		b.WriteString("NO")
	}
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants