113 lines
2.4 KiB
Go

package downloader
import (
"errors"
"fmt"
"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 (s *StreamSet) BuildSegmentURL(filename string) string {
return fmt.Sprintf("%s%s", HTTPSPrefix, s.Metadata.Domain+"/streams/"+s.Metadata.StreamID+"/a/5000/"+filename)
}
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
}