init
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from .config import ScreenshotCfg
|
||||
|
||||
|
||||
class ScreenshotCapture:
|
||||
def __init__(self, cfg: ScreenshotCfg):
|
||||
self._cfg = cfg
|
||||
|
||||
def capture(self) -> str:
|
||||
"""截取全屏,返回保存路径。自动选择当前平台最佳方式。"""
|
||||
if self._cfg.delay_ms > 0:
|
||||
time.sleep(self._cfg.delay_ms / 1000)
|
||||
|
||||
out_path = self._cfg.tmp_path
|
||||
Path(out_path).parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
if sys.platform == "darwin":
|
||||
self._capture_macos(out_path)
|
||||
else:
|
||||
self._capture_linux(out_path)
|
||||
|
||||
if not Path(out_path).exists():
|
||||
raise RuntimeError(f"截图文件未生成: {out_path}")
|
||||
return out_path
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# macOS
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _capture_macos(self, out_path: str) -> None:
|
||||
# screencapture -x 静默截全屏(无声音/闪烁)
|
||||
subprocess.run(["screencapture", "-x", out_path], check=True)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Linux(按优先级尝试)
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _capture_linux(self, out_path: str) -> None:
|
||||
wayland = os.environ.get("WAYLAND_DISPLAY")
|
||||
|
||||
if wayland:
|
||||
# Wayland 优先:grim(轻量)> spectacle > gnome-screenshot
|
||||
if shutil.which("grim"):
|
||||
subprocess.run(["grim", out_path], check=True)
|
||||
return
|
||||
if shutil.which("spectacle"):
|
||||
# spectacle -b 后台 -f 全屏 -n 无通知 -o 输出路径
|
||||
# 丢弃 stderr(Tesseract 未安装的无害警告)
|
||||
subprocess.run(
|
||||
["spectacle", "-b", "-f", "-n", "-o", out_path],
|
||||
check=True,
|
||||
timeout=10,
|
||||
stderr=subprocess.DEVNULL,
|
||||
)
|
||||
return
|
||||
if shutil.which("gnome-screenshot"):
|
||||
subprocess.run(["gnome-screenshot", "-f", out_path], check=True)
|
||||
return
|
||||
# 最后尝试 mss(可能在 XWayland 下有效)
|
||||
self._capture_mss(out_path)
|
||||
else:
|
||||
# X11:mss 最快,失败则用 scrot
|
||||
try:
|
||||
self._capture_mss(out_path)
|
||||
except Exception:
|
||||
if shutil.which("scrot"):
|
||||
subprocess.run(["scrot", out_path], check=True)
|
||||
elif shutil.which("import"): # ImageMagick
|
||||
subprocess.run(["import", "-window", "root", out_path], check=True)
|
||||
else:
|
||||
raise RuntimeError("未找到可用的截图工具(scrot / import)")
|
||||
|
||||
def _capture_mss(self, out_path: str) -> None:
|
||||
import mss
|
||||
import mss.tools
|
||||
|
||||
with mss.mss() as sct:
|
||||
monitor = sct.monitors[0] # 0 = 全部显示器合并
|
||||
screenshot = sct.grab(monitor)
|
||||
mss.tools.to_png(screenshot.rgb, screenshot.size, output=out_path)
|
||||
Reference in New Issue
Block a user