add: SVT-AV1 lp (thread cap) config knob

Add encoding.lp (0 = auto) so a long encode can be capped to N logical
processors instead of pinning every core, as a lighter-weight alternative to
the compose cgroup limit. Threaded config -> types.Job -> -svtav1-params via a
testable svtav1Params helper. Settings-UI surfacing stays with #1.

refs #5
This commit is contained in:
Esa Kataja
2026-06-21 19:37:26 +03:00
parent 9bb7c72c1a
commit 80b602fbbb
5 changed files with 43 additions and 1 deletions
+1
View File
@@ -192,6 +192,7 @@ func processFile(ctx context.Context, inputPath string, cfg *types.Config, enc *
MediaType: mediaType, MediaType: mediaType,
CRF: crf, CRF: crf,
Preset: preset, Preset: preset,
LP: cfg.Encoding.LP,
DeleteOrigin: deleteOrigin, DeleteOrigin: deleteOrigin,
} }
+3
View File
@@ -11,6 +11,9 @@ encoding:
bluray: bluray:
crf: 29 crf: 29
preset: 3 preset: 3
# SVT-AV1 logical-processor (thread) cap so a long encode can't pin every core.
# 0 = auto (use all cores). Applies to every profile.
lp: 0
paths: paths:
input: "./input" input: "./input"
+12 -1
View File
@@ -403,6 +403,17 @@ func (e *Encoder) encodeOpus(ctx context.Context, wavs []string, workDir string)
return opusFiles, nil return opusFiles, nil
} }
// svtav1Params builds the -svtav1-params value, appending lp=N (logical
// processors / encoder thread count) only when lp > 0. lp=0 lets SVT-AV1
// auto-detect, preserving prior behavior.
func svtav1Params(lp int) string {
p := "film-grain=10:film-grain-denoise=1:scd=1:qm-min=4:qm-max=15:keyint=10s"
if lp > 0 {
p += fmt.Sprintf(":lp=%d", lp)
}
return p
}
func (e *Encoder) encodeVideo(ctx context.Context, input, workDir string, opusFiles []string, job *types.Job, metadata *types.Metadata, interlaced bool, streamLangs []StreamMetadata) error { func (e *Encoder) encodeVideo(ctx context.Context, input, workDir string, opusFiles []string, job *types.Job, metadata *types.Metadata, interlaced bool, streamLangs []StreamMetadata) error {
outFile := filepath.Join(workDir, "output.mkv") outFile := filepath.Join(workDir, "output.mkv")
@@ -418,7 +429,7 @@ func (e *Encoder) encodeVideo(ctx context.Context, input, workDir string, opusFi
} }
} }
svtParams := fmt.Sprintf("film-grain=10:film-grain-denoise=1:scd=1:qm-min=4:qm-max=15:keyint=10s") svtParams := svtav1Params(job.LP)
zscaleStr, newWidth, err := e.calculateZscaleWidth(ctx, input, 0) zscaleStr, newWidth, err := e.calculateZscaleWidth(ctx, input, 0)
if err != nil { if err != nil {
+23
View File
@@ -0,0 +1,23 @@
package encoder
import (
"strings"
"testing"
)
func TestSvtav1Params(t *testing.T) {
const base = "film-grain=10:film-grain-denoise=1:scd=1:qm-min=4:qm-max=15:keyint=10s"
if got := svtav1Params(0); got != base {
t.Errorf("lp=0 should not append lp:\n got %q\nwant %q", got, base)
}
if got := svtav1Params(-1); got != base {
t.Errorf("lp<0 should not append lp: got %q", got)
}
if got := svtav1Params(4); got != base+":lp=4" {
t.Errorf("lp=4: got %q, want suffix :lp=4", got)
}
if got := svtav1Params(4); !strings.HasPrefix(got, base) {
t.Errorf("lp set should keep the base params intact: got %q", got)
}
}
+4
View File
@@ -16,6 +16,7 @@ type Job struct {
Metadata *Metadata Metadata *Metadata
CRF int CRF int
Preset int Preset int
LP int // SVT-AV1 logical processors; 0 = auto
DeleteOrigin bool DeleteOrigin bool
} }
@@ -46,6 +47,9 @@ type EncodingConfig struct {
Bluray EncodingParams `yaml:"bluray"` Bluray EncodingParams `yaml:"bluray"`
WebDL EncodingParams `yaml:"webdl"` WebDL EncodingParams `yaml:"webdl"`
TVRip EncodingParams `yaml:"tvrip"` TVRip EncodingParams `yaml:"tvrip"`
// LP caps SVT-AV1's logical-processor (thread) count so a long encode can't
// pin every core. 0 = let SVT-AV1 auto-detect (default). Applies to all profiles.
LP int `yaml:"lp"`
} }
type EncodingParams struct { type EncodingParams struct {