ok trnscode swp

This commit is contained in:
Olive Vaughn 2026-08-26 02:16:50 -04:00
parent 54668c0d93
commit e9766de877
12 changed files with 221 additions and 243 deletions

View file

@ -1,139 +0,0 @@
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 9bbe037..c0297fe 100644
--- a/hlsvod/transcode.go
+++ b/hlsvod/transcode.go
@@ -5,6 +5,7 @@ import (
"context"
"fmt"
"log"
+ "os"
"os/exec"
"path"
"strings"
@@ -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
}...)
}
+ // 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",
+ }...)
+ if hardwareDecode {
+ args = append(args, "-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi")
+ }
+ }
+
// Input specs
args = append(args, []string{
"-i", config.InputFilePath, // Input file
@@ -89,14 +106,30 @@ func TranscodeSegments(ctx context.Context, ffmpegBinary string, config Transcod
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)
+ }
+ if !hardwareDecode {
+ scale = "format=nv12,hwupload," + scale
+ }
+ args = append(args, []string{
+ "-vf", scale, "-c:v", "h264_vaapi", "-profile:v", "high",
+ "-level:v", "4.0", "-rc_mode", "VBR",
+ "-b:v", fmt.Sprintf("%dk", profile.Bitrate),
+ "-maxrate", fmt.Sprintf("%dk", profile.Bitrate*3/2),
+ "-bufsize", fmt.Sprintf("%dk", profile.Bitrate*2),
+ "-bf", "2", "-compression_level", "0",
+ }...)
+ } 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
@@ -106,12 +127,15 @@ func TranscodeSegments(ctx context.Context, ffmpegBinary string, config Transcod
args = append(args, []string{
"-c:a", "aac",
"-b:a", fmt.Sprintf("%dk", profile.Bitrate),
+ "-af", "aresample=async=1:min_hard_comp=0.100",
}...)
}
// Segmenting specs
args = append(args, []string{
"-f", "segment",
+ "-muxdelay", "0",
+ "-muxpreload", "0",
"-segment_time_delta", "0.2",
"-segment_format", "mpegts",
"-segment_times", commaSeparatedSegTimes,

View file

@ -0,0 +1,69 @@
diff --git a/transcoder/handler.go b/transcoder/handler.go
index 8c5bb08..0ad7458 100644
--- a/transcoder/handler.go
+++ b/transcoder/handler.go
@@ -37,6 +37,14 @@ func NewHandler(c *Config) *Handler {
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
+ w.Header().Set("Access-Control-Allow-Methods", "GET, HEAD, OPTIONS")
+ w.Header().Set("Access-Control-Allow-Headers", "Range, Content-Type")
+ if r.Method == http.MethodOptions {
+ w.WriteHeader(http.StatusNoContent)
+ return
+ }
+
// Check version if monitoring is enabled
if h.c.VersionMonitor && !h.versionOk(w, r) {
return
@@ -55,15 +63,15 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
// Serve actual file from manager
- if len(parts) < 3 {
+ if len(parts) < 5 || parts[0] != "vod" {
log.Println("Invalid URL", url)
w.WriteHeader(http.StatusBadRequest)
return
}
// Get streamid and chunk
- streamid := parts[0]
- path := "/" + strings.Join(parts[1:len(parts)-1], "/")
+ streamid := parts[1]
+ path := "/" + strings.Join(parts[2:len(parts)-1], "/")
chunk := parts[len(parts)-1]
// Check if POST request to create temp file
diff --git a/transcoder/stream.go b/transcoder/stream.go
index cf353fc..f8694fc 100644
--- a/transcoder/stream.go
+++ b/transcoder/stream.go
@@ -370,8 +370,12 @@ func (s *Stream) transcodeArgs(startAt float64, isHls bool) []string {
// Check whether hwaccel should be used
if s.c.VAAPI {
CV = ENCODER_VAAPI
- extra := "-hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi -init_hw_device vaapi=memories:/dev/dri/renderD128 -filter_hw_device memories"
+ extra := "-init_hw_device vaapi=memories:/dev/dri/renderD128 -filter_hw_device memories"
args = append(args, strings.Split(extra, " ")...)
+ if s.m.probe.CodecName == CODEC_H264 {
+ extra = "-hwaccel vaapi -hwaccel_device /dev/dri/renderD128 -hwaccel_output_format vaapi"
+ args = append(args, strings.Split(extra, " ")...)
+ }
} else if s.c.NVENC {
CV = ENCODER_NVENC
extra := "-hwaccel cuda"
@@ -397,7 +401,11 @@ func (s *Stream) transcodeArgs(startAt float64, isHls bool) []string {
scalerArgs = append(scalerArgs, "force_original_aspect_ratio=decrease")
if CV == ENCODER_VAAPI {
- format = "format=nv12|vaapi,hwupload"
+ if s.m.probe.CodecName == CODEC_H264 {
+ format = "format=nv12|vaapi,hwupload"
+ } else {
+ format = "format=nv12,hwupload"
+ }
scaler = "scale_vaapi"
scalerArgs = append(scalerArgs, "format=nv12")
} else if CV == ENCODER_NVENC {