StreamRecorder/media/stream.go

99 lines
2.2 KiB
Go

package media
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 media 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
}