import cv2
import mss
import numpy as np
from flask import Flask, Response, request, redirect, url_for, send_from_directory
from comet_ml import Experiment
# 初始化Comet实验
experiment = Experiment(api_key="YOUR_API_KEY", project_name="screen-sharing")
# 第二块显示器的编号为1(索引从0开始)
monitor_number = 2
app = Flask(__name__)
def generate_frames():
with mss.mss() as sct:
monitor = sct.monitors[monitor_number]
while True:
# 捕获屏幕
screenshot = sct.grab(monitor)
img = np.array(screenshot)
# 将图像转换为JPEG格式
ret, buffer = cv2.imencode('.jpg', img)
frame = buffer.tobytes()
# 使用Comet记录图像
experiment.log_image(img, name="screen_capture")
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
@app.route('/')
def index():
return redirect(url_for('video_feed'))
@app.route('/video_feed')
def video_feed():
return Response(generate_frames(),
mimetype='multipart/x-mixed-replace; boundary=frame')
# 添加静态文件路由
@app.route('/static/<path:filename>')
def static_files(filename):
return send_from_directory('static', filename)
# 假设我们有一个函数可以模拟触摸事件
def simulate_touch_event(event_type, x, y):
# 这里可以调用某个库或者工具来模拟触摸事件
# 例如,使用pyautogui库来模拟鼠标点击
import pyautogui
if event_type == 'tap':
pyautogui.click(x, y)
elif event_type == 'double_tap':
pyautogui.doubleClick(x, y)
elif event_type == 'long_press':
pyautogui.mouseDown(x, y)
pyautogui.mouseUp(x, y)
elif event_type == 'swipe_left':
pyautogui.moveTo(x, y)
pyautogui.dragTo(x - 100, y, duration=0.5)
elif event_type == 'swipe_right':
pyautogui.moveTo(x, y)
pyautogui.dragTo(x + 100, y, duration=0.5)
elif event_type == 'swipe_up':
pyautogui.moveTo(x, y)
pyautogui.dragTo(x, y - 100, duration=0.5)
elif event_type == 'swipe_down':
pyautogui.moveTo(x, y)
pyautogui.dragTo(x, y + 100, duration=0.5)
@app.route('/tap', methods=['POST'])
def handle_tap():
# 处理单击事件
print("Single Tap Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Tap at coordinates: ({x}, {y})") # 打印触摸信息
simulate_touch_event('tap', x, y)
return "OK"
@app.route('/double_tap', methods=['POST'])
def handle_double_tap():
# 处理双击事件
print("Double Tap Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Double Tap at coordinates: ({x}, {y})") # 打印触摸信息
simulate_touch_event('double_tap', x, y)
return "OK"
@app.route('/long_press', methods=['POST'])
def handle_long_press():
# 处理长按事件
print("Long Press Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Long Press at coordinates: ({x}, {y})") # 打印触摸信息
simulate_touch_event('long_press', x, y)
return "OK"
@app.route('/swipe_left', methods=['POST'])
def handle_swipe_left():
# 处理左滑事件
print("Swipe Left Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Swipe Left from ({x}, {y})") # 打印触摸信息
simulate_touch_event('swipe_left', x, y)
return "OK"
@app.route('/swipe_right', methods=['POST'])
def handle_swipe_right():
# 处理右滑事件
print("Swipe Right Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Swipe Right from ({x}, {y})") # 打印触摸信息
simulate_touch_event('swipe_right', x, y)
return "OK"
@app.route('/swipe_up', methods=['POST'])
def handle_swipe_up():
# 处理上滑事件
print("Swipe Up Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Swipe Up from ({x}, {y})") # 打印触摸信息
simulate_touch_event('swipe_up', x, y)
return "OK"
@app.route('/swipe_down', methods=['POST'])
def handle_swipe_down():
# 处理下滑事件
print("Swipe Down Detected")
data = request.get_json()
x = data.get('x')
y = data.get('y')
print(f"Swipe Down from ({x}, {y})") # 打印触摸信息
simulate_touch_event('swipe_down', x, y)
return "OK"
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Screen Sharing</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<h1>Screen Sharing</h1>
<img id="screen-capture" src="{{ url_for('video_feed') }}" alt="Screen Capture">
<script src="{{ url_for('static', filename='js/script.js') }}"></script>
<script>
const screenCapture = document.getElementById('screen-capture');
// 添加全屏显示代码
document.addEventListener('DOMContentLoaded', () => {
if (screenCapture.requestFullscreen) {
screenCapture.requestFullscreen();
} else if (screenCapture.mozRequestFullScreen) { // Firefox
screenCapture.mozRequestFullScreen();
} else if (screenCapture.webkitRequestFullscreen) { // Chrome, Safari and Opera
screenCapture.webkitRequestFullscreen();
} else if (screenCapture.msRequestFullscreen) { // IE/Edge
screenCapture.msRequestFullscreen();
}
});
let touchStartTime;
let touchStartX, touchStartY;
let touchEndX, touchEndY;
screenCapture.addEventListener('touchstart', (event) => {
console.log('Touch Start'); // 添加调试信息
touchStartTime = new Date().getTime();
touchStartX = event.touches[0].clientX;
touchStartY = event.touches[0].clientY;
});
screenCapture.addEventListener('touchend', (event) => {
console.log('Touch End'); // 添加调试信息
const touchEndTime = new Date().getTime();
touchEndX = event.changedTouches[0].clientX;
touchEndY = event.changedTouches[0].clientY;
const touchDuration = touchEndTime - touchStartTime;
const deltaX = touchEndX - touchStartX;
const deltaY = touchEndY - touchStartY;
const rect = screenCapture.getBoundingClientRect();
const x = touchStartX - rect.left;
const y = touchStartY - rect.top;
if (touchDuration < 500) {
if (Math.abs(deltaX) < 30 && Math.abs(deltaY) < 30) {
// Tap or Double Tap
if (touchDuration < 200) {
// Double Tap
console.log('Double Tap'); // 添加调试信息
fetch('/double_tap', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
} else {
// Single Tap
console.log('Single Tap'); // 添加调试信息
fetch('/tap', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
}
} else {
// Swipe
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (deltaX > 0) {
// Swipe Right
console.log('Swipe Right'); // 添加调试信息
fetch('/swipe_right', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
} else {
// Swipe Left
console.log('Swipe Left'); // 添加调试信息
fetch('/swipe_left', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
}
} else {
if (deltaY > 0) {
// Swipe Down
console.log('Swipe Down'); // 添加调试信息
fetch('/swipe_down', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
} else {
// Swipe Up
console.log('Swipe Up'); // 添加调试信息
fetch('/swipe_up', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
}
}
}
} else {
// Long Press
console.log('Long Press'); // 添加调试信息
fetch('/long_press', { method: 'POST', body: JSON.stringify({ x: x, y: y }), headers: { 'Content-Type': 'application/json' } });
}
});
</script>
</body>
</html>
我本来想实现与parsecVDisplay的创建虚拟显示器做配合的,但以上代码已经实现了在手机端显示第二个显示器的屏幕信息,但我碰到一个问题,就是不知道为何html文件里的触摸事件总是检测不了,且无法实现手机触摸对虚拟显示屏的控制。