diff --git a/config.go b/config.go index 277417b7..5b976860 100644 --- a/config.go +++ b/config.go @@ -3,5 +3,5 @@ package main type Config struct { ffmpeg string ffprobe string - chunkSize float64 + chunkSize int } diff --git a/main.go b/main.go index d2c4c11d..be5f60af 100644 --- a/main.go +++ b/main.go @@ -111,7 +111,7 @@ func main() { h := NewHandler(&Config{ ffmpeg: "ffmpeg", ffprobe: "ffprobe", - chunkSize: 2.0, + chunkSize: 3, }) http.Handle("/", h) diff --git a/manager.go b/manager.go index c0ee8600..fefb26de 100644 --- a/manager.go +++ b/manager.go @@ -42,15 +42,15 @@ func NewManager(c *Config, path string, id string, close chan string) (*Manager, 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 - m.streams["360p"] = &Stream{c: c, m: m, quality: "360p", height: 360, width: 640, bitrate: 945000} - m.streams["480p"] = &Stream{c: c, m: m, quality: "480p", height: 480, width: 640, bitrate: 1365000} - m.streams["720p"] = &Stream{c: c, m: m, quality: "720p", height: 720, width: 1280, bitrate: 3045000} - m.streams["1080p"] = &Stream{c: c, m: m, quality: "1080p", height: 1080, width: 1920, bitrate: 6045000} - m.streams["1440p"] = &Stream{c: c, m: m, quality: "1440p", height: 1440, width: 2560, bitrate: 9045000} - m.streams["2160p"] = &Stream{c: c, m: m, quality: "2160p", height: 2160, width: 3840, bitrate: 14045000} + 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: 1500000} + 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: 5000000} + 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: 14000000} // Only keep streams that are smaller than the video for k, stream := range m.streams { diff --git a/stream.go b/stream.go index a3965382..43486e71 100644 --- a/stream.go +++ b/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-MEDIA-SEQUENCE:0\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() i := 0 for duration > 0 { - size := s.c.chunkSize + size := float64(s.c.chunkSize) if duration < size { 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("%s-%06d.ts\n", s.quality, i))) - duration -= s.c.chunkSize + duration -= float64(s.c.chunkSize) i++ } @@ -192,7 +192,7 @@ func (s *Stream) restartAtChunk(w http.ResponseWriter, id int) { } func (s *Stream) transcode(startId int) { - startAt := float64(startId) * s.c.chunkSize + startAt := float64(startId * s.c.chunkSize) args := []string{ "-loglevel", "warning", @@ -238,13 +238,14 @@ func (s *Stream) transcode(startId int) { "-vf", scale, "-c:v", CV, "-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 if !VAAPI { args = append(args, []string{ - "-preset", "faster", + "-preset", "fast", "-level:v", "4.0", }...) } @@ -258,11 +259,9 @@ func (s *Stream) transcode(startId int) { // Segmenting specs args = append(args, []string{ "-avoid_negative_ts", "disabled", - "-max_muxing_queue_size", "2048", "-f", "hls", - "-max_delay", "5000000", - "-hls_time", fmt.Sprintf("%.6f", s.c.chunkSize), - "-g", fmt.Sprintf("%.6f", s.c.chunkSize), + "-hls_time", fmt.Sprintf("%d", s.c.chunkSize), + "-g", fmt.Sprintf("%d", s.c.chunkSize), "-hls_segment_type", "mpegts", "-start_number", fmt.Sprintf("%d", startId), "-hls_segment_filename", s.getTsPath(-1), @@ -270,7 +269,7 @@ func (s *Stream) transcode(startId int) { }...) 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() if err != nil { @@ -358,6 +357,9 @@ func (s *Stream) monitorTranscodeOutput(cmdStdOut io.ReadCloser, startAt float64 // Notify everyone chunk := s.createChunk(id) + if chunk.done { + return + } chunk.done = true for _, n := range chunk.notifs { n <- true