Files
deskflow/screenCaptureNoConfirm.py
2026-04-09 10:37:51 +08:00

148 lines
5.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""screenCaptureNoConfirm
pywebview 通过js跳过确认直接获取屏幕媒体流
"""
import webview
import threading
import time
# -------------------------- 1. PyWebView配置 --------------------------
class ScreenCaptureAPI:
def __init__(self):
self.window = None
def set_window(self, window):
self.window = window
def auto_trigger_capture(self):
"""后台自动触发屏幕采集(模拟用户点击)"""
# 延迟1秒等待页面加载完成
time.sleep(1)
# 执行JS自动点击按钮触发屏幕采集
self.window.evaluate_js("document.getElementById('autoCaptureBtn').click();")
# -------------------------- 2. 前端HTML核心自动触发+无感采集) --------------------------
HTML_CONTENT = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>自动获取屏幕流</title>
<style>
* {margin: 0; padding: 0; box-sizing: border-box;}
body {padding: 20px; background: #f5f7fa; font-family: Arial;}
.video-container {
width: 100%; max-width: 1600px;
border: 1px solid #ddd; border-radius: 8px;
overflow: hidden; background: #000;
margin-top: 20px;
}
#localVideo {
width: 100%; height: auto;
display: block; object-fit: contain;
}
/* 隐藏触发按钮(仅用于自动点击) */
#autoCaptureBtn {
position: absolute; top: -9999px; left: -9999px;
opacity: 0; pointer-events: none;
}
.status {
margin: 10px 0; color: #666; font-size: 14px;
}
</style>
</head>
<body>
<!-- 隐藏的自动触发按钮(用于模拟用户点击) -->
<button id="autoCaptureBtn" onclick="captureScreen()"></button>
<div class="status" id="status">状态:等待自动采集...</div>
<div class="video-container">
<video id="localVideo" autoplay muted playsinline></video>
</div>
<script>
const videoEl = document.getElementById('localVideo');
const statusEl = document.getElementById('status');
let screenStream = null;
// 核心:获取屏幕媒体流(必须由用户手势触发)
async function captureScreen() {
try {
statusEl.textContent = "状态:请求屏幕权限...";
// 调用Screen Capture API系统级弹窗无法跳过
screenStream = await navigator.mediaDevices.getDisplayMedia({
video: {
cursor: "always", // 显示鼠标光标
displaySurface: "monitor" // 优先选择整个显示器
},
audio: false // 可选:是否采集音频
});
// 将流绑定到video标签
videoEl.srcObject = screenStream;
statusEl.textContent = "状态:屏幕采集成功!";
// 监听流结束事件(用户停止共享)
screenStream.getVideoTracks()[0].addEventListener('ended', () => {
statusEl.textContent = "状态:屏幕采集已停止";
videoEl.srcObject = null;
});
} catch (error) {
statusEl.textContent = `状态:采集失败 - ${error.message}`;
console.error("屏幕采集错误:", error);
}
}
// 页面加载完成后通知Python端可以自动触发
window.onload = async () => {
// 告知Python页面已加载可触发自动点击
await window.pywebview.api.page_loaded();
};
</script>
</body>
</html>
"""
# -------------------------- 3. 主程序入口 --------------------------
if __name__ == "__main__":
# 初始化API
api = ScreenCaptureAPI()
# 创建pywebview窗口关键配置WebView2引擎+权限豁免)
window = webview.create_window(
title="自动获取屏幕流",
html=HTML_CONTENT,
width=1400,
height=900,
resizable=True,
# confirm_close=True,
# 额外权限配置WebView2
# webview_settings={
# "web_security": False, # 关闭跨域限制(本地运行需开启)
# "allow_displaying_insecure_content": True,
# "allow_running_insecure_content": True
# },
js_api=api
)
api.set_window(window)
# 定义页面加载完成后的回调(自动触发采集)
def on_page_loaded():
# 启动线程自动触发点击
trigger_thread = threading.Thread(target=api.auto_trigger_capture, daemon=True)
trigger_thread.start()
# 暴露API给前端
api.page_loaded = on_page_loaded
# 启动pywebview
try:
webview.start(
private_mode=False, # 关键:关闭私有模式,授予本地权限
debug=True,
http_server=True
)
except KeyboardInterrupt:
print("程序已终止")