作者:昼夜
关键词:屏幕录制
在平时搭建或者运行应用的过程当中,也会又客户或多或少存在着这样的想法:这一部分比较重要,我能不能单独看到某一段指令的运行情况是不是按照我预设的那样;或者说是我想根据他的运行情况排查一下我错误的原因。
当然,在影刀的设置中我们已经带上这样的功能,在设置的运行回放模块中,我们也带有定长时间的回放录制的功能,并且会在文件超过一定体积的时候自动去清除更早的文件等。但是,也会存在一些问题,例如当我磁盘的容量小于某个值的时候,录屏功能就无法使用;或者说我们版本跟进不及时、ffmpeg在下载过程中损坏了和处于内网的环境下时,需要手动去添加ffmpeg才能进行录屏;以及客户觉得我只想看某个子流程运行的情况等。
在本文当中,介绍了如何通过python中的OpenCV、numpy及pyautogui等库来实现我们对于屏幕的录制。
首先来介绍一下OpenCV这个库, OpenCV主要用于处理图像和视频数据,其中蕴含着大量的优化算法可以用于图像处理、机器学习和计算机视觉领域。在这里我们主要用到OpenCV在视频文件的读取和写入的功能,通过VideoCapture类可以轻松读取视频文件中的图像帧,并且通过VideoWriter类可以将图像帧写入视频文件。此外,OpenCV还有许多的函数可以对图像和视频文件进行处理,进行一些压缩与解码、特效及增强技术,可以更加灵活的录制高质量和个性化的视频。
我们来看一下具体的实现逻辑:
1.使用win32api中的GetSystemMetrics()函数去获取本机屏幕的分辨率,保证后面我们录制视频的时候获取到的整个屏幕的图像(也可以通过规定分辨率去指定录制某块特定的区域)。
2.调用OpenCV库中的,使用VideoWriter_fourcc()函数确定视频文件的格式为avi,并创建一个VideoWriter对象,用来将每一帧的图像都写进视频文件中,这里通过参数output_filename规定了视频文件的存放路径,通过fps规定了视频文件的帧数。
3.进入一个无限循环,在循环中我们不断截取屏幕的图像,通过numpy将图像转换为数组排列并且使用cvtColor()函数进行RGB格式转换之后,通过write()函数写入到视频文件对象中去。
4.同时,我们在循环里面设置了退出规则,当我们同时按下Ctrl+C的时候,整个屏幕录制的过程就会停止。
5.在视频录制完成之后,我们会释放掉视频的写入对象并销毁对应的窗口,释放资源以及清理内存,保证设备正常。
此外,在代码中我们注释了一条cv2.imshow()的语句,这条语句可以帮助我们在录制的时候显示出来屏幕图像(经测试不建议开启,运行时会看到类似于直播工具一样的画面)
import cv2
import numpy as np
import pyautogui
import win32api
import win32con
def record_screen(output_filename, fps):
# 获取本机屏幕分辨率
screen_width = win32api.GetSystemMetrics(0)
screen_height = win32api.GetSystemMetrics(1)
screen_size = (screen_width, screen_height)
fourcc = cv2.VideoWriter_fourcc(*'XVID') # 确定文件的格式
# 创建一个VideoWriter对象,将每一帧的图像写入视频文件
out = cv2.VideoWriter(output_filename, fourcc, fps, screen_size)
print("-" * 15 + "开始录制屏幕....(如需终止请按'Ctrl+C')" + "-" * 15)
while True:
img = pyautogui.screenshot() # 截取屏幕图像
frame = np.array(img) # 将截取的图像转换为数组排列
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 将图像从BGR格式转换为RGB格式
out.write(frame)
# cv2.imshow('Screen Recorder', frame) # 显示录制的屏幕图像
# 设置退出规则
if win32api.GetAsyncKeyState(win32con.VK_CONTROL) and win32api.GetAsyncKeyState(ord('C')):
print("-" * 15 + "录制已结束" + "-" * 15)
break
out.release()
cv2.destroyAllWindows()在影刀中的流程演示如下:
1.将代码写入模块,并创建录制屏幕子流程调用该模块,在调用中,我们设置好对应的文件存储路径与对应帧率。


2.创建一个退出录制的流程,其中的使用键盘输入的指令输入Ctrl+C,保证录制可以在任何位置退出。

3.搭建一个我们要执行的流程,在我们想要录制的指令段开始之前并发调用录制屏幕的子流程,再在我们想要结束的地方调用退出录制的子流程,完成某块指令段的运行情况录制。

我们运行刚才搭建的应用,可以看到,在录制开始的时候会在指定的存放位置上(我这里指定的是桌面)生成一个avi文件(此时文件内部处于一种没有图像的状态),随着流程开始执行,会把运行情况记录到这个avi文件中,一直到我们执行退出流程结束录制,文件会整体生成。

此处运行生成的视频文件如下:

在这里可以看到,我们录制的内容只有在百度内搜索影刀的部分,并没有后续输入“哈哈哈哈”的部分,也就是说这边就按照我们预设的退出了录制,符合我们的需求。
在录制的过程中,如果觉得视频播放的速度过快,可以尝试降低我们设置的帧率。