作为一个测试,在跑游戏的时候偶然间遇到一些 BUG,都需要提交表单并附上重现操作,但有时候,我们也不记得之前进行了什么操作,所以在跑功能的时候,开启录屏就是一个好习惯了,遇到问题,可以通过回看视频,重复之前的操作步骤来尝试定位问题。常用的录屏软件也就那几个,游戏录屏的话可以使用 windows 自带的录屏软件(win+G),其他的市面上也有不少好用的录屏软件,但是这些录屏软件基本都不支持分段循环录制,每个视频录制下来都很大,不利于保存和传播,小伙伴们都想要一个能够像行车记录仪一样的视频录制软件,循环录制,单个视频时长 1 分钟,可以定义存储上限,不会无限保存视频,翻阅了网上的资料,决定自己试着写个。
python 实现录屏主要用到了 PIL 和 cv2 库,然后还有 numpy 和 pygetwindow 等,首先声明这些库
import time
from datetime import datetime
from PIL import ImageGrab, ImageDraw
import numpy as np
import cv2
import pygetwindow as gw
import pyautogui as pag
接下来是实现录像功能的方法:
def recode(window_title):
"""
录制指定窗口的视频
:param window_title: 窗口名称
:return:
"""
# 1.首先根据窗口名称获取到对应的窗口
window = gw.getWindowsWithTitle(window_title)[0]
# 2.激活并将对应的窗口显示到最顶层
window.restore()
window.activate()
# 3.根据当前时间生成录像文件的名字
file_name = datetime.now().strftime('%Y-%m-%d %H-%M-%S')
# 4.获取窗口的位置和大小
left, top, width, height = window.left, window.top, window.width, window.height
# 5.设置VideoWriter_fourcc录制类型
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# 6.设置文件名,大小,帧率等, VIDEO_FILE_PATH是我设置的一个全局参数,是录像的保存目录,如VIDEO_FILE_PATH = 'E:\\record_files'
# FPS我也参数化了,FPS=15,这个帧率可能会影响录像的播放速度,可以根据自己的情况自行调整
video = cv2.VideoWriter(f'{VIDEO_FILE_PATH}\\{file_name}.avi', fourcc, FPS, (width, height))
# 7.记录开始录制视频的时间
start_time = time.time()
# 8.当录制时间不足1分钟时,循环写入到录像文件中
while time.time() - start_time < 60:
# 这里我每次写入都重新获取了窗口的顶点位置和大小,这样的用处是在你拖动对应的窗口后,录像的区域会跟随你的拖动重新选定,不会傻傻的还在录原来的位置
left, top, width, height = window.left, window.top, window.width, window.height
# 根据窗口区域截取对应的图像
capture_image = ImageGrab.grab((left, top, left+width, top+height))
# 生成图像帧
frame = cv2.cvtColor(np.array(capture_image), cv2.COLOR_RGB2BGR)
# 将图像帧写入到文件中
video.write(frame)
video.release()
然后写一个简单的主函数,循环调用进行录制
def main():
while True:
recode('锚点降临')
这样就可以将录制的视频文件循环保存到指定的文件夹中了。第一步成功!
在使用过程中,我们发现录制的视频是没有包含鼠标的,也就是说我们只能看到视频,无法确定我们的鼠标怎么移动,点了哪里,然后又查阅资料,写了一个绘制鼠标轨迹的方法,这个方法是将窗口截图传入,根据当时鼠标的位置,在传入的截图中指定位置自己绘制一个鼠标(真正的鼠标图案有点复杂,我是以圆点代替的)
def record_mouse(img, mouse_x, mouse_y):
"""
在图片上绘制鼠标位置
:param img: 需要绘制的图片
:param mouse_x: 鼠标在图片上的相对x坐标
:param mouse_y: 鼠标在图片上的相对y坐标
:return:
"""
# 1.首先获取图片大小
w, h = img.size
# 2.加载图像
draw = ImageDraw.Draw(img)
# 判断鼠标位置,如果当时鼠标坐标在图片范围之内,则绘制鼠标
if 0 < mouse_x < w and 0 < mouse_y < h:
# 绘制一个圆点,以红色填充
draw.ellipse((mouse_x-2, mouse_y-2, mouse_x+2, mouse_y+2), fill=250)
# 返回添加了鼠标的截图图像
return img
然后修改一下原来的方法,在截图的时候绘制上鼠标位置
# # 根据窗口区域截取对应的图像
# capture_image = ImageGrab.grab((left, top, left + width, top + height))
# 将上面的方法修改为:
# 获取鼠标坐标,利用到了pyautogui库
mouse_x, mouse_y = pag.position()
# 将截图的图像传入record_mouse方法,获得绘制了鼠标位置之后的截图
capture_image = record_mouse(ImageGrab.grab((left, top, left+width, top+height)), mouse_x - left, mouse_y-top)
这样,录制的视频就可以显示鼠标轨迹了。
最后,就只剩定时删文件,以确保不会占用太多的硬盘空间。
def del_files():
"""
判断文件数量是否超过设定值,如果超过,则删除一定数量的文件
:return:
"""
# 根据目录获取文件列表
files = os.listdir(VIDEO_FILE_PATH)
# 判断文件数量,如果超过了设定的最大值MAX_FILES_COUNT(自行定义),则删除最前面的几个文件
if len(files) > MAX_FILES_COUNT:
for i in files[:len(files)-MAX_FILES_COUNT]:
os.remove(f'{VIDEO_FILE_PATH}\\{i}')
然后再修改一下 main 函数:
def main():
while True:
del_files()
recode('锚点降临')
这样,一个模拟行车记录仪的视频录制软件就完成了,试了一下效果好像还可以?
为了将其打包成一个工具,方便给组里的其他小伙伴使用,我用 PYQT5 给他添加了一个图形界面:
点击开始录制按钮,倒计时 321 开始循环录制,按钮变成停止录制,可以点击停止录制按钮自行停止录制,当找不到对应名称的窗口时,也会 tips 提醒,以上就是这个录屏软件的全部功能,有兴趣的小伙伴欢迎探讨~