From affe933fec3f7c2b54d800ef8674acb4e00d9221 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Fri, 6 Mar 2026 17:30:34 +0800 Subject: [PATCH] =?UTF-8?q?fix(video):=20=E8=A7=A3=E5=86=B3=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E6=97=B6=E9=97=B4=E6=88=B3=E5=A4=84=E7=90=86=E5=92=8C?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E5=8F=82=E6=95=B0=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 统一归零视频起始时间戳,避免源素材非 0 起始 PTS 造成封装后首帧冻结 - 修改 setpts 滤镜表达式为 setpts=PTS-STARTPTS 格式 - 为所有速度调整场景应用标准化的时间戳处理 - 添加视频编码参数测试文件,确保 B 帧在各种硬件加速下被禁用 - 为软件、QSV 和 CUDA 硬件加速添加 B 帧禁用测试用例 --- handlers/render_video.py | 5 ++++- tests/unit/test_render_video_effects.py | 25 ++++++++++++++++++++----- tests/unit/test_video_encode_args.py | 25 +++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 tests/unit/test_video_encode_args.py diff --git a/handlers/render_video.py b/handlers/render_video.py index 25f176c..9b2f2a6 100644 --- a/handlers/render_video.py +++ b/handlers/render_video.py @@ -725,8 +725,11 @@ class RenderSegmentTsHandler(BaseHandler): break combined_pts_factor = (1.0 / speed) * ospeed_factor + # 统一归零视频起始时间戳,避免源素材非 0 起始 PTS 造成封装后首帧冻结 if combined_pts_factor != 1.0: - filters.append(f"setpts={combined_pts_factor}*PTS") + filters.append(f"setpts={combined_pts_factor}*(PTS-STARTPTS)") + else: + filters.append("setpts=PTS-STARTPTS") # 2. LUT 调色 if lut_file: diff --git a/tests/unit/test_render_video_effects.py b/tests/unit/test_render_video_effects.py index 0a2aa1d..a8498f5 100644 --- a/tests/unit/test_render_video_effects.py +++ b/tests/unit/test_render_video_effects.py @@ -137,7 +137,22 @@ def test_ospeed_does_not_trigger_filter_complex(tmp_path): # 验证 setpts 滤镜 vf_idx = command.index('-vf') vf_value = command[vf_idx + 1] - assert 'setpts=2.0*PTS' in vf_value + assert 'setpts=2.0*(PTS-STARTPTS)' in vf_value + + +def test_default_speed_always_normalizes_pts(tmp_path): + handler = _create_handler(tmp_path) + render_spec = RenderSpec() + output_spec = OutputSpec(width=1080, height=1920, fps=30) + + filters = handler._build_video_filters( + render_spec=render_spec, + output_spec=output_spec, + duration_ms=6000, + source_duration_sec=10.0, + ) + + assert 'setpts=PTS-STARTPTS' in filters def test_ospeed_combined_with_speed(tmp_path): @@ -153,7 +168,7 @@ def test_ospeed_combined_with_speed(tmp_path): source_duration_sec=10.0, ) - assert 'setpts=1.5*PTS' in filters + assert 'setpts=1.5*(PTS-STARTPTS)' in filters def test_ospeed_with_complex_effects(tmp_path): @@ -171,7 +186,7 @@ def test_ospeed_with_complex_effects(tmp_path): # zoom 触发 filter_complex assert '[v_base]' in filters # setpts 在 base_chain 中 - assert 'setpts=2.0*PTS' in filters + assert 'setpts=2.0*(PTS-STARTPTS)' in filters # zoom 正常处理 assert "overlay=0:0:enable='between(t,1.0,3.0)'" in filters @@ -188,8 +203,8 @@ def test_only_first_ospeed_is_used(tmp_path): source_duration_sec=10.0, ) - assert 'setpts=2.0*PTS' in filters - assert 'setpts=5.0*PTS' not in filters + assert 'setpts=2.0*(PTS-STARTPTS)' in filters + assert 'setpts=5.0*(PTS-STARTPTS)' not in filters def test_ospeed_affects_tpad_calculation(tmp_path): diff --git a/tests/unit/test_video_encode_args.py b/tests/unit/test_video_encode_args.py new file mode 100644 index 0000000..527d355 --- /dev/null +++ b/tests/unit/test_video_encode_args.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from constant import HW_ACCEL_CUDA, HW_ACCEL_NONE, HW_ACCEL_QSV +from handlers.base import get_video_encode_args + + +def _assert_bframe_disabled(args): + assert '-bf' in args + bf_index = args.index('-bf') + assert args[bf_index + 1] == '0' + + +def test_get_video_encode_args_disable_b_frames_for_software(): + args = get_video_encode_args(HW_ACCEL_NONE) + _assert_bframe_disabled(args) + + +def test_get_video_encode_args_disable_b_frames_for_qsv(): + args = get_video_encode_args(HW_ACCEL_QSV) + _assert_bframe_disabled(args) + + +def test_get_video_encode_args_disable_b_frames_for_cuda(): + args = get_video_encode_args(HW_ACCEL_CUDA) + _assert_bframe_disabled(args)