package downloader import ( "fmt" "strings" ) type PlaylistMetadata struct { URL string Domain string StreamID string } func NewPlaylistMetadata(masterURL string) *PlaylistMetadata { strippedURL := strings.Replace(masterURL, HTTPSPrefix, "", 1) urlPrefix := strings.Split(strippedURL, "/")[0] return &PlaylistMetadata{ URL: masterURL, Domain: urlPrefix, StreamID: strings.Split(strippedURL, "/")[2], } } type StreamSet struct { Metadata *PlaylistMetadata VideoStreams []VideoStream AudioStreams []AudioStream } func (s *StreamSet) BuildStreamURL(endpoint string) string { return fmt.Sprintf("%s%s/streams/%s/%s", HTTPSPrefix, s.Metadata.Domain, s.Metadata.StreamID, endpoint) } func ParseMasterPlaylist(masterURL string) (*StreamSet, error) { metadata := NewPlaylistMetadata(masterURL) content, err := FetchPlaylistContent(masterURL) if err != nil { return nil, err } videoStreams, audioStreams := parsePlaylistLines(content) return &StreamSet{ Metadata: metadata, VideoStreams: videoStreams, AudioStreams: audioStreams, }, nil } func parsePlaylistLines(content string) ([]VideoStream, []AudioStream) { lines := strings.Split(content, "\n") var videoStreams []VideoStream var audioStreams []AudioStream for i, line := range lines { if strings.HasPrefix(line, ExtXStreamInf) && i+1 < len(lines) { if video, err := NewVideoStream(line, lines[i+1]); err == nil { videoStreams = append(videoStreams, *video) } } else if strings.HasPrefix(line, ExtXMedia) { if audio, err := NewAudioStream(line); err == nil { audioStreams = append(audioStreams, *audio) } } } return videoStreams, audioStreams }