mirror of
https://github.com/pacnpal/Pac-cogs.git
synced 2025-12-20 10:51:05 -05:00
Added proper physical GPU detection on Linux/Windows/macOS
Separated physical GPU detection from FFmpeg encoder support Only enable GPU encoding when both physical GPU and FFmpeg support exist Added multiple detection methods for better reliability
This commit is contained in:
@@ -5,7 +5,7 @@ import subprocess
|
|||||||
import logging
|
import logging
|
||||||
import platform
|
import platform
|
||||||
import re
|
import re
|
||||||
from typing import Dict, List
|
from typing import Dict, List, Tuple
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
logger = logging.getLogger("VideoArchiver")
|
logger = logging.getLogger("VideoArchiver")
|
||||||
@@ -34,24 +34,23 @@ class GPUDetector:
|
|||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Check system-specific GPU detection first
|
# First detect physical GPUs
|
||||||
system = platform.system().lower()
|
physical_gpus = self._detect_physical_gpus()
|
||||||
if system == "windows":
|
|
||||||
gpu_info.update(self._detect_windows_gpu())
|
|
||||||
elif system == "linux":
|
|
||||||
gpu_info.update(self._detect_linux_gpu())
|
|
||||||
elif system == "darwin":
|
|
||||||
gpu_info.update(self._detect_macos_gpu())
|
|
||||||
|
|
||||||
# Verify GPU support in FFmpeg
|
# Then check FFmpeg support
|
||||||
gpu_info.update(self._verify_ffmpeg_gpu_support())
|
ffmpeg_support = self._verify_ffmpeg_gpu_support()
|
||||||
|
|
||||||
|
# Only enable GPU if both physical GPU exists and FFmpeg supports it
|
||||||
|
gpu_info["nvidia"] = physical_gpus["nvidia"] and ffmpeg_support["nvidia"]
|
||||||
|
gpu_info["amd"] = physical_gpus["amd"] and ffmpeg_support["amd"]
|
||||||
|
gpu_info["intel"] = physical_gpus["intel"] and ffmpeg_support["intel"]
|
||||||
|
|
||||||
# Log detection results
|
# Log detection results
|
||||||
detected_gpus = [name for name, detected in gpu_info.items() if detected]
|
detected_gpus = [name for name, detected in gpu_info.items() if detected]
|
||||||
if detected_gpus:
|
if detected_gpus:
|
||||||
logger.info(f"Detected GPUs: {', '.join(detected_gpus)}")
|
logger.info(f"Detected GPUs with FFmpeg support: {', '.join(detected_gpus)}")
|
||||||
else:
|
else:
|
||||||
logger.info("No GPU acceleration support detected")
|
logger.info("No GPU acceleration available")
|
||||||
|
|
||||||
return gpu_info
|
return gpu_info
|
||||||
|
|
||||||
@@ -59,6 +58,17 @@ class GPUDetector:
|
|||||||
logger.error(f"Error during GPU detection: {str(e)}")
|
logger.error(f"Error during GPU detection: {str(e)}")
|
||||||
return {"nvidia": False, "amd": False, "intel": False}
|
return {"nvidia": False, "amd": False, "intel": False}
|
||||||
|
|
||||||
|
def _detect_physical_gpus(self) -> Dict[str, bool]:
|
||||||
|
"""Detect physical GPUs in the system"""
|
||||||
|
system = platform.system().lower()
|
||||||
|
if system == "windows":
|
||||||
|
return self._detect_windows_gpu()
|
||||||
|
elif system == "linux":
|
||||||
|
return self._detect_linux_gpu()
|
||||||
|
elif system == "darwin":
|
||||||
|
return self._detect_macos_gpu()
|
||||||
|
return {"nvidia": False, "amd": False, "intel": False}
|
||||||
|
|
||||||
def _detect_windows_gpu(self) -> Dict[str, bool]:
|
def _detect_windows_gpu(self) -> Dict[str, bool]:
|
||||||
"""Detect GPUs on Windows using PowerShell"""
|
"""Detect GPUs on Windows using PowerShell"""
|
||||||
gpu_info = {"nvidia": False, "amd": False, "intel": False}
|
gpu_info = {"nvidia": False, "amd": False, "intel": False}
|
||||||
@@ -80,60 +90,56 @@ class GPUDetector:
|
|||||||
return gpu_info
|
return gpu_info
|
||||||
|
|
||||||
def _detect_linux_gpu(self) -> Dict[str, bool]:
|
def _detect_linux_gpu(self) -> Dict[str, bool]:
|
||||||
"""Detect GPUs on Linux using lspci and other tools"""
|
"""Detect GPUs on Linux using multiple methods"""
|
||||||
gpu_info = {"nvidia": False, "amd": False, "intel": False}
|
gpu_info = {"nvidia": False, "amd": False, "intel": False}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Try lspci first
|
# Check for NVIDIA GPU
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["lspci", "-v"],
|
["nvidia-smi"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
if result.returncode == 0:
|
gpu_info["nvidia"] = result.returncode == 0
|
||||||
output = result.stdout.lower()
|
|
||||||
gpu_info["nvidia"] = "nvidia" in output
|
|
||||||
gpu_info["amd"] = any(x in output for x in ["amd", "radeon"])
|
|
||||||
gpu_info["intel"] = "intel" in output
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Check for NVIDIA using nvidia-smi
|
# Check for AMD GPU using DRI
|
||||||
if not gpu_info["nvidia"]:
|
if os.path.exists("/dev/dri"):
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["nvidia-smi"],
|
["ls", "/dev/dri/render*"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
gpu_info["nvidia"] = result.returncode == 0
|
if result.returncode == 0:
|
||||||
except FileNotFoundError:
|
# Check device info using lspci
|
||||||
|
lspci_result = subprocess.run(
|
||||||
|
["lspci", "-v"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
if lspci_result.returncode == 0:
|
||||||
|
output = lspci_result.stdout.lower()
|
||||||
|
gpu_info["amd"] = any(x in output for x in ["amd", "radeon", "advanced micro devices"])
|
||||||
|
gpu_info["intel"] = "intel" in output and "graphics" in output
|
||||||
|
except (FileNotFoundError, subprocess.SubprocessError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Check for AMD using rocm-smi
|
# Additional check for Intel GPU
|
||||||
if not gpu_info["amd"]:
|
if not gpu_info["intel"] and os.path.exists("/sys/class/drm"):
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["rocm-smi"],
|
["find", "/sys/class/drm", "-name", "*i915*"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
gpu_info["amd"] = result.returncode == 0
|
gpu_info["intel"] = bool(result.stdout.strip())
|
||||||
except FileNotFoundError:
|
except subprocess.SubprocessError:
|
||||||
pass
|
|
||||||
|
|
||||||
# Check for Intel using intel_gpu_top
|
|
||||||
if not gpu_info["intel"]:
|
|
||||||
try:
|
|
||||||
result = subprocess.run(
|
|
||||||
["intel_gpu_top", "-L"],
|
|
||||||
capture_output=True,
|
|
||||||
timeout=10
|
|
||||||
)
|
|
||||||
gpu_info["intel"] = result.returncode == 0
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -187,7 +193,7 @@ class GPUDetector:
|
|||||||
encoders.append("QSV")
|
encoders.append("QSV")
|
||||||
|
|
||||||
if encoders:
|
if encoders:
|
||||||
logger.info(f"FFmpeg supports GPU encoders: {', '.join(encoders)}")
|
logger.info(f"FFmpeg compiled with GPU encoders: {', '.join(encoders)}")
|
||||||
else:
|
else:
|
||||||
logger.info("No GPU encoders available in FFmpeg")
|
logger.info("No GPU encoders available in FFmpeg")
|
||||||
|
|
||||||
@@ -197,11 +203,7 @@ class GPUDetector:
|
|||||||
return gpu_support
|
return gpu_support
|
||||||
|
|
||||||
def get_gpu_info(self) -> Dict[str, List[str]]:
|
def get_gpu_info(self) -> Dict[str, List[str]]:
|
||||||
"""Get detailed GPU information
|
"""Get detailed GPU information"""
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict containing lists of GPU names by type
|
|
||||||
"""
|
|
||||||
gpu_info = {
|
gpu_info = {
|
||||||
"nvidia": [],
|
"nvidia": [],
|
||||||
"amd": [],
|
"amd": [],
|
||||||
@@ -211,23 +213,9 @@ class GPUDetector:
|
|||||||
try:
|
try:
|
||||||
system = platform.system().lower()
|
system = platform.system().lower()
|
||||||
|
|
||||||
if system == "windows":
|
if system == "linux":
|
||||||
cmd = ["powershell", "-Command", "Get-WmiObject Win32_VideoController | Select-Object Name"]
|
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
|
||||||
|
|
||||||
if result.returncode == 0:
|
|
||||||
for line in result.stdout.splitlines():
|
|
||||||
line = line.strip().lower()
|
|
||||||
if line:
|
|
||||||
if "nvidia" in line:
|
|
||||||
gpu_info["nvidia"].append(line)
|
|
||||||
elif any(x in line for x in ["amd", "radeon"]):
|
|
||||||
gpu_info["amd"].append(line)
|
|
||||||
elif "intel" in line:
|
|
||||||
gpu_info["intel"].append(line)
|
|
||||||
|
|
||||||
elif system == "linux":
|
|
||||||
try:
|
try:
|
||||||
|
# Try lspci first
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["lspci", "-v"],
|
["lspci", "-v"],
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
@@ -246,6 +234,35 @@ class GPUDetector:
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Try nvidia-smi for NVIDIA GPUs
|
||||||
|
if not gpu_info["nvidia"]:
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["nvidia-smi", "-L"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
gpu_info["nvidia"].extend(line.strip() for line in result.stdout.splitlines() if line.strip())
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
elif system == "windows":
|
||||||
|
cmd = ["powershell", "-Command", "Get-WmiObject Win32_VideoController | Select-Object Name"]
|
||||||
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||||
|
|
||||||
|
if result.returncode == 0:
|
||||||
|
for line in result.stdout.splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith("Name"):
|
||||||
|
if "nvidia" in line.lower():
|
||||||
|
gpu_info["nvidia"].append(line)
|
||||||
|
elif any(x in line.lower() for x in ["amd", "radeon"]):
|
||||||
|
gpu_info["amd"].append(line)
|
||||||
|
elif "intel" in line.lower():
|
||||||
|
gpu_info["intel"].append(line)
|
||||||
|
|
||||||
elif system == "darwin":
|
elif system == "darwin":
|
||||||
cmd = ["system_profiler", "SPDisplaysDataType"]
|
cmd = ["system_profiler", "SPDisplaysDataType"]
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10)
|
||||||
@@ -253,17 +270,15 @@ class GPUDetector:
|
|||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
current_gpu = None
|
current_gpu = None
|
||||||
for line in result.stdout.splitlines():
|
for line in result.stdout.splitlines():
|
||||||
line = line.strip().lower()
|
line = line.strip()
|
||||||
if "chipset model" in line:
|
if "Chipset Model:" in line:
|
||||||
if "nvidia" in line:
|
model = line.split(":", 1)[1].strip()
|
||||||
current_gpu = "nvidia"
|
if "nvidia" in model.lower():
|
||||||
gpu_info["nvidia"].append(line.split(":")[1].strip())
|
gpu_info["nvidia"].append(model)
|
||||||
elif any(x in line for x in ["amd", "radeon"]):
|
elif any(x in model.lower() for x in ["amd", "radeon"]):
|
||||||
current_gpu = "amd"
|
gpu_info["amd"].append(model)
|
||||||
gpu_info["amd"].append(line.split(":")[1].strip())
|
elif "intel" in model.lower():
|
||||||
elif "intel" in line:
|
gpu_info["intel"].append(model)
|
||||||
current_gpu = "intel"
|
|
||||||
gpu_info["intel"].append(line.split(":")[1].strip())
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error getting detailed GPU info: {str(e)}")
|
logger.error(f"Error getting detailed GPU info: {str(e)}")
|
||||||
|
|||||||
Reference in New Issue
Block a user