manager: improve bitrate scaling

monorepo
Varun Patil 2023-10-24 18:45:40 -07:00
parent a8ad3e95c6
commit 029d3bf1cb
2 changed files with 42 additions and 15 deletions

View File

@ -60,20 +60,15 @@ func NewManager(c *Config, path string, id string, close chan string) (*Manager,
return nil, err return nil, err
} }
// heuristic
if m.probe.CodecName != "h264" {
m.probe.BitRate *= 2
}
m.numChunks = int(math.Ceil(m.probe.Duration.Seconds() / float64(c.ChunkSize))) m.numChunks = int(math.Ceil(m.probe.Duration.Seconds() / float64(c.ChunkSize)))
// Possible streams // Possible streams
m.streams["360p"] = &Stream{c: c, m: m, quality: "360p", height: 360, width: 640, bitrate: 500000} m.streams["360p"] = &Stream{c: c, m: m, quality: "360p", height: 360, width: 640, bitrate: 300}
m.streams["480p"] = &Stream{c: c, m: m, quality: "480p", height: 480, width: 854, bitrate: 1200000} m.streams["480p"] = &Stream{c: c, m: m, quality: "480p", height: 480, width: 854, bitrate: 400}
m.streams["720p"] = &Stream{c: c, m: m, quality: "720p", height: 720, width: 1280, bitrate: 2200000} m.streams["720p"] = &Stream{c: c, m: m, quality: "720p", height: 720, width: 1280, bitrate: 700}
m.streams["1080p"] = &Stream{c: c, m: m, quality: "1080p", height: 1080, width: 1920, bitrate: 3600000} m.streams["1080p"] = &Stream{c: c, m: m, quality: "1080p", height: 1080, width: 1920, bitrate: 1000}
m.streams["1440p"] = &Stream{c: c, m: m, quality: "1440p", height: 1440, width: 2560, bitrate: 6000000} m.streams["1440p"] = &Stream{c: c, m: m, quality: "1440p", height: 1440, width: 2560, bitrate: 1400}
m.streams["2160p"] = &Stream{c: c, m: m, quality: "2160p", height: 2160, width: 3840, bitrate: 10000000} m.streams["2160p"] = &Stream{c: c, m: m, quality: "2160p", height: 2160, width: 3840, bitrate: 3000}
// height is our primary dimension for scaling // height is our primary dimension for scaling
// using the probed size, we adjust the width of the stream // using the probed size, we adjust the width of the stream
@ -83,12 +78,44 @@ func NewManager(c *Config, path string, id string, close chan string) (*Manager,
smDim, lgDim = lgDim, smDim smDim, lgDim = lgDim, smDim
} }
// Get the reference bitrate. This is the same as the current bitrate
// if the video is H.264, otherwise use double the current bitrate.
refBitrate := m.probe.BitRate
if m.probe.CodecName != CODEC_H264 {
refBitrate *= 2
}
// If bitrate could not be read, use 10Mbps
if refBitrate == 0 {
refBitrate = 10000000
}
// Get the multiplier for the reference bitrate.
// For this get the nearest stream size to the original.
origPixels := float64(m.probe.Height * m.probe.Width)
nearestPixels := float64(0)
nearestStream := ""
for key, stream := range m.streams {
streamPixels := float64(stream.height * stream.width)
if nearestPixels == 0 || math.Abs(origPixels-streamPixels) < math.Abs(origPixels-nearestPixels) {
nearestPixels = streamPixels
nearestStream = key
}
}
// Get the bitrate multiplier. This is the ratio of the reference
// bitrate to the nearest stream bitrate, so we can scale all streams.
bitrateMultiplier := 1.0
if nearestStream != "" {
bitrateMultiplier = float64(refBitrate) / float64(m.streams[nearestStream].bitrate)
}
// Only keep streams that are smaller than the video // Only keep streams that are smaller than the video
for k, stream := range m.streams { for k, stream := range m.streams {
stream.order = 0 stream.order = 0
// scale bitrate by frame rate with reference 30 // scale bitrate using the multiplier
stream.bitrate = int(float64(stream.bitrate) * float64(m.probe.FrameRate) / 30.0) stream.bitrate = int(math.Ceil(float64(stream.bitrate) * bitrateMultiplier))
// now store the width of the stream as the larger dimension // now store the width of the stream as the larger dimension
stream.width = int(math.Ceil(float64(lgDim) * float64(stream.height) / float64(smDim))) stream.width = int(math.Ceil(float64(lgDim) * float64(stream.height) / float64(smDim)))
@ -110,7 +137,7 @@ func NewManager(c *Config, path string, id string, close chan string) (*Manager,
quality: QUALITY_MAX, quality: QUALITY_MAX,
height: m.probe.Height, height: m.probe.Height,
width: m.probe.Width, width: m.probe.Width,
bitrate: m.probe.BitRate, bitrate: refBitrate,
order: 1, order: 1,
} }

View File

@ -8,7 +8,7 @@ import (
"github.com/pulsejet/go-vod/go_vod" "github.com/pulsejet/go-vod/go_vod"
) )
const VERSION = "0.1.22" const VERSION = "0.1.23"
func main() { func main() {
// Build initial configuration // Build initial configuration