Fixed NVENC preset compatibility

Added proper NVENC preset validation
Separated CPU and GPU presets
Added preset conversion logic for GPU encoding
This commit is contained in:
pacnpal
2024-11-15 05:22:38 +00:00
parent f8fe409cdd
commit 8e581d660e

View File

@@ -14,36 +14,36 @@ class EncoderParams:
QUALITY_PRESETS = { QUALITY_PRESETS = {
"gaming": { "gaming": {
"crf": "20", "crf": "20",
"preset": "fast", "preset": "p4", # NVENC preset
"tune": "zerolatency", "tune": "zerolatency",
"x264opts": "rc-lookahead=20:me=hex:subme=6:ref=3:b-adapt=1:direct=spatial" "x264opts": "rc-lookahead=20:me=hex:subme=6:ref=3:b-adapt=1:direct=spatial"
}, },
"animation": { "animation": {
"crf": "18", "crf": "18",
"preset": "slow", "preset": "p7", # NVENC preset
"tune": "animation", "tune": "animation",
"x264opts": "rc-lookahead=60:me=umh:subme=9:ref=6:b-adapt=2:direct=auto:deblock=-1,-1" "x264opts": "rc-lookahead=60:me=umh:subme=9:ref=6:b-adapt=2:direct=auto:deblock=-1,-1"
}, },
"film": { "film": {
"crf": "22", "crf": "22",
"preset": "medium", "preset": "p6", # NVENC preset
"tune": "film", "tune": "film",
"x264opts": "rc-lookahead=50:me=umh:subme=8:ref=4:b-adapt=2:direct=auto" "x264opts": "rc-lookahead=50:me=umh:subme=8:ref=4:b-adapt=2:direct=auto"
} }
} }
# NVENC specific presets
NVENC_PRESETS = ["p1", "p2", "p3", "p4", "p5", "p6", "p7"]
# CPU specific presets
CPU_PRESETS = ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow"]
# Minimum bitrates to ensure quality # Minimum bitrates to ensure quality
MIN_VIDEO_BITRATE = 500_000 # 500 Kbps MIN_VIDEO_BITRATE = 500_000 # 500 Kbps
MIN_AUDIO_BITRATE = 64_000 # 64 Kbps per channel MIN_AUDIO_BITRATE = 64_000 # 64 Kbps per channel
MAX_AUDIO_BITRATE = 192_000 # 192 Kbps per channel MAX_AUDIO_BITRATE = 192_000 # 192 Kbps per channel
def __init__(self, cpu_cores: int, gpu_info: Dict[str, bool]): def __init__(self, cpu_cores: int, gpu_info: Dict[str, bool]):
"""Initialize encoder parameters manager """Initialize encoder parameters manager"""
Args:
cpu_cores: Number of available CPU cores
gpu_info: Dict containing GPU availability information
"""
self.cpu_cores = cpu_cores self.cpu_cores = cpu_cores
self.gpu_info = gpu_info self.gpu_info = gpu_info
logger.info(f"Initialized encoder with {cpu_cores} CPU cores and GPU info: {gpu_info}") logger.info(f"Initialized encoder with {cpu_cores} CPU cores and GPU info: {gpu_info}")
@@ -64,6 +64,9 @@ class EncoderParams:
gpu_params = self._get_gpu_specific_params() gpu_params = self._get_gpu_specific_params()
if gpu_params: if gpu_params:
params.update(gpu_params) params.update(gpu_params)
# Convert CPU preset to GPU preset if using NVENC
if params.get("c:v") == "h264_nvenc" and params.get("preset") in self.CPU_PRESETS:
params["preset"] = "p6" # Default to p6 for NVENC
logger.debug(f"GPU-specific parameters: {gpu_params}") logger.debug(f"GPU-specific parameters: {gpu_params}")
# Calculate and update bitrate parameters # Calculate and update bitrate parameters
@@ -105,7 +108,11 @@ class EncoderParams:
# Detect content type # Detect content type
content_type = self._detect_content_type(video_info) content_type = self._detect_content_type(video_info)
if content_type in self.QUALITY_PRESETS: if content_type in self.QUALITY_PRESETS:
params.update(self.QUALITY_PRESETS[content_type]) preset_params = self.QUALITY_PRESETS[content_type].copy()
# Don't copy preset if we're using NVENC
if self.gpu_info.get("nvidia", False):
preset_params.pop("preset", None)
params.update(preset_params)
# Additional optimizations based on content analysis # Additional optimizations based on content analysis
if video_info.get("has_high_motion", False): if video_info.get("has_high_motion", False):
@@ -128,7 +135,7 @@ class EncoderParams:
if self.gpu_info.get("nvidia", False): if self.gpu_info.get("nvidia", False):
return { return {
"c:v": "h264_nvenc", "c:v": "h264_nvenc",
"preset": "p7", "preset": "p6", # Use NVENC preset
"rc:v": "vbr", "rc:v": "vbr",
"cq:v": "19", "cq:v": "19",
"b_ref_mode": "middle", "b_ref_mode": "middle",
@@ -195,19 +202,19 @@ class EncoderParams:
"ac": str(audio_channels) "ac": str(audio_channels)
}) })
# Adjust CRF based on target size # Adjust quality based on target size
input_bitrate = int(video_info.get("bitrate", 0)) input_bitrate = int(video_info.get("bitrate", 0))
if input_bitrate > 0: if input_bitrate > 0:
compression_ratio = input_bitrate / video_bitrate compression_ratio = input_bitrate / video_bitrate
if compression_ratio > 4: if compression_ratio > 4:
params["crf"] = "26" params["crf"] = "26"
params["preset"] = "faster" params["preset"] = "p4" if self.gpu_info.get("nvidia", False) else "faster"
elif compression_ratio > 2: elif compression_ratio > 2:
params["crf"] = "23" params["crf"] = "23"
params["preset"] = "medium" params["preset"] = "p6" if self.gpu_info.get("nvidia", False) else "medium"
else: else:
params["crf"] = "20" params["crf"] = "20"
params["preset"] = "slow" params["preset"] = "p7" if self.gpu_info.get("nvidia", False) else "slow"
logger.info(f"Calculated bitrates - Video: {video_bitrate}bps, Audio: {audio_bitrate}bps") logger.info(f"Calculated bitrates - Video: {video_bitrate}bps, Audio: {audio_bitrate}bps")
return params return params
@@ -254,10 +261,13 @@ class EncoderParams:
if params["c:v"] not in ["libx264", "h264_nvenc", "h264_amf", "h264_qsv"]: if params["c:v"] not in ["libx264", "h264_nvenc", "h264_amf", "h264_qsv"]:
raise ValueError(f"Invalid video codec: {params['c:v']}") raise ValueError(f"Invalid video codec: {params['c:v']}")
# Validate preset # Validate preset based on codec
valid_presets = ["ultrafast", "superfast", "veryfast", "faster", "fast", "medium", "slow", "slower", "veryslow", "p1", "p2", "p3", "p4", "p5", "p6", "p7"] if params["c:v"] == "h264_nvenc":
if params["preset"] not in valid_presets: if params["preset"] not in self.NVENC_PRESETS:
raise ValueError(f"Invalid preset: {params['preset']}") raise ValueError(f"Invalid NVENC preset: {params['preset']}")
elif params["c:v"] == "libx264":
if params["preset"] not in self.CPU_PRESETS:
raise ValueError(f"Invalid CPU preset: {params['preset']}")
# Validate pixel format # Validate pixel format
if params["pix_fmt"] not in ["yuv420p", "nv12", "yuv444p"]: if params["pix_fmt"] not in ["yuv420p", "nv12", "yuv444p"]: