108 lines
2.2 KiB
Go
108 lines
2.2 KiB
Go
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
|
|
}
|