mirror of
https://github.com/linyqh/NarratoAI.git
synced 2025-12-10 18:02:51 +00:00
优化 ffmpeg 硬件加速 独显 兼容性
This commit is contained in:
parent
47cd4f145d
commit
8fda320d50
@ -216,21 +216,32 @@ def process_single_video(
|
||||
use_software_encoder = True
|
||||
|
||||
if hwaccel:
|
||||
if hwaccel == 'cuda' or hwaccel == 'nvenc':
|
||||
# 获取硬件加速类型和编码器信息
|
||||
hwaccel_type = ffmpeg_utils.get_ffmpeg_hwaccel_type()
|
||||
hwaccel_encoder = ffmpeg_utils.get_ffmpeg_hwaccel_encoder()
|
||||
|
||||
if hwaccel_type == 'cuda' or hwaccel_type == 'nvenc':
|
||||
try:
|
||||
# 在使用NVIDIA编码器前先检查其可用性
|
||||
subprocess.run(['ffmpeg', '-hide_banner', '-encoders'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
command.extend(['-c:v', 'h264_nvenc', '-preset', 'p4', '-profile:v', 'high'])
|
||||
use_software_encoder = False
|
||||
except Exception:
|
||||
logger.warning("NVENC编码器不可用,将使用软件编码")
|
||||
elif hwaccel == 'qsv' and not is_windows: # 在Windows上避免使用QSV
|
||||
# 检查NVENC编码器是否可用
|
||||
encoders_cmd = subprocess.run(
|
||||
["ffmpeg", "-hide_banner", "-encoders"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
if "h264_nvenc" in encoders_cmd.stdout.lower():
|
||||
command.extend(['-c:v', 'h264_nvenc', '-preset', 'p4', '-profile:v', 'high'])
|
||||
use_software_encoder = False
|
||||
else:
|
||||
logger.warning("NVENC编码器不可用,将使用软件编码")
|
||||
except Exception as e:
|
||||
logger.warning(f"NVENC编码器检测失败: {str(e)},将使用软件编码")
|
||||
elif hwaccel_type == 'qsv':
|
||||
command.extend(['-c:v', 'h264_qsv', '-preset', 'medium'])
|
||||
use_software_encoder = False
|
||||
elif hwaccel == 'videotoolbox': # macOS
|
||||
elif hwaccel_type == 'videotoolbox': # macOS
|
||||
command.extend(['-c:v', 'h264_videotoolbox', '-profile:v', 'high'])
|
||||
use_software_encoder = False
|
||||
elif hwaccel == 'vaapi' and not is_windows: # Linux VA-API
|
||||
elif hwaccel_type == 'vaapi': # Linux VA-API
|
||||
command.extend(['-c:v', 'h264_vaapi', '-profile', '100'])
|
||||
use_software_encoder = False
|
||||
|
||||
|
||||
@ -138,18 +138,48 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None:
|
||||
|
||||
# 检测NVIDIA CUDA支持
|
||||
if 'cuda' in supported_hwaccels and 'nvidia' in gpu_info.lower():
|
||||
# 添加调试日志
|
||||
logger.debug(f"Windows检测到NVIDIA显卡,尝试CUDA加速")
|
||||
try:
|
||||
test_cmd = subprocess.run(
|
||||
["ffmpeg", "-hwaccel", "cuda", "-i", "/dev/null", "-f", "null", "-"],
|
||||
# 先检查NVENC编码器是否可用
|
||||
encoders_cmd = subprocess.run(
|
||||
["ffmpeg", "-hide_banner", "-encoders"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
if test_cmd.returncode == 0:
|
||||
has_nvenc = "h264_nvenc" in encoders_cmd.stdout.lower()
|
||||
logger.debug(f"NVENC编码器检测结果: {'可用' if has_nvenc else '不可用'}")
|
||||
|
||||
# 测试CUDA硬件加速
|
||||
test_cmd = subprocess.run(
|
||||
["ffmpeg", "-hwaccel", "cuda", "-i", "NUL", "-f", "null", "-t", "0.1", "-"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
# 记录详细的返回信息以便调试
|
||||
logger.debug(f"CUDA测试返回码: {test_cmd.returncode}")
|
||||
logger.debug(f"CUDA测试错误输出: {test_cmd.stderr[:200]}..." if len(test_cmd.stderr) > 200 else f"CUDA测试错误输出: {test_cmd.stderr}")
|
||||
|
||||
if test_cmd.returncode == 0 or has_nvenc:
|
||||
_FFMPEG_HW_ACCEL_INFO["available"] = True
|
||||
_FFMPEG_HW_ACCEL_INFO["type"] = "cuda"
|
||||
_FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
|
||||
_FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "cuda"]
|
||||
_FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
|
||||
return
|
||||
|
||||
# 如果上面的测试失败,尝试另一种方式
|
||||
test_cmd2 = subprocess.run(
|
||||
["ffmpeg", "-hide_banner", "-loglevel", "error", "-hwaccel", "cuda", "-hwaccel_output_format", "cuda", "-i", "NUL", "-f", "null", "-t", "0.1", "-"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
if test_cmd2.returncode == 0:
|
||||
_FFMPEG_HW_ACCEL_INFO["available"] = True
|
||||
_FFMPEG_HW_ACCEL_INFO["type"] = "cuda"
|
||||
_FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
|
||||
_FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = ["-hwaccel", "cuda", "-hwaccel_output_format", "cuda"]
|
||||
_FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
|
||||
return
|
||||
except Exception as e:
|
||||
logger.debug(f"测试CUDA失败: {str(e)}")
|
||||
|
||||
@ -172,11 +202,16 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None:
|
||||
|
||||
# 检测D3D11VA支持
|
||||
if 'd3d11va' in supported_hwaccels:
|
||||
logger.debug("Windows尝试D3D11VA加速")
|
||||
try:
|
||||
test_cmd = subprocess.run(
|
||||
["ffmpeg", "-hwaccel", "d3d11va", "-i", "/dev/null", "-f", "null", "-"],
|
||||
["ffmpeg", "-hwaccel", "d3d11va", "-i", "NUL", "-f", "null", "-t", "0.1", "-"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
# 记录详细的返回信息以便调试
|
||||
logger.debug(f"D3D11VA测试返回码: {test_cmd.returncode}")
|
||||
|
||||
if test_cmd.returncode == 0:
|
||||
_FFMPEG_HW_ACCEL_INFO["available"] = True
|
||||
_FFMPEG_HW_ACCEL_INFO["type"] = "d3d11va"
|
||||
@ -189,11 +224,16 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None:
|
||||
|
||||
# 检测DXVA2支持
|
||||
if 'dxva2' in supported_hwaccels:
|
||||
logger.debug("Windows尝试DXVA2加速")
|
||||
try:
|
||||
test_cmd = subprocess.run(
|
||||
["ffmpeg", "-hwaccel", "dxva2", "-i", "/dev/null", "-f", "null", "-"],
|
||||
["ffmpeg", "-hwaccel", "dxva2", "-i", "NUL", "-f", "null", "-t", "0.1", "-"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
# 记录详细的返回信息以便调试
|
||||
logger.debug(f"DXVA2测试返回码: {test_cmd.returncode}")
|
||||
|
||||
if test_cmd.returncode == 0:
|
||||
_FFMPEG_HW_ACCEL_INFO["available"] = True
|
||||
_FFMPEG_HW_ACCEL_INFO["type"] = "dxva2"
|
||||
@ -204,6 +244,36 @@ def _detect_windows_acceleration(supported_hwaccels: str) -> None:
|
||||
except Exception as e:
|
||||
logger.debug(f"测试DXVA2失败: {str(e)}")
|
||||
|
||||
# 如果检测到NVIDIA显卡但前面的测试都失败,尝试直接使用NVENC编码器
|
||||
if 'nvidia' in gpu_info.lower():
|
||||
logger.debug("Windows检测到NVIDIA显卡,尝试直接使用NVENC编码器")
|
||||
try:
|
||||
# 检查NVENC编码器是否可用
|
||||
encoders_cmd = subprocess.run(
|
||||
["ffmpeg", "-hide_banner", "-encoders"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
if "h264_nvenc" in encoders_cmd.stdout.lower():
|
||||
logger.debug("NVENC编码器可用,尝试直接使用")
|
||||
# 测试NVENC编码器
|
||||
test_cmd = subprocess.run(
|
||||
["ffmpeg", "-f", "lavfi", "-i", "color=c=black:s=640x360:r=30", "-c:v", "h264_nvenc", "-t", "0.1", "-f", "null", "-"],
|
||||
stderr=subprocess.PIPE, stdout=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
logger.debug(f"NVENC编码器测试返回码: {test_cmd.returncode}")
|
||||
|
||||
if test_cmd.returncode == 0:
|
||||
_FFMPEG_HW_ACCEL_INFO["available"] = True
|
||||
_FFMPEG_HW_ACCEL_INFO["type"] = "nvenc"
|
||||
_FFMPEG_HW_ACCEL_INFO["encoder"] = "h264_nvenc"
|
||||
_FFMPEG_HW_ACCEL_INFO["hwaccel_args"] = [] # 不使用hwaccel参数,直接使用编码器
|
||||
_FFMPEG_HW_ACCEL_INFO["is_dedicated_gpu"] = True
|
||||
return
|
||||
except Exception as e:
|
||||
logger.debug(f"测试NVENC编码器失败: {str(e)}")
|
||||
|
||||
_FFMPEG_HW_ACCEL_INFO["message"] = f"Windows系统未检测到可用的硬件加速,显卡信息: {gpu_info}"
|
||||
|
||||
|
||||
@ -295,10 +365,21 @@ def _get_windows_gpu_info() -> str:
|
||||
str: 显卡信息字符串
|
||||
"""
|
||||
try:
|
||||
# 使用PowerShell获取更可靠的显卡信息
|
||||
gpu_info = subprocess.run(
|
||||
['wmic', 'path', 'win32_VideoController', 'get', 'name'],
|
||||
['powershell', '-Command', "Get-WmiObject Win32_VideoController | Select-Object Name | Format-List"],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
# 如果PowerShell失败,尝试使用wmic
|
||||
if not gpu_info.stdout.strip():
|
||||
gpu_info = subprocess.run(
|
||||
['wmic', 'path', 'win32_VideoController', 'get', 'name'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False
|
||||
)
|
||||
|
||||
# 记录详细的显卡信息以便调试
|
||||
logger.debug(f"Windows显卡信息: {gpu_info.stdout}")
|
||||
return gpu_info.stdout
|
||||
except Exception as e:
|
||||
logger.warning(f"获取Windows显卡信息失败: {str(e)}")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user