将网络/IP 路由拆分并加入去重缓存,系统检测改为线程执行并支持强制刷新,前端改为先展示缓存快照后按需手动重测,降低阻塞与重复探测开销。 Co-authored-by: Cursor <cursoragent@cursor.com>
72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
"""本机能力探测:GPU 等(供控制台 UI)。"""
|
||
from __future__ import annotations
|
||
|
||
import platform
|
||
import socket
|
||
import subprocess
|
||
import threading
|
||
import time
|
||
from typing import Any
|
||
|
||
|
||
def detect_nvidia_gpu() -> bool:
|
||
if platform.system().lower() not in ("windows", "linux"):
|
||
return False
|
||
try:
|
||
_kw: dict = {"capture_output": True, "timeout": 4}
|
||
if platform.system().lower() == "windows":
|
||
_kw["creationflags"] = subprocess.CREATE_NO_WINDOW
|
||
r = subprocess.run(["nvidia-smi"], **_kw)
|
||
return r.returncode == 0
|
||
except Exception:
|
||
return False
|
||
|
||
|
||
def detect_nvenc_available(nvidia_present: bool | None = None) -> bool:
|
||
if nvidia_present is None:
|
||
nvidia_present = detect_nvidia_gpu()
|
||
if not nvidia_present:
|
||
return False
|
||
try:
|
||
_kw = {"capture_output": True, "text": True, "timeout": 8}
|
||
if platform.system().lower() == "windows":
|
||
_kw["creationflags"] = subprocess.CREATE_NO_WINDOW
|
||
r = subprocess.run(["ffmpeg", "-hide_banner", "-encoders"], **_kw)
|
||
return r.returncode == 0 and "h264_nvenc" in (r.stdout or "")
|
||
except Exception:
|
||
return False
|
||
|
||
|
||
_GPU_STATUS_CACHE_TTL_SECONDS = 60.0
|
||
_gpu_status_lock = threading.Lock()
|
||
_gpu_status_cache: tuple[float, dict[str, Any]] | None = None
|
||
|
||
|
||
def gpu_status_payload(force_refresh: bool = False) -> dict[str, Any]:
|
||
global _gpu_status_cache
|
||
now = time.time()
|
||
with _gpu_status_lock:
|
||
if not force_refresh and _gpu_status_cache and (now - _gpu_status_cache[0]) < _GPU_STATUS_CACHE_TTL_SECONDS:
|
||
return dict(_gpu_status_cache[1])
|
||
|
||
nv = detect_nvidia_gpu()
|
||
enc = detect_nvenc_available(nv)
|
||
payload = {
|
||
"nvidia_detected": nv,
|
||
"nvenc_available": enc,
|
||
}
|
||
with _gpu_status_lock:
|
||
_gpu_status_cache = (time.time(), payload)
|
||
return dict(payload)
|
||
|
||
|
||
def machine_summary_payload() -> dict[str, Any]:
|
||
"""供远程 App 遥测:本机标识与系统信息。"""
|
||
return {
|
||
"hostname": socket.gethostname(),
|
||
"os": platform.system(),
|
||
"os_release": platform.release(),
|
||
"machine": platform.machine(),
|
||
"python": platform.python_version(),
|
||
}
|