好友
阅读权限 10
听众
最后登录 1970-1-1
本帖最后由 pinkLove 于 2025-3-21 09:43 编辑
[md]事情是因为我朋友开了一个电竞酒店,有客人在电脑上开挂,硬件被cf打标了,其他玩家上号就被封号。想了很多办法都不合适,写了个轻量的录屏软件,如果出现问题,也可以找到开东西的人。下面是代码
import os
import subprocess
import sys
import pyautogui
import cv2
import numpy as np
import threading
from datetime import datetime
import time
import signal
parser = argparse.ArgumentParser(description="Screen Recording Service" )
parser.add_argument("--duration" , type =int , default=10 , help ="Video duration in seconds (default: 3600 seconds)" )
parser.add_argument("--save_path" , type =str , default="D:/doc/local/vid" ,
help ="Directory to save videos (default: D:/doc/local/vid)" )
args = parser.parse_args()
VIDEO_DURATION = args.duration
SAVE_PATH = args.save_path
TARGET_RESOLUTION = (1280 , 720 )
FPS = 15
recording = False
current_video = None
out = None
if getattr (sys, 'frozen' , False ):
BASE_PATH = sys._MEIPASS
else :
BASE_PATH = os.path.dirname(os.path.abspath(__file__))
FFMPEG_PATH = os.path.join(BASE_PATH, 'ffmpeg.exe' )
print (FFMPEG_PATH)
os.makedirs(SAVE_PATH, exist_ok=True )
def record_screen ():
global recording, current_video, out
screen_width, screen_height = pyautogui.size()
fourcc = cv2.VideoWriter_fourcc(*'XVID' )
current_video = f"recording_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S' )} .mp4"
output_path = os.path.join(SAVE_PATH, current_video)
out = cv2.VideoWriter(output_path, fourcc, FPS, TARGET_RESOLUTION)
start_time = time.time()
recording = True
while recording and (time.time() - start_time < VIDEO_DURATION):
screenshot = pyautogui.screenshot()
frame = np.array(screenshot)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
frame_resized = cv2.resize(frame, TARGET_RESOLUTION)
out.write(frame_resized)
out.release()
print (f"视频保存为: {output_path} " )
def save_video ():
"""保存并压缩视频"""
global current_video
if current_video:
video_path = os.path.join(SAVE_PATH, current_video)
if out is None :
print (f"发生异常,视频未压缩,原视频文件保存在:{video_path} " )
else :
compressed_video_path = os.path.join(SAVE_PATH, current_video.replace('.mp4' , '_compressed.mp4' ))
compress_video_with_ffmpeg(video_path, compressed_video_path)
os.remove(video_path)
print (f"已删除原视频文件:{video_path} " )
def compress_video_with_ffmpeg (video_path, output_path ):
"""使用 FFmpeg 压缩视频"""
ffmpeg_cmd = [
FFMPEG_PATH, '-i' , video_path,
'-vcodec' , 'libx264' ,
'-crf' , '23' ,
'-an' ,
'-preset' , 'fast' ,
'-movflags' , 'faststart' ,
'-y' , output_path
]
startupinfo = None
if sys.platform == "win32" :
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
try :
subprocess.run(ffmpeg_cmd, check=True , startupinfo=startupinfo)
print (f"视频已压缩并保存为:{output_path} " )
except subprocess.CalledProcessError as e:
print (f"FFmpeg 压缩失败: {e} " )
def stop_recording ():
"""停止录制"""
global recording
recording = False
save_video()
def schedule_recording ():
"""每小时录制一次"""
while True :
record_screen()
time.sleep(VIDEO_DURATION)
stop_recording()
def start_service ():
"""启动录屏服务"""
recording_thread = threading.Thread(target=schedule_recording)
recording_thread.daemon = True
recording_thread.start()
print ("录屏服务已启动..." )
def exit_gracefully (signum, frame ):
"""程序异常退出时保存视频"""
global out
print ("程序异常退出,正在保存视频..." )
if out is not None :
out.release()
if __name__ == "__main__" :
signal.signal(signal.SIGINT, exit_gracefully)
signal.signal(signal.SIGTERM, exit_gracefully)
start_service()
while True :
time.sleep(1 )
然后我们通过打包命令打包成可执行文件
pyinstaller -w --onefile --windowed --add-data "ffmpeg.exe:." -i .\ico.ico -n ikunScreenW.exe screen.py
这里需要使用到ffmpeg 可自行上网查阅
给一个成品
https://wwts.lanzoub.com/ivlJG2r0hj0b
密码:5r73
___=============分割线===========___
又仔细想了一下需求,感觉截屏比录屏更有性价比,而且截屏能更少的占用资源,在大佬的指点下,我对代码进行了优化,特别是顾客隐私方面,设置了白名单过滤,话不多说,下面是代码
```python
import argparse
import os
import time
from datetime import datetime
import win32gui
import win32con
from PIL import ImageGrab
# 解析命令行参数
parser = argparse.ArgumentParser(description="Screen Shot Service")
parser.add_argument("--sleep", type=int, default=5, help="截屏间隔时间 默认5秒")
parser.add_argument("--save_path", type=str, default="D:/doc/local/testPng", help="图片文件存储地址 默认D:/doc/local")
parser.add_argument("--white_list", type=str, default="", help="应用白名单 按,分割传入 默认为空")
# 忽略非预期参数
args, _ = parser.parse_known_args()
SLEEP_TIME = args.sleep
SAVE_PATH = args.save_path
os.makedirs(SAVE_PATH, exist_ok=True)
WHITE_LIST = args.white_list
# 这个是默认的白名单 主要是微信
white_list = ['微信', 'WeChat', '聊天文件', '朋友圈']
if WHITE_LIST != "":
str_list = WHITE_LIST.split(",") # 按逗号分割字符串
white_list = list(set(str_list + white_list)) # 合并列表并去重
def is_white_window_open():
"""检测白名单窗口是否打开"""
def enum_windows_callback(hwnd, open_list):
# 获取窗口标题
title = win32gui.GetWindowText(hwnd)
# 检查开启的窗口是否包含白名单应用
if title in white_list:
# 检查窗口是否可见
if win32gui.IsWindowVisible(hwnd):
# 检查窗口是否最小化
placement = win32gui.GetWindowPlacement(hwnd)
if placement[1] != win32con.SW_SHOWMINIMIZED: # 窗口未最小化
open_list.append(hwnd)
results = []
# 枚举所有窗口
win32gui.EnumWindows(enum_windows_callback, results)
return bool(results)
def screenshot():
"""截屏保存"""
screenshot_png = ImageGrab.grab()
# file_name = f"{SAVE_PATH}/screenshot_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.webp"
# screenshot_png.save(file_name, 'webp', quality=80)
file_name = f"{SAVE_PATH}/screenshot_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.png"
screenshot_png.save(file_name)
if __name__ == "__main__":
while True:
if not is_white_window_open():
screenshot()
time.sleep(SLEEP_TIME)
```
可通过启动参数的方式来设置白名单,可对客户的隐私做保护
<h1>最后还是感谢大佬们的指点</h1>[/md]
免费评分
查看全部评分