99 lines
2.2 KiB
Go
99 lines
2.2 KiB
Go
package downloader
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type VideoStream struct {
|
|
URL string
|
|
Bandwidth int
|
|
Codecs string
|
|
Resolution string
|
|
FrameRate string
|
|
AudioGroup string
|
|
}
|
|
|
|
func NewVideoStream(streamInfo, url string) (*VideoStream, error) {
|
|
if !strings.HasPrefix(streamInfo, ExtXStreamInf) {
|
|
return nil, errors.New("invalid stream info line")
|
|
}
|
|
|
|
reg := regexp.MustCompile(`([A-Z0-9-]+)=(".*?"|[^,]*)`)
|
|
matches := reg.FindAllStringSubmatch(streamInfo, -1)
|
|
|
|
if len(matches) < 5 {
|
|
return nil, errors.New("insufficient stream attributes")
|
|
}
|
|
|
|
bandwidth, err := strconv.Atoi(matches[0][2])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &VideoStream{
|
|
URL: url,
|
|
Bandwidth: bandwidth,
|
|
Codecs: StripQuotes(matches[1][2]),
|
|
Resolution: StripQuotes(matches[2][2]),
|
|
FrameRate: StripQuotes(matches[3][2]),
|
|
AudioGroup: StripQuotes(matches[4][2]),
|
|
}, nil
|
|
}
|
|
|
|
type AudioStream struct {
|
|
URL string
|
|
MediaType string
|
|
GroupID string
|
|
Name string
|
|
IsDefault bool
|
|
AutoSelect bool
|
|
}
|
|
|
|
func NewAudioStream(mediaInfo string) (*AudioStream, error) {
|
|
if !strings.HasPrefix(mediaInfo, ExtXMedia) {
|
|
return nil, errors.New("invalid downloader info line")
|
|
}
|
|
|
|
attributes := parseMediaAttributes(mediaInfo)
|
|
|
|
return &AudioStream{
|
|
URL: StripQuotes(attributes["URI"]),
|
|
MediaType: StripQuotes(attributes["TYPE"]),
|
|
GroupID: StripQuotes(attributes["GROUP-ID"]),
|
|
Name: StripQuotes(attributes["NAME"]),
|
|
IsDefault: attributes["DEFAULT"] == "YES",
|
|
AutoSelect: attributes["AUTOSELECT"] == "YES",
|
|
}, nil
|
|
}
|
|
|
|
func (s *StreamSet) SelectBestQualityStreams() (*VideoStream, *AudioStream) {
|
|
if len(s.VideoStreams) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
bestVideo := s.VideoStreams[0]
|
|
maxPixels := ResolutionToPixels(bestVideo.Resolution)
|
|
|
|
for _, video := range s.VideoStreams {
|
|
pixels := ResolutionToPixels(video.Resolution)
|
|
if video.Bandwidth > bestVideo.Bandwidth || pixels > maxPixels {
|
|
bestVideo = video
|
|
maxPixels = pixels
|
|
}
|
|
}
|
|
|
|
return &bestVideo, s.FindAudioStreamByGroup(bestVideo.AudioGroup)
|
|
}
|
|
|
|
func (s *StreamSet) FindAudioStreamByGroup(groupID string) *AudioStream {
|
|
for _, audio := range s.AudioStreams {
|
|
if audio.GroupID == groupID {
|
|
return &audio
|
|
}
|
|
}
|
|
return nil
|
|
}
|