diff --git a/docker-compose.nvidia.yml b/docker-compose.nvidia.yml new file mode 100644 index 00000000..44a35494 --- /dev/null +++ b/docker-compose.nvidia.yml @@ -0,0 +1,12 @@ +version: "3.8" + +services: + transcoder: + runtime: nvidia + deploy: + resources: + reservations: + devices: + - capabilities: [gpu] + environment: + - GOTRANSCODER_HWACCEL=nvidia diff --git a/transcoder/Dockerfile b/transcoder/Dockerfile index 95f62aeb..a4882850 100644 --- a/transcoder/Dockerfile +++ b/transcoder/Dockerfile @@ -2,6 +2,7 @@ FROM golang:1.21 as build RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ ffmpeg libavformat-dev libavutil-dev libswscale-dev libmediainfo-dev \ + && apt-get clean autoclean -y \ && apt-get autoremove -y WORKDIR /app COPY go.mod go.sum ./ diff --git a/transcoder/Dockerfile.dev b/transcoder/Dockerfile.dev index 843877ce..47acc5eb 100644 --- a/transcoder/Dockerfile.dev +++ b/transcoder/Dockerfile.dev @@ -2,6 +2,7 @@ FROM golang:1.21 RUN apt-get update \ && apt-get install --no-install-recommends --no-install-suggests -y \ ffmpeg libavformat-dev libavutil-dev libswscale-dev libmediainfo-dev \ + && apt-get clean autoclean -y \ && apt-get autoremove -y RUN go install github.com/bokwoon95/wgo@latest WORKDIR /app diff --git a/transcoder/src/hwaccel.go b/transcoder/src/hwaccel.go index 0405be6d..20e5a9d5 100644 --- a/transcoder/src/hwaccel.go +++ b/transcoder/src/hwaccel.go @@ -1,7 +1,11 @@ package src +import "log" + func DetectHardwareAccel() HwAccelT { - name := "disabled" + name := GetEnvOr("GOTRANSCODER_HWACCEL", "disabled") + log.Printf("Using hardware acceleration: %s", name) + switch name { case "nvidia": return HwAccelT{ @@ -17,6 +21,7 @@ func DetectHardwareAccel() HwAccelT { "-c:v", "h264_nvenc", "-preset", "fast", }, + ScaleFilter: "hwupload_cuda,scale_cuda=%d:%d:force_original_aspect_ratio=decrease", } default: return HwAccelT{ @@ -27,6 +32,7 @@ func DetectHardwareAccel() HwAccelT { // superfast or ultrafast would produce a file extremly big so we prever veryfast or faster. "-preset", "faster", }, + ScaleFilter: "scale=%d:%d:force_original_aspect_ratio=decrease", } } } diff --git a/transcoder/src/settings.go b/transcoder/src/settings.go index c54573e3..c6af123d 100644 --- a/transcoder/src/settings.go +++ b/transcoder/src/settings.go @@ -20,6 +20,7 @@ type HwAccelT struct { Name string DecodeFlags []string EncodeFlags []string + ScaleFilter string } var Settings = SettingsT{ diff --git a/transcoder/src/videostream.go b/transcoder/src/videostream.go index af476f22..5a936639 100644 --- a/transcoder/src/videostream.go +++ b/transcoder/src/videostream.go @@ -29,6 +29,16 @@ func (vs *VideoStream) getOutPath(encoder_id int) string { return fmt.Sprintf("%s/segment-%s-%d-%%d.ts", vs.file.Out, vs.quality, encoder_id) } +func closestMultiple(n int32, x int32) int32 { + if x > n { + return x + } + + n = n + x/2 + n = n - (n % x) + return n +} + func (vs *VideoStream) getTranscodeArgs(segments string) []string { args := []string{ "-map", "0:V:0", @@ -42,9 +52,11 @@ func (vs *VideoStream) getTranscodeArgs(segments string) []string { } args = append(args, Settings.HwAccel.EncodeFlags...) + width := int32(float64(vs.quality.Height()) / float64(vs.file.Info.Video.Height) * float64(vs.file.Info.Video.Width)) + // force a width that is a multiple of two else some apps behave badly. + width = closestMultiple(width, 2) args = append(args, - // resize but keep aspect ratio (also force a width that is a multiple of two else some apps behave badly. - "-vf", fmt.Sprintf("scale=-2:'min(%d,ih)'", vs.quality.Height()), + "-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),