Tuning
parent
91c6a43fc1
commit
75d2768fe6
|
@ -3,5 +3,5 @@ package main
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ffmpeg string
|
ffmpeg string
|
||||||
ffprobe string
|
ffprobe string
|
||||||
chunkSize float64
|
chunkSize int
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -111,7 +111,7 @@ func main() {
|
||||||
h := NewHandler(&Config{
|
h := NewHandler(&Config{
|
||||||
ffmpeg: "ffmpeg",
|
ffmpeg: "ffmpeg",
|
||||||
ffprobe: "ffprobe",
|
ffprobe: "ffprobe",
|
||||||
chunkSize: 2.0,
|
chunkSize: 3,
|
||||||
})
|
})
|
||||||
|
|
||||||
http.Handle("/", h)
|
http.Handle("/", h)
|
||||||
|
|
14
manager.go
14
manager.go
|
@ -42,15 +42,15 @@ func NewManager(c *Config, path string, id string, close chan string) (*Manager,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m.numChunks = int(math.Ceil(m.probe.Duration.Seconds() / 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: 945000}
|
m.streams["360p"] = &Stream{c: c, m: m, quality: "360p", height: 360, width: 640, bitrate: 800000}
|
||||||
m.streams["480p"] = &Stream{c: c, m: m, quality: "480p", height: 480, width: 640, bitrate: 1365000}
|
m.streams["480p"] = &Stream{c: c, m: m, quality: "480p", height: 480, width: 640, bitrate: 1500000}
|
||||||
m.streams["720p"] = &Stream{c: c, m: m, quality: "720p", height: 720, width: 1280, bitrate: 3045000}
|
m.streams["720p"] = &Stream{c: c, m: m, quality: "720p", height: 720, width: 1280, bitrate: 3000000}
|
||||||
m.streams["1080p"] = &Stream{c: c, m: m, quality: "1080p", height: 1080, width: 1920, bitrate: 6045000}
|
m.streams["1080p"] = &Stream{c: c, m: m, quality: "1080p", height: 1080, width: 1920, bitrate: 5000000}
|
||||||
m.streams["1440p"] = &Stream{c: c, m: m, quality: "1440p", height: 1440, width: 2560, bitrate: 9045000}
|
m.streams["1440p"] = &Stream{c: c, m: m, quality: "1440p", height: 1440, width: 2560, bitrate: 9000000}
|
||||||
m.streams["2160p"] = &Stream{c: c, m: m, quality: "2160p", height: 2160, width: 3840, bitrate: 14045000}
|
m.streams["2160p"] = &Stream{c: c, m: m, quality: "2160p", height: 2160, width: 3840, bitrate: 14000000}
|
||||||
|
|
||||||
// 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 {
|
||||||
|
|
24
stream.go
24
stream.go
|
@ -51,12 +51,12 @@ func (s *Stream) ServeList(w http.ResponseWriter) error {
|
||||||
w.Write([]byte("#EXT-X-VERSION:4\n"))
|
w.Write([]byte("#EXT-X-VERSION:4\n"))
|
||||||
w.Write([]byte("#EXT-X-MEDIA-SEQUENCE:0\n"))
|
w.Write([]byte("#EXT-X-MEDIA-SEQUENCE:0\n"))
|
||||||
w.Write([]byte("#EXT-X-PLAYLIST-TYPE:VOD\n"))
|
w.Write([]byte("#EXT-X-PLAYLIST-TYPE:VOD\n"))
|
||||||
w.Write([]byte(fmt.Sprintf("#EXT-X-TARGETDURATION:%.3f\n", s.c.chunkSize)))
|
w.Write([]byte(fmt.Sprintf("#EXT-X-TARGETDURATION:%d\n", s.c.chunkSize)))
|
||||||
|
|
||||||
duration := s.m.probe.Duration.Seconds()
|
duration := s.m.probe.Duration.Seconds()
|
||||||
i := 0
|
i := 0
|
||||||
for duration > 0 {
|
for duration > 0 {
|
||||||
size := s.c.chunkSize
|
size := float64(s.c.chunkSize)
|
||||||
if duration < size {
|
if duration < size {
|
||||||
size = duration
|
size = duration
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ func (s *Stream) ServeList(w http.ResponseWriter) error {
|
||||||
w.Write([]byte(fmt.Sprintf("#EXTINF:%.3f, nodesc\n", size)))
|
w.Write([]byte(fmt.Sprintf("#EXTINF:%.3f, nodesc\n", size)))
|
||||||
w.Write([]byte(fmt.Sprintf("%s-%06d.ts\n", s.quality, i)))
|
w.Write([]byte(fmt.Sprintf("%s-%06d.ts\n", s.quality, i)))
|
||||||
|
|
||||||
duration -= s.c.chunkSize
|
duration -= float64(s.c.chunkSize)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ func (s *Stream) restartAtChunk(w http.ResponseWriter, id int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) transcode(startId int) {
|
func (s *Stream) transcode(startId int) {
|
||||||
startAt := float64(startId) * s.c.chunkSize
|
startAt := float64(startId * s.c.chunkSize)
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-loglevel", "warning",
|
"-loglevel", "warning",
|
||||||
|
@ -238,13 +238,14 @@ func (s *Stream) transcode(startId int) {
|
||||||
"-vf", scale,
|
"-vf", scale,
|
||||||
"-c:v", CV,
|
"-c:v", CV,
|
||||||
"-profile:v", "high",
|
"-profile:v", "high",
|
||||||
"-b:v", fmt.Sprintf("%dk", s.bitrate/1000),
|
"-maxrate", fmt.Sprintf("%dk", s.bitrate/1000),
|
||||||
|
"-bufsize", fmt.Sprintf("%dK", s.bitrate/3000),
|
||||||
}...)
|
}...)
|
||||||
|
|
||||||
// Extra args only for x264
|
// Extra args only for x264
|
||||||
if !VAAPI {
|
if !VAAPI {
|
||||||
args = append(args, []string{
|
args = append(args, []string{
|
||||||
"-preset", "faster",
|
"-preset", "fast",
|
||||||
"-level:v", "4.0",
|
"-level:v", "4.0",
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
@ -258,11 +259,9 @@ func (s *Stream) transcode(startId int) {
|
||||||
// Segmenting specs
|
// Segmenting specs
|
||||||
args = append(args, []string{
|
args = append(args, []string{
|
||||||
"-avoid_negative_ts", "disabled",
|
"-avoid_negative_ts", "disabled",
|
||||||
"-max_muxing_queue_size", "2048",
|
|
||||||
"-f", "hls",
|
"-f", "hls",
|
||||||
"-max_delay", "5000000",
|
"-hls_time", fmt.Sprintf("%d", s.c.chunkSize),
|
||||||
"-hls_time", fmt.Sprintf("%.6f", s.c.chunkSize),
|
"-g", fmt.Sprintf("%d", s.c.chunkSize),
|
||||||
"-g", fmt.Sprintf("%.6f", s.c.chunkSize),
|
|
||||||
"-hls_segment_type", "mpegts",
|
"-hls_segment_type", "mpegts",
|
||||||
"-start_number", fmt.Sprintf("%d", startId),
|
"-start_number", fmt.Sprintf("%d", startId),
|
||||||
"-hls_segment_filename", s.getTsPath(-1),
|
"-hls_segment_filename", s.getTsPath(-1),
|
||||||
|
@ -270,7 +269,7 @@ func (s *Stream) transcode(startId int) {
|
||||||
}...)
|
}...)
|
||||||
|
|
||||||
s.coder = exec.Command(s.c.ffmpeg, args...)
|
s.coder = exec.Command(s.c.ffmpeg, args...)
|
||||||
// log.Println("Starting FFmpeg process with args", strings.Join(s.coder.Args[:], " "))
|
log.Println("Starting FFmpeg process with args", strings.Join(s.coder.Args[:], " "))
|
||||||
|
|
||||||
cmdStdOut, err := s.coder.StdoutPipe()
|
cmdStdOut, err := s.coder.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -358,6 +357,9 @@ func (s *Stream) monitorTranscodeOutput(cmdStdOut io.ReadCloser, startAt float64
|
||||||
|
|
||||||
// Notify everyone
|
// Notify everyone
|
||||||
chunk := s.createChunk(id)
|
chunk := s.createChunk(id)
|
||||||
|
if chunk.done {
|
||||||
|
return
|
||||||
|
}
|
||||||
chunk.done = true
|
chunk.done = true
|
||||||
for _, n := range chunk.notifs {
|
for _, n := range chunk.notifs {
|
||||||
n <- true
|
n <- true
|
||||||
|
|
Loading…
Reference in New Issue