From ca9033690557d07cef4e1f7b5ead8bc0efae64fb Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Wed, 4 Mar 2026 10:03:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(video):=20=E6=B7=BB=E5=8A=A0=E8=A7=86?= =?UTF-8?q?=E9=A2=91=E7=BC=96=E7=A0=81=E6=9C=80=E5=A4=A7=E7=A0=81=E7=8E=87?= =?UTF-8?q?=E9=99=90=E5=88=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 get_video_encode_args 函数中新增 maxrate 参数用于限制峰值码率 - 实现 CRF/CQ 模式下同时控制质量和峰值码率的功能 - 自动计算 bufsize 为 maxrate 的 2 倍值 - 更新 VideoHandler 类中的编码参数方法以传递码率限制 - 修改视频合成和渲染模块以应用输出规格中的码率设置 - 移除静态 VIDEO_ENCODE_ARGS 常量以支持动态参数生成 --- handlers/base.py | 25 +++++++++++++++++++------ handlers/compose_transition.py | 2 +- handlers/render_video.py | 6 +++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/handlers/base.py b/handlers/base.py index ca14fb9..93e9a84 100644 --- a/handlers/base.py +++ b/handlers/base.py @@ -42,19 +42,21 @@ if TYPE_CHECKING: logger = logging.getLogger(__name__) -def get_video_encode_args(hw_accel: str = HW_ACCEL_NONE) -> List[str]: +def get_video_encode_args(hw_accel: str = HW_ACCEL_NONE, maxrate: Optional[int] = None) -> List[str]: """ 根据硬件加速配置获取视频编码参数 Args: hw_accel: 硬件加速类型 (none, qsv, cuda) + maxrate: 最大码率(bps),用于限制 CRF/CQ 模式的峰值码率。 + 例如 4000000 表示 4Mbps。bufsize 自动设为 maxrate 的 2 倍。 Returns: FFmpeg 视频编码参数列表 """ if hw_accel == HW_ACCEL_QSV: params = VIDEO_ENCODE_PARAMS_QSV - return [ + args = [ '-c:v', params['codec'], '-preset', params['preset'], '-profile:v', params['profile'], @@ -64,7 +66,7 @@ def get_video_encode_args(hw_accel: str = HW_ACCEL_NONE) -> List[str]: ] elif hw_accel == HW_ACCEL_CUDA: params = VIDEO_ENCODE_PARAMS_CUDA - return [ + args = [ '-c:v', params['codec'], '-preset', params['preset'], '-profile:v', params['profile'], @@ -76,7 +78,7 @@ def get_video_encode_args(hw_accel: str = HW_ACCEL_NONE) -> List[str]: else: # 软件编码(默认) params = VIDEO_ENCODE_PARAMS - return [ + args = [ '-c:v', params['codec'], '-preset', params['preset'], '-profile:v', params['profile'], @@ -85,6 +87,14 @@ def get_video_encode_args(hw_accel: str = HW_ACCEL_NONE) -> List[str]: '-pix_fmt', params['pix_fmt'], ] + # CRF/CQ + maxrate 上限:保留质量控制的同时限制峰值码率 + if maxrate and maxrate > 0: + maxrate_k = f'{maxrate // 1000}k' + bufsize_k = f'{maxrate * 2 // 1000}k' + args.extend(['-maxrate', maxrate_k, '-bufsize', bufsize_k]) + + return args + def get_hwaccel_decode_args(hw_accel: str = HW_ACCEL_NONE, device_index: Optional[int] = None) -> List[str]: """ @@ -579,14 +589,17 @@ class BaseHandler(TaskHandler, ABC): # ========== FFmpeg 参数生成 ========== - def get_video_encode_args(self) -> List[str]: + def get_video_encode_args(self, maxrate: Optional[int] = None) -> List[str]: """ 获取当前配置的视频编码参数 + Args: + maxrate: 最大码率(bps),用于限制峰值码率 + Returns: FFmpeg 视频编码参数列表 """ - return get_video_encode_args(self.config.hw_accel) + return get_video_encode_args(self.config.hw_accel, maxrate=maxrate) def get_hwaccel_decode_args(self) -> List[str]: """ diff --git a/handlers/compose_transition.py b/handlers/compose_transition.py index edd0076..debe9ae 100644 --- a/handlers/compose_transition.py +++ b/handlers/compose_transition.py @@ -250,7 +250,7 @@ class ComposeTransitionHandler(BaseHandler): ] # 编码参数(根据硬件加速配置动态获取) - cmd.extend(self.get_video_encode_args()) + cmd.extend(self.get_video_encode_args(maxrate=output_spec.bitrate)) # 帧率 fps = output_spec.fps diff --git a/handlers/render_video.py b/handlers/render_video.py index c7e8087..25f176c 100644 --- a/handlers/render_video.py +++ b/handlers/render_video.py @@ -11,7 +11,7 @@ import logging from typing import List, Optional, Tuple from urllib.parse import urlparse, unquote -from handlers.base import BaseHandler, VIDEO_ENCODE_ARGS +from handlers.base import BaseHandler from domain.task import Task, TaskType, RenderSpec, OutputSpec, Effect, IMAGE_EXTENSIONS from domain.result import TaskResult, ErrorCode @@ -492,7 +492,7 @@ class RenderSegmentTsHandler(BaseHandler): '-vf', vf_filter, ] - cmd.extend(VIDEO_ENCODE_ARGS) + cmd.extend(self.get_video_encode_args(maxrate=output_spec.bitrate)) fps = output_spec.fps cmd.extend(['-r', str(fps)]) @@ -628,7 +628,7 @@ class RenderSegmentTsHandler(BaseHandler): cmd.extend(['-vf', filters]) # 编码参数(根据硬件加速配置动态获取) - cmd.extend(self.get_video_encode_args()) + cmd.extend(self.get_video_encode_args(maxrate=output_spec.bitrate)) # 帧率 fps = output_spec.fps