monorepo
Varun Patil 2022-11-10 09:39:09 -08:00
parent 91c6a43fc1
commit 75d2768fe6
4 changed files with 22 additions and 20 deletions

View File

@ -3,5 +3,5 @@ package main
type Config struct { type Config struct {
ffmpeg string ffmpeg string
ffprobe string ffprobe string
chunkSize float64 chunkSize int
} }

View File

@ -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)

View File

@ -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 {

View File

@ -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