From a71fe4bb28a5040d7412207b7352f0fac6fb9a2e Mon Sep 17 00:00:00 2001 From: Olive Vaughn Date: Wed, 26 Aug 2026 01:24:51 -0400 Subject: [PATCH] ptch it bro --- Dockerfile.transcode | 36 ++++++++++++++++++ config.example.yaml | 44 ++++++++++------------ docker-compose.yml | 5 ++- patches/go-transcode-vaapi.patch | 63 ++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 26 deletions(-) create mode 100644 Dockerfile.transcode create mode 100644 patches/go-transcode-vaapi.patch diff --git a/Dockerfile.transcode b/Dockerfile.transcode new file mode 100644 index 0000000..fba8eea --- /dev/null +++ b/Dockerfile.transcode @@ -0,0 +1,36 @@ +FROM golang:1.23-alpine AS builder + +ARG GO_TRANSCODE_COMMIT=f8137e68c7b8da88c51aec9563eec9585c10c723 +WORKDIR /src + +RUN apk add --no-cache git +RUN git clone https://github.com/m1k1o/go-transcode.git . \ + && git checkout "$GO_TRANSCODE_COMMIT" + +COPY patches/go-transcode-vaapi.patch /tmp/go-transcode-vaapi.patch +RUN git apply /tmp/go-transcode-vaapi.patch \ + && CGO_ENABLED=0 go build -o /go-transcode . + +# Keep Alpine 3.17: upstream documents an FFmpeg 6 segmenting regression with +# newer Alpine releases. Install both Intel and Mesa VAAPI drivers so this also +# works if the Unraid host exposes an AMD render device. +FROM alpine:3.17 +WORKDIR /app + +RUN echo "https://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ + && apk add --no-cache \ + bash \ + ffmpeg \ + intel-media-driver \ + libva-intel-driver \ + libva-utils \ + mesa-va-gallium + +COPY --from=builder /go-transcode /app/go-transcode + +EXPOSE 8080 +ENV TRANSCODE_BIND=:8080 \ + TRANSCODE_VAAPI_DEVICE=/dev/dri/renderD128 + +ENTRYPOINT ["/app/go-transcode"] +CMD ["serve"] diff --git a/config.example.yaml b/config.example.yaml index c53f771..941bb91 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -1,33 +1,27 @@ -# go-transcode configuration for VAAPI hardware encoding -# Copy this to go-transcode/config.yaml and adjust as needed +# go-transcode VOD configuration. Hardware encoding is enabled by the +# TRANSCODE_VAAPI_DEVICE environment variable in docker-compose.yml. vod: media-dir: /media transcode-dir: /tmp/go-transcode - # Cache transcoded segments cache: true + cache-dir: /cache + video-keyframes: true + video-profiles: + 480p: + width: 854 + height: 480 + bitrate: 1200 -profiles: - 480p: - height: 480 - videoBitrate: 1500k - audioBitrate: 128k - hwaccel: vaapi - vaapi-device: /dev/dri/renderD128 - codec: h264_vaapi + 720p: + width: 1280 + height: 720 + bitrate: 3000 - 720p: - height: 720 - videoBitrate: 3000k - audioBitrate: 192k - hwaccel: vaapi - vaapi-device: /dev/dri/renderD128 - codec: h264_vaapi + 1080p: + width: 1920 + height: 1080 + bitrate: 6000 - 1080p: - height: 1080 - videoBitrate: 6000k - audioBitrate: 256k - hwaccel: vaapi - vaapi-device: /dev/dri/renderD128 - codec: h264_vaapi + audio-profile: + bitrate: 192 diff --git a/docker-compose.yml b/docker-compose.yml index c122fb5..e41e023 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,9 +14,12 @@ services: transcode: build: - context: https://github.com/m1k1o/go-transcode.git + context: . + dockerfile: Dockerfile.transcode devices: - /dev/dri:/dev/dri + environment: + - TRANSCODE_VAAPI_DEVICE=/dev/dri/renderD128 volumes: - /mnt/user/plex:/media:ro - ./transcode-config.yaml:/app/config.yaml:ro diff --git a/patches/go-transcode-vaapi.patch b/patches/go-transcode-vaapi.patch new file mode 100644 index 0000000..437595f --- /dev/null +++ b/patches/go-transcode-vaapi.patch @@ -0,0 +1,63 @@ +diff --git a/hlsvod/transcode.go b/hlsvod/transcode.go +index 1b04b00..12eb935 100644 +--- a/hlsvod/transcode.go ++++ b/hlsvod/transcode.go +@@ -6,5 +6,6 @@ import ( + "fmt" + "log" ++ "os" + "os/exec" + "path" + "strings" +@@ -56,6 +57,16 @@ func TranscodeSegments(ctx context.Context, ffmpegBinary string, config Transcod + }...) + } + ++ // Decode and filter on the GPU when a VAAPI render device is configured. ++ // This is opt-in so upstream's software behavior remains available. ++ vaapiDevice := os.Getenv("TRANSCODE_VAAPI_DEVICE") ++ if vaapiDevice != "" { ++ args = append(args, []string{ ++ "-init_hw_device", "vaapi=va:" + vaapiDevice, ++ "-filter_hw_device", "va", "-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi", ++ }...) ++ } ++ + // Input specs + args = append(args, []string{ + "-i", config.InputFilePath, // Input file +@@ -79,17 +89,26 @@ func TranscodeSegments(ctx context.Context, ffmpegBinary string, config Transcod + if profile.Width >= profile.Height { + scale = fmt.Sprintf("scale=-2:%d", profile.Height) + } else { + scale = fmt.Sprintf("scale=%d:-2", profile.Width) + } + +- args = append(args, []string{ +- "-vf", scale, +- "-c:v", "libx264", +- "-preset", "faster", +- "-profile:v", "high", +- "-level:v", "4.0", +- "-b:v", fmt.Sprintf("%dk", profile.Bitrate), +- }...) ++ if vaapiDevice != "" { ++ if profile.Width >= profile.Height { ++ scale = fmt.Sprintf("scale_vaapi=w=-2:h=%d:format=nv12", profile.Height) ++ } else { ++ scale = fmt.Sprintf("scale_vaapi=w=%d:h=-2:format=nv12", profile.Width) ++ } ++ args = append(args, []string{ ++ "-vf", scale, "-c:v", "h264_vaapi", "-profile:v", "high", ++ "-level:v", "4.0", "-b:v", fmt.Sprintf("%dk", profile.Bitrate), ++ }...) ++ } else { ++ args = append(args, []string{ ++ "-vf", scale, "-c:v", "libx264", "-preset", "faster", ++ "-profile:v", "high", "-level:v", "4.0", ++ "-b:v", fmt.Sprintf("%dk", profile.Bitrate), ++ }...) ++ } + } + + // Audio specs