千家信息网

基于Python+OpenCV如何制作屏幕录制工具

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,这篇文章跟大家分析一下"基于Python+OpenCV如何制作屏幕录制工具"。内容详细易懂,对"基于Python+OpenCV如何制作屏幕录制工具"感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希
千家信息网最后更新 2026年11月02日基于Python+OpenCV如何制作屏幕录制工具

这篇文章跟大家分析一下"基于Python+OpenCV如何制作屏幕录制工具"。内容详细易懂,对"基于Python+OpenCV如何制作屏幕录制工具"感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习"基于Python+OpenCV如何制作屏幕录制工具"的知识吧。

应用平台

  • windows 10

  • python 3.7

屏幕录制部分

屏幕录制可以简单地理解为将屏幕快照以动图的形式播放,这里我选用PIL下的ImageGrab来截取屏幕画面,首先

pip install Pillow

之后需要将截取到的快照数组合成为视频,使用cv2模块

pip install opencv-python

ImageGrab类不能直接存储为视频,使用numpy模块进行数组化,再通过cv2.COLOR_BGR2RGB转换为cv2色彩通道。

pip install numpy

屏幕录制主要代码:

import numpy as npfrom PIL import ImageGrabimport cv2im = ImageGrab.grab()width, high = im.size  # 获取屏幕的宽和高fourcc = cv2.VideoWriter_fourcc(*'I420')  # 设置视频编码格式fps = 15  # 设置帧率video = cv2.VideoWriter('test.avi', fourcc, fps, (width, high))while True:  # 开始录制    im = ImageGrab.grab()    im_cv = cv2.cvtColor(np.array(im), cv2.COLOR_BGR2RGB)    # 图像写入    video.write(im_cv)    if xx:  # 当某某条件满足中断循环        breakvideo.release()  # 释放缓存,持久化视频

测试运行可以保存屏幕快照为视频,但操作起来不优雅,也不利于后续的操作。

封装成类,继承线程父类,方便使用键盘来控制视频录制的结束。

from threading import Threadclass ScreenshotVideo(Thread):    def __init__(self):     """初始化参数"""        super().__init__()

详细代码将在文末给出。

计算视频最优fps及使用numpy计算中间帧数组

实际操作中视频录制在不同电脑中会出现不一样的帧率,导致视频播放或快或慢,需要根据不同的电脑计算出相应的最优fps值。

def video_best_fps(self, path):    """获取电脑录制视频的最优帧率"""    video = cv2.VideoCapture(path)  # 读取视频    fps = video.get(cv2.CAP_PROP_FPS)  # 获取当前视频的帧率    count = video.get(cv2.CAP_PROP_FRAME_COUNT)  # 获取视频帧数,即该视频有多少幅画面    self.best_fps = int(fps * ((int(count) / fps) / self.spend_time))   # 计算播放时间与录制时间对比得到最优帧率    video.release()

再调整帧率参数进行录制视频就减弱了视频播放太快或者太慢。也可以给视频增加帧数从而延长播放时间,这里我采用一种很简单的方法增加视频帧,仅供参考。

from numba import jit# 使用numpy计算相邻两帧图像且更接近于后一帧的图像# 调用jit方法加速数组计算@jit(nopython=True)def average_n(x, y):    """Numpy计算趋近值"""    return ((x + y + y) // 3).astype(x.dtype)

该方法仅针对于设置的fps比最优fps要高时,处理后的视频观感,视频还是较为急促,但是细节帧增多,所以播放时长会比未处理前的要长,略有残影。

使用pynput监听键盘按键

在视频录制中,并不知道视频何时结束,所以用while循环包裹录制代码,但也不可能让代码无休止的运行下去,在此使用监听键盘模块来中断录制代码的运行。

from pynput import keyboard  # pip install pynputdef hotkey(self):    """热键监听"""    with keyboard.Listener(on_press=self.on_press) as listener:        listener.join()def on_press(self, key):    try:        if key.char == 't':  # 录屏结束,保存视频            self.flag = True        elif key.char == 'k':  # 录屏中止,删除文件            self.flag = True            self.kill = True    except Exception as e:        print(e)

按下键盘"T"键时,结束录制,保存视频。"K"键则是停止录制,删除缓存文件。

如何保存MP4格式视频

视频编码格式应该为('a', 'v', 'c', '1'),文件后缀为'.mp4',在录制前先去https://github.com/cisco/openh364/releases下下载对应平台的dll.bz2文件,将压缩包解压放在项目文件夹下。再运行代码,成功会出现一行编码说明:

OpenH264 Video Codec provided by Cisco Systems, Inc.

源码

本文实现的源码如下:

