From 10c2727a388afa27c7a97b421f7f2376be6c994b Mon Sep 17 00:00:00 2001 From: sergystepanov Date: Fri, 12 Jun 2026 16:39:41 +0300 Subject: [PATCH] Move keyframe interval to common Video config and set it to 120 frames --- pkg/config/worker.go | 16 +++++++------- pkg/encoder/encoder.go | 4 ++-- pkg/encoder/h264/x264.go | 8 +++++-- pkg/encoder/h264/x264_test.go | 4 ++-- pkg/encoder/vpx/libvpx.go | 38 ++++++++++++++-------------------- pkg/worker/media/media_test.go | 17 +++++++-------- 6 files changed, 41 insertions(+), 46 deletions(-) diff --git a/pkg/config/worker.go b/pkg/config/worker.go index f0dc80d8..9a156430 100644 --- a/pkg/config/worker.go +++ b/pkg/config/worker.go @@ -56,9 +56,10 @@ type Audio struct { } type Video struct { - Codec string - Threads int - H264 struct { + Codec string + KeyframeInterval int + Threads int + H264 struct { Mode string Crf uint8 MaxRate int @@ -69,11 +70,10 @@ type Video struct { Tune string } Vpx struct { - Bitrate uint - KeyframeInterval uint - CpuUsed int - TileColumns int - Tune string + Bitrate uint + CpuUsed int + TileColumns int + Tune string } } diff --git a/pkg/encoder/encoder.go b/pkg/encoder/encoder.go index 0372c2c5..5aa3886a 100644 --- a/pkg/encoder/encoder.go +++ b/pkg/encoder/encoder.go @@ -53,14 +53,14 @@ func NewVideoEncoder(w, h, dw, dh int, scale float64, conf config.Video, log *lo switch codec { case H264: opts := h264.Options(conf.H264) - enc, err = h264.NewEncoder(dw, dh, conf.Threads, &opts) + enc, err = h264.NewEncoder(dw, dh, conf.Threads, conf.KeyframeInterval, &opts) case VP8, VP9, VPX: opts := vpx.Options(conf.Vpx) v := 8 if codec == VP9 { v = 9 } - enc, err = vpx.NewEncoder(dw, dh, conf.Threads, v, &opts) + enc, err = vpx.NewEncoder(dw, dh, conf.Threads, conf.KeyframeInterval, v, &opts) default: err = fmt.Errorf("unsupported codec: %v", conf.Codec) } diff --git a/pkg/encoder/h264/x264.go b/pkg/encoder/h264/x264.go index e0ce43ef..08c310cd 100644 --- a/pkg/encoder/h264/x264.go +++ b/pkg/encoder/h264/x264.go @@ -98,7 +98,7 @@ type Options struct { Tune string } -func NewEncoder(w, h int, th int, opts *Options) (encoder *H264, err error) { +func NewEncoder(w, h int, th int, kfi int, opts *Options) (encoder *H264, err error) { ver := Version() if ver < 150 { @@ -146,7 +146,11 @@ func NewEncoder(w, h int, th int, opts *Options) (encoder *H264, err error) { param.i_width = C.int(w) param.i_height = C.int(h) param.i_log_level = C.int(opts.LogLevel) - param.i_keyint_max = 120 + if kfi > 0 { + param.i_keyint_max = C.int(kfi) + } else { + param.i_keyint_max = 120 + } param.i_sync_lookahead = 0 param.i_threads = C.int(th) if th != 1 { diff --git a/pkg/encoder/h264/x264_test.go b/pkg/encoder/h264/x264_test.go index 822e4cec..2a98bdb5 100644 --- a/pkg/encoder/h264/x264_test.go +++ b/pkg/encoder/h264/x264_test.go @@ -3,7 +3,7 @@ package h264 import "testing" func TestH264Encode(t *testing.T) { - h264, err := NewEncoder(120, 120, 0, nil) + h264, err := NewEncoder(120, 120, 0, 120, nil) if err != nil { t.Error(err) return @@ -17,7 +17,7 @@ func TestH264Encode(t *testing.T) { func Benchmark(b *testing.B) { w, h := 1920, 1080 - h264, err := NewEncoder(w, h, 0, nil) + h264, err := NewEncoder(w, h, 0, 120, nil) if err != nil { b.Error(err) return diff --git a/pkg/encoder/vpx/libvpx.go b/pkg/encoder/vpx/libvpx.go index 33b3b573..fb64c7d6 100644 --- a/pkg/encoder/vpx/libvpx.go +++ b/pkg/encoder/vpx/libvpx.go @@ -127,10 +127,7 @@ func autoThreads(configured, cpus int) int { if configured != 0 { return configured } - reserve := cpus / 4 - if reserve < 1 { - reserve = 1 - } + reserve := max(cpus/4, 1) if t := cpus - reserve; t > 0 { return t } @@ -140,8 +137,6 @@ func autoThreads(configured, cpus int) int { type Options struct { // Target bandwidth to use for this stream, in kilobits per second. Bitrate uint - // Force keyframe interval. - KeyframeInterval uint // Speed/quality tradeoff (0=auto, 1–8 manual). Defaults to 0. // Applies to both VP8 and VP9. CpuUsed int @@ -151,28 +146,21 @@ type Options struct { Tune string } -func NewEncoder(w, h int, th int, version int, opts *Options) (*Vpx, error) { - idx := 0 - if version == 9 { - idx = 1 - } - encoder := &C.vpx_encoders[idx] - if encoder == nil { - return nil, fmt.Errorf("couldn't get the encoder") - } - +func NewEncoder(w, h int, th int, kfi int, version int, opts *Options) (*Vpx, error) { if opts == nil { opts = &Options{ - Bitrate: 1200, - KeyframeInterval: 120, - TileColumns: 2, - Tune: "screen", + Bitrate: 1200, + TileColumns: 2, + Tune: "screen", } } + if kfi == 0 { + kfi = 120 + } vpx := Vpx{ frameCount: C.int(0), - kfi: C.int(opts.KeyframeInterval), + kfi: C.int(kfi), v: version, } @@ -180,6 +168,12 @@ func NewEncoder(w, h int, th int, version int, opts *Options) (*Vpx, error) { return nil, fmt.Errorf("vpx_img_alloc failed") } + idx := 0 + if version == 9 { + idx = 1 + } + encoder := &C.vpx_encoders[idx] + var cfg C.vpx_codec_enc_cfg_t if C.call_vpx_codec_enc_config_default(encoder, &cfg) != 0 { return nil, fmt.Errorf("failed to get default codec config") @@ -274,9 +268,7 @@ func (vpx *Vpx) IntraRefresh() { } func (vpx *Vpx) Shutdown() error { - //if &vpx.image != nil { C.vpx_img_free(&vpx.image) - //} C.vpx_codec_destroy(&vpx.codecCtx) vpx.flipped = false return nil diff --git a/pkg/worker/media/media_test.go b/pkg/worker/media/media_test.go index 829ebe13..16fb758f 100644 --- a/pkg/worker/media/media_test.go +++ b/pkg/worker/media/media_test.go @@ -37,8 +37,9 @@ func BenchmarkVP8(b *testing.B) { run(1920, 1080, encoder.VP8, b.N, nil, nil, b func run(w, h int, cod encoder.VideoCodec, count int, a *image.RGBA, b *image.RGBA, backend testing.TB) { conf := config.Video{ - Codec: string(cod), - Threads: 0, + Codec: string(cod), + Threads: 0, + KeyframeInterval: 120, H264: struct { Mode string Crf uint8 @@ -56,14 +57,12 @@ func run(w, h int, cod encoder.VideoCodec, count int, a *image.RGBA, b *image.RG Tune: "zerolatency", }, Vpx: struct { - Bitrate uint - KeyframeInterval uint - CpuUsed int - TileColumns int - Tune string + Bitrate uint + CpuUsed int + TileColumns int + Tune string }{ - Bitrate: 1000, - KeyframeInterval: 5, + Bitrate: 1000, }, }