mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Handle non resize transcode (#755)
This commit is contained in:
parent
aadf300e5e
commit
cd89e757c1
@ -91,8 +91,8 @@ func (fs *FileStream) GetMaster() string {
|
||||
master += "\n"
|
||||
|
||||
// codec is the prefix + the level, the level is not part of the codec we want to compare for the same_codec check bellow
|
||||
transmux_prefix := "avc1.6400"
|
||||
transmux_codec := transmux_prefix + "28"
|
||||
transcode_prefix := "avc1.6400"
|
||||
transcode_codec := transcode_prefix + "28"
|
||||
audio_codec := "mp4a.40.2"
|
||||
|
||||
var def_video *Video
|
||||
@ -108,10 +108,15 @@ func (fs *FileStream) GetMaster() string {
|
||||
|
||||
if def_video != nil {
|
||||
qualities := Filter(Qualities, func(quality Quality) bool {
|
||||
same_codec := def_video.MimeCodec != nil && strings.HasPrefix(*def_video.MimeCodec, transmux_prefix)
|
||||
return quality.Height() < def_video.Height ||
|
||||
(quality.Height() == def_video.Height && !same_codec)
|
||||
return quality.Height() < def_video.Height
|
||||
})
|
||||
transcode_count := len(qualities)
|
||||
|
||||
// NoResize is the same idea as Original but we change the codec.
|
||||
// This is only needed when the original's codec is different from what we would transcode it to.
|
||||
if def_video.MimeCodec == nil || !strings.HasPrefix(*def_video.MimeCodec, transcode_prefix) {
|
||||
qualities = append(qualities, NoResize)
|
||||
}
|
||||
qualities = append(qualities, Original)
|
||||
|
||||
for _, quality := range qualities {
|
||||
@ -137,26 +142,23 @@ func (fs *FileStream) GetMaster() string {
|
||||
}
|
||||
master += "\n"
|
||||
|
||||
// original stream
|
||||
{
|
||||
bitrate := float64(def_video.Bitrate)
|
||||
master += "#EXT-X-STREAM-INF:"
|
||||
master += fmt.Sprintf("AVERAGE-BANDWIDTH=%d,", int(math.Min(bitrate*0.8, float64(def_video.Quality().AverageBitrate()))))
|
||||
master += fmt.Sprintf("BANDWIDTH=%d,", int(math.Min(bitrate, float64(def_video.Quality().MaxBitrate()))))
|
||||
master += fmt.Sprintf("RESOLUTION=%dx%d,", def_video.Width, def_video.Height)
|
||||
if def_video.MimeCodec != nil {
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{*def_video.MimeCodec, audio_codec}, ","))
|
||||
}
|
||||
master += "AUDIO=\"audio\","
|
||||
master += "CLOSED-CAPTIONS=NONE\n"
|
||||
master += fmt.Sprintf("%d/%s/index.m3u8\n", def_video.Index, Original)
|
||||
}
|
||||
|
||||
aspectRatio := float32(def_video.Width) / float32(def_video.Height)
|
||||
|
||||
for i, quality := range qualities {
|
||||
if i == len(qualities)-1 {
|
||||
// skip the original stream that already got handled
|
||||
if i >= transcode_count {
|
||||
// original & noresize streams
|
||||
bitrate := float64(def_video.Bitrate)
|
||||
master += "#EXT-X-STREAM-INF:"
|
||||
master += fmt.Sprintf("AVERAGE-BANDWIDTH=%d,", int(math.Min(bitrate*0.8, float64(def_video.Quality().AverageBitrate()))))
|
||||
master += fmt.Sprintf("BANDWIDTH=%d,", int(math.Min(bitrate, float64(def_video.Quality().MaxBitrate()))))
|
||||
master += fmt.Sprintf("RESOLUTION=%dx%d,", def_video.Width, def_video.Height)
|
||||
if quality != Original {
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{transcode_codec, audio_codec}, ","))
|
||||
} else if def_video.MimeCodec != nil {
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{*def_video.MimeCodec, audio_codec}, ","))
|
||||
}
|
||||
master += "AUDIO=\"audio\","
|
||||
master += "CLOSED-CAPTIONS=NONE\n"
|
||||
master += fmt.Sprintf("%d/%s/index.m3u8\n", def_video.Index, quality)
|
||||
continue
|
||||
}
|
||||
|
||||
@ -164,7 +166,7 @@ func (fs *FileStream) GetMaster() string {
|
||||
master += fmt.Sprintf("AVERAGE-BANDWIDTH=%d,", quality.AverageBitrate())
|
||||
master += fmt.Sprintf("BANDWIDTH=%d,", quality.MaxBitrate())
|
||||
master += fmt.Sprintf("RESOLUTION=%dx%d,", int(aspectRatio*float32(quality.Height())+0.5), quality.Height())
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{transmux_codec, audio_codec}, ","))
|
||||
master += fmt.Sprintf("CODECS=\"%s\",", strings.Join([]string{transcode_codec, audio_codec}, ","))
|
||||
master += "AUDIO=\"audio\","
|
||||
master += "CLOSED-CAPTIONS=NONE\n"
|
||||
master += fmt.Sprintf("%d/%s/index.m3u8\n", def_video.Index, quality)
|
||||
|
@ -17,6 +17,7 @@ const (
|
||||
P1440 Quality = "1440p"
|
||||
P4k Quality = "4k"
|
||||
P8k Quality = "8k"
|
||||
NoResize Quality = "transcode"
|
||||
Original Quality = "original"
|
||||
)
|
||||
|
||||
@ -27,6 +28,9 @@ func QualityFromString(str string) (Quality, error) {
|
||||
if str == string(Original) {
|
||||
return Original, nil
|
||||
}
|
||||
if str == string(NoResize) {
|
||||
return NoResize, nil
|
||||
}
|
||||
|
||||
for _, quality := range Qualities {
|
||||
if string(quality) == str {
|
||||
|
@ -71,16 +71,30 @@ func (vs *VideoStream) getTranscodeArgs(segments string) []string {
|
||||
}
|
||||
|
||||
args = append(args, Settings.HwAccel.EncodeFlags...)
|
||||
width := int32(float64(vs.quality.Height()) / float64(vs.video.Height) * float64(vs.video.Width))
|
||||
// force a width that is a multiple of two else some apps behave badly.
|
||||
width = closestMultiple(width, 2)
|
||||
|
||||
quality := vs.quality
|
||||
if vs.quality != NoResize {
|
||||
width := int32(float64(vs.quality.Height()) / float64(vs.video.Height) * float64(vs.video.Width))
|
||||
// force a width that is a multiple of two else some apps behave badly.
|
||||
width = closestMultiple(width, 2)
|
||||
args = append(args,
|
||||
"-vf", fmt.Sprintf(Settings.HwAccel.ScaleFilter, width, vs.quality.Height()),
|
||||
)
|
||||
} else {
|
||||
// NoResize doesn't have bitrate info, fallback to a know quality higher or equal.
|
||||
for _, q := range Qualities {
|
||||
if q.Height() >= vs.video.Height {
|
||||
quality = q
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
args = append(args,
|
||||
"-vf", fmt.Sprintf(Settings.HwAccel.ScaleFilter, width, vs.quality.Height()),
|
||||
// Even less sure but bufsize are 5x the avergae bitrate since the average bitrate is only
|
||||
// useful for hls segments.
|
||||
"-bufsize", fmt.Sprint(vs.quality.MaxBitrate()*5),
|
||||
"-b:v", fmt.Sprint(vs.quality.AverageBitrate()),
|
||||
"-maxrate", fmt.Sprint(vs.quality.MaxBitrate()),
|
||||
"-bufsize", fmt.Sprint(quality.MaxBitrate()*5),
|
||||
"-b:v", fmt.Sprint(quality.AverageBitrate()),
|
||||
"-maxrate", fmt.Sprint(quality.MaxBitrate()),
|
||||
// Force segments to be split exactly on keyframes (only works when transcoding)
|
||||
// forced-idr is needed to force keyframes to be an idr-frame (by default it can be any i frames)
|
||||
// without this option, some hardware encoders uses others i-frames and the -f segment can't cut at them.
|
||||
|
Loading…
x
Reference in New Issue
Block a user