import timefrom PIL import ImageGrabimport cv2from pathlib import Pathimport numpy as npfrom numba import jitfrom pynput import keyboardfrom threading import Thread@jit(nopython=True)def average_n(x, y):    """Numpy计算趋近值"""    return ((x + y + y) // 3).astype(x.dtype)class ScreenshotVideo(Thread):    def __init__(self, width, high, path='', fps=15):        """初始化参数"""        super().__init__()        self.save_file = path        self.best_fps = fps        self.fps = fps        self.width = width        self.high = high        self.spend_time = 1        self.flag = False        self.kill = False        self.video = None    def __call__(self, path):        """重载视频路径,便于类的二次调用"""        self.save_file = Path(path)        self.video = self.init_videowriter(self.save_file)    @staticmethod    def screenshot():        """静态方法,屏幕截图,并转换为np.array数组"""        return np.array(ImageGrab.grab())    @staticmethod    def get_fourcc(name):        """视频编码字典"""        fourcc_maps = {'.avi': 'I420',                       '.m4v': 'mp4v',                       '.mp4': 'avc1',                       '.ogv': 'THEO',                       '.flv': 'FLV1',                       }        return fourcc_maps.get(name)    def init_videowriter(self, path):        """获取视频编码并新建视频文件"""        if not path:            raise Exception('视频路径未设置,请设置\nvideo = ScreenshotVideo(fps,width,high)\nvideo = video(video_path)')        path = Path(path) if isinstance(path, str) else path        fourcc = cv2.VideoWriter_fourcc(*self.get_fourcc(path.suffix))        return cv2.VideoWriter(path.as_posix(), fourcc, self.fps, (self.width, self.high))    def video_record_doing(self, img):        """将BGR数组转换为RGB数组"""        im_cv = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)        self.video.write(im_cv)    def video_record_end(self):        """录制结束,根据条件判断文件是否保存"""        self.video.release()        cv2.destroyAllWindows()        if self.save_file and self.kill:            Path(self.save_file).unlink()    def video_best_fps(self, path):        """获取电脑录制视频的最优帧率"""        video = cv2.VideoCapture(path)        fps = video.get(cv2.CAP_PROP_FPS)        count = video.get(cv2.CAP_PROP_FRAME_COUNT)        self.best_fps = int(fps * ((int(count) / fps) / self.spend_time))        video.release()    def pre_video_record(self):        """预录制,以获取最佳fps值"""        self.video = self.init_videowriter('test.mp4')        start_time = time.time()        for _ in range(10):            im = self.screenshot()            self.video_record_doing(im)        self.spend_time = round(time.time() - start_time, 4)        self.video_record_end()        time.sleep(2)        self.video_best_fps('test.mp4')        Path('test.mp4').unlink()    def insert_frame_array(self, frame_list):        """Numpy增强截图信息"""        fps_n = round(self.fps / self.best_fps)        if fps_n <= 0:            return frame_list        times = int(np.log2(fps_n))  # 倍率        for _ in range(times):            frame_list2 = map(average_n, [frame_list[0]] + frame_list[:-1], frame_list)            frame_list = [[x, y] for x, y in zip(frame_list2, frame_list)]            frame_list = [j for i in frame_list for j in i]        return frame_list    def frame2video_run(self):        """使用opencv将连续型截图转换为视频"""        self.video = self.init_videowriter(self.save_file)        start_time = time.time()        frame_list = []        while True:            frame_list.append(self.screenshot())            if self.flag:                break        self.spend_time = round(time.time() - start_time, 4)        if not self.kill:  # 视频录制不被终止将逐帧处理图像            frame_list = self.insert_frame_array(frame_list)            for im in frame_list:                self.video_record_doing(im)        self.video_record_end()    def hotkey(self):        """热键监听"""        with keyboard.Listener(on_press=self.on_press) as listener:            listener.join()    def on_press(self, key):        try:            if key.char == 't':  # 录屏结束,保存视频                self.flag = True            elif key.char == 'k':  # 录屏中止,删除文件                self.flag = True                self.kill = True        except Exception as e:            print(e)    def run(self):        # 运行函数        # 设置守护线程        Thread(target=self.hotkey, daemon=True).start()        # 运行截图函数        self.frame2video_run()screen = ImageGrab.grab()width, high = screen.sizevideo = ScreenshotVideo(width, high, fps=60)video.pre_video_record()  # 预录制获取最优fpsvideo('test1.mp4')video.run()

关于基于Python+OpenCV如何制作屏幕录制工具就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下网站!

视频 屏幕 文件 代码 数组 运行 编码 工具 制作 图像 截图 方法 电脑 键盘 监听 参数 快照 时间 格式 模块 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 厦门中拓互联网络科技有限公司 互联网巨头反垄断金融科技 互联网 科技公司 互联网金融公司科技 广州宏创互联网科技 未来的互联网科技 互联网养老 桔豆科技 互联网 科技服务平台 华中科技有哪些互联网大佬 科技互联网的估值 字节跳动和互联网科技 青岛科技大学互联网大赛研究生 成都互联网科技公司工作好不好 电子科技大学互联网创业大赛 浙南科技城互联网大厦建设工程 互联网科技创新的路径 互联网金融科技公司的优势 云鲸互联网络科技有限公司 湖北辰鑫科技互联网 云南互联网科技学费 互联网科技保险 迪茉互联网科技 华服互联网科技官网 科技互联网大厂 注册互联网科技公司经营范围大全 恒生互联网科技业指数调整周期 无锡工业互联网科技有限公司 互联网第三次科技革命特征 昆明中奇联合互联网科技 云鲸互联网络科技有限公司
0