better trnscode

This commit is contained in:
Olive Vaughn 2026-08-26 01:43:55 -04:00
parent e7255ea8a2
commit 8e7944f688
5 changed files with 75 additions and 14 deletions

View file

@ -1,35 +1,88 @@
diff --git a/hlsvod/manager.go b/hlsvod/manager.go
index 662c41d..51460f8 100644
--- a/hlsvod/manager.go
+++ b/hlsvod/manager.go
@@ -378,12 +378,17 @@ func (m *ManagerCtx) waitForSegment(index int) (chan struct{}, bool) {
func (m *ManagerCtx) transcodeSegments(offset, limit int) error {
logger := m.logger.With().Int("offset", offset).Int("limit", limit).Logger()
+ inputCodec := ""
+ if m.metadata.Video != nil {
+ inputCodec = m.metadata.Video.CodecName
+ }
segmentTimes := m.breakpoints[offset : offset+limit+1]
logger.Info().Interface("segments-times", segmentTimes).Msg("transcoding segments")
segments, err := TranscodeSegments(m.ctx, m.config.FFmpegBinary, TranscodeConfig{
InputFilePath: m.config.MediaPath,
+ InputCodec: inputCodec,
OutputDirPath: m.config.TranscodeDir,
SegmentPrefix: m.config.SegmentPrefix, // This does not need to match.
diff --git a/hlsvod/probe.go b/hlsvod/probe.go
index c39461c..58c3edd 100644
--- a/hlsvod/probe.go
+++ b/hlsvod/probe.go
@@ -83,6 +83,7 @@ func ProbeMedia(ctx context.Context, ffprobeBinary string, inputFilePath string)
}
data.Video = &ProbeVideoData{
+ CodecName: stream.CodecName,
Width: stream.Width,
Height: stream.Height,
Duration: duration,
@@ -118,6 +119,7 @@ func ProbeMedia(ctx context.Context, ffprobeBinary string, inputFilePath string)
}
type ProbeVideoData struct {
+ CodecName string
Width int
Height int
Duration time.Duration
diff --git a/hlsvod/transcode.go b/hlsvod/transcode.go
index 1b04b00..12eb935 100644
index 9bbe037..c0297fe 100644
--- a/hlsvod/transcode.go
+++ b/hlsvod/transcode.go
@@ -6,5 +6,6 @@ import (
@@ -5,6 +5,7 @@ import (
"context"
"fmt"
"log"
+ "os"
"os/exec"
"path"
"strings"
@@ -56,6 +57,16 @@ func TranscodeSegments(ctx context.Context, ffmpegBinary string, config Transcod
@@ -13,6 +14,7 @@ import (
type TranscodeConfig struct {
InputFilePath string // Transcoded video input.
+ InputCodec string // ffprobe codec name, e.g. h264 or hevc.
OutputDirPath string // Segments output path.
SegmentPrefix string // e.g. prefix-000001.ts
SegmentOffset int // Start segment number.
@@ -69,6 +71,21 @@ 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.
+ // Haswell can decode H.264 in hardware, but not HEVC Main 10. Use full
+ // hardware transcoding for H.264 and software decode plus VAAPI upload for
+ // other codecs. Scaling and H.264 encoding always remain on the GPU.
+ vaapiDevice := os.Getenv("TRANSCODE_VAAPI_DEVICE")
+ hardwareDecode := vaapiDevice != "" && config.InputCodec == "h264"
+ if vaapiDevice != "" {
+ args = append(args, []string{
+ "-init_hw_device", "vaapi=va:" + vaapiDevice,
+ "-filter_hw_device", "va", "-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi",
+ "-filter_hw_device", "va",
+ }...)
+ if hardwareDecode {
+ args = append(args, "-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 {
@@ -89,14 +106,26 @@ func TranscodeSegments(ctx context.Context, ffmpegBinary string, config Transcod
scale = fmt.Sprintf("scale=%d:-2", profile.Width)
}
@ -47,6 +100,9 @@ index 1b04b00..12eb935 100644
+ } else {
+ scale = fmt.Sprintf("scale_vaapi=w=%d:h=-2:format=nv12", profile.Width)
+ }
+ if !hardwareDecode {
+ scale = "format=nv12,hwupload," + scale
+ }
+ args = append(args, []string{
+ "-vf", scale, "-c:v", "h264_vaapi", "-profile:v", "high",
+ "-level:v", "4.0", "-b:v", fmt.Sprintf("%dk", profile.Bitrate),