No.027-实现独立子流程或指令段的运行录制功能——By.杭州组
评论
收藏

No.027-实现独立子流程或指令段的运行录制功能——By.杭州组

经验分享
昼夜
2023-08-30 20:02·浏览量:1376
昼夜
发布于 2023-08-30 20:02更新于 2023-08-30 20:021376浏览


作者:昼夜

关键词:屏幕录制



一、问题背景

在平时搭建或者运行应用的过程当中,也会又客户或多或少存在着这样的想法:这一部分比较重要,我能不能单独看到某一段指令的运行情况是不是按照我预设的那样;或者说是我想根据他的运行情况排查一下我错误的原因。

当然,在影刀的设置中我们已经带上这样的功能,在设置的运行回放模块中,我们也带有定长时间的回放录制的功能,并且会在文件超过一定体积的时候自动去清除更早的文件等。但是,也会存在一些问题,例如当我磁盘的容量小于某个值的时候,录屏功能就无法使用;或者说我们版本跟进不及时、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文件中,一直到我们执行退出流程结束录制,文件会整体生成。


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


   在这里可以看到,我们录制的内容只有在百度内搜索影刀的部分,并没有后续输入“哈哈哈哈”的部分,也就是说这边就按照我们预设的退出了录制,符合我们的需求。


四、其他

在录制的过程中,如果觉得视频播放的速度过快,可以尝试降低我们设置的帧率。

收藏3
全部评论1
最新
发布评论
评论