package media import ( "errors" "strconv" "strings" ) type Segment struct { URL string Duration float64 Sequence int } type MediaPlaylist struct { Segments []Segment TargetDuration float64 IsLive bool HasEndList bool } func (s *StreamSet) FetchSegmentPlaylists() (videoPlaylist, audioPlaylist string, err error) { video, audio := s.SelectBestQualityStreams() if video == nil { return "", "", errors.New("no video streams available") } videoURL := s.BuildStreamURL(video.URL) videoContent, err := FetchPlaylistContent(StripQuotes(videoURL)) if err != nil { return "", "", err } var audioContent string if audio != nil { audioURL := s.BuildStreamURL(StripQuotes(audio.URL)) audioContent, err = FetchPlaylistContent(StripQuotes(audioURL)) if err != nil { return "", "", err } } return videoContent, audioContent, nil } func ParseMediaPlaylist(content string) *MediaPlaylist { lines := strings.Split(content, "\n") var segments []Segment playlist := &MediaPlaylist{ IsLive: true, HasEndList: false, } mediaSequence := 0 for i, line := range lines { switch { case strings.HasPrefix(line, ExtXTargetDuration): playlist.TargetDuration = parseTargetDuration(line) case strings.HasPrefix(line, ExtInf): if i+1 < len(lines) { duration := parseSegmentDuration(line) segments = append(segments, Segment{ URL: lines[i+1], Duration: duration, Sequence: mediaSequence, }) mediaSequence++ } case strings.HasPrefix(line, ExtXPlaylistType): if strings.Contains(line, PlaylistTypeVOD) { playlist.IsLive = false } case strings.HasPrefix(line, ExtXEndList): playlist.HasEndList = true } } playlist.Segments = segments return playlist } func parseTargetDuration(line string) float64 { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { if duration, err := strconv.ParseFloat(strings.TrimSpace(parts[1]), 64); err == nil { return duration } } return 0.0 } func parseSegmentDuration(line string) float64 { parts := strings.Split(line, ":") if len(parts) >= 2 { durationPart := strings.Split(parts[1], ",")[0] if duration, err := strconv.ParseFloat(durationPart, 64); err == nil { return duration } } return 0.0 }