使用opencv-python制作屏幕录制工具

  • 应用平台
  • 屏幕录制部分
  • 计算视频最优fps及使用numpy计算中间帧数组
  • 使用pynput监听键盘按键
  • 如何保存MP4格式视频
  • 总结

最近有在使用屏幕录制软件录制桌面,在用的过程中突发奇想,使用python能不能做屏幕录制工具,也锻炼下自己的动手能力。
接下准备写使用python如何做屏幕录制工具的系列文章:

  • 录制屏幕制作视频
  • 录制音频
  • 合成视频,音频
  • 基于pyqt5制作可视化窗口

大概上述四个部分,希望自己能够尽快完善,接下来开始使用python制作屏幕录制部分。

应用平台

  • 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 np
from PIL import ImageGrab
import 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:  # 当某某条件满足中断循环break
video.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 = Trueelif key.char == 'k':  # 录屏中止,删除文件self.flag = Trueself.kill = Trueexcept Exception as e:print(e)

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

如何保存MP4格式视频

视频编码格式应该为(‘a’, ‘v’, ‘c’, ‘1’),文件后缀为’.mp4’,在录制前先去https://github.com/cisco/openh264/releases下下载对应平台的dll.bz2文件,将压缩包解压放在项目文件夹下。

再运行代码,成功会出现一行编码说明:
OpenH264 Video Codec provided by Cisco Systems, Inc.

总结

目前使用了opencv和相关模块对屏幕进行录制并转换为视频保存,学习将多个函数封装为类,方便后续功能开发。学习的道路是无止境的,大胆的迈步走吧!


于二零二一年十二月十四日作

源码:

import time
from PIL import ImageGrab
import cv2
from pathlib import Path
import numpy as np
from numba import jit
from pynput import keyboard
from 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 = pathself.best_fps = fpsself.fps = fpsself.width = widthself.high = highself.spend_time = 1self.flag = Falseself.kill = Falseself.video = Nonedef __call__(self, path):"""重载视频路径,便于类的二次调用"""self.save_file = Path(path)self.video = self.init_videowriter(self.save_file)@staticmethoddef screenshot():"""静态方法,屏幕截图,并转换为np.array数组"""return np.array(ImageGrab.grab())@staticmethoddef 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 pathfourcc = 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_listtimes = 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_listdef 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:breakself.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 = Trueelif key.char == 'k':  # 录屏中止,删除文件self.flag = Trueself.kill = Trueexcept Exception as e:print(e)def run(self):# 运行函数# 设置守护线程Thread(target=self.hotkey, daemon=True).start()# 运行截图函数self.frame2video_run()screen = ImageGrab.grab()
width, high = screen.size
video = ScreenshotVideo(width, high, fps=60)
video.pre_video_record()  # 预录制获取最优fps
video('test1.mp4')
video.run()

使用opencv-python制作屏幕录制工具相关推荐

  1. 手把手教你使用opencv-python库制作屏幕录制工具(附源码)

    目录 目录 应用平台 屏幕录制部分 计算视频最优fps及使用numpy计算中间帧数组 使用pynput监听键盘按键 如何保存MP4格式视频 源码 总结 最近有在使用屏幕录制软件录制桌面,在用的过程中突 ...

  2. python屏幕录制与回放_使用Python来做一个屏幕录制工具的操作代码

    本文给大家分享使用Python来做一个屏幕录制工具,通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下 一.写在前面 作为一名测试,有时候经常会遇到需要录屏记录自己操作,方 ...

  3. 脚本录制软件python 按键精灵 tc_使用Python来做一个屏幕录制工具的操作代码

    一.写在前面 作为一名测试,有时候经常会遇到需要录屏记录自己操作,方便后续开发同学定位.以前都是用ScreenToGif来录屏制作成动态图,偶尔的机会看到python也能实现.那就赶紧学习下. 二.效 ...

  4. 制作gif动态图片,LICEcap – 灵活好用,GIF 屏幕录制工具

    一.制作gif动态图片,LICEcap – 灵活好用,GIF 屏幕录制工具 LICEcap 是一款屏幕录制工具,支持导出 GIF 动画图片格式,轻量级.使用简单,录制过程中可以随意改变录屏范围. 二. ...

  5. python实现屏幕录制_屏幕录制工具有哪些?这是可以实现无水印录制的

    屏幕录制工具有哪些?屏幕录制可以运用的场景是非常多的,比方说屏幕录制游戏视频.屏幕录制直播视频.屏幕录制追剧视频.屏幕录制网课视频.屏幕录制演示视频.屏幕录制会议视频.屏幕录制讲座视频等等.那么,屏幕 ...

  6. 使用Pyqt5制作屏幕录制界面

    使用Pyqt5制作屏幕录制界面 应用平台 窗口设置 主体窗口代码 划选窗口代码 总结 最近有在使用屏幕录制软件录制桌面,在用的过程中突发奇想,使用python能不能做屏幕录制工具,也锻炼下自己的动手能 ...

  7. ubuntu 15个最佳的屏幕录制工具推荐

    前言 屏幕播放对于许多人来说是一项重要任务,原因很多,包括制作视频教程,创建演示文稿,编写操作指南或进行软件评审,或者在玩PC游戏时享受流媒体的乐趣. 此外,现在有很多用户通过YouTube,Face ...

  8. 如何用Python进行屏幕录制?

    文章目录 引言 gpt3.5给出的代码 更换截图函数--ImageGrab.grab 禁用imshow解决递归现象 摄像头录制代码 后期需求 引言 关于屏幕录制这个功能需求,之前用过基于ffmpeg的 ...

  9. VideoSolo Screen Recorder for mac(mac屏幕录制工具)

    VideoSolo Screen Recorder是一款mac屏幕录制工具,无论您要对屏幕进行哪项活动都可以为您进行记录,例如在线视频,游戏,Skype聊天,演示等等,此软件都可以快速将计算机上的屏幕 ...

最新文章

  1. C# redis 分布式session存储
  2. 黑马lavarel教程---4、csrf验证及相关
  3. 哇,居然可以用这种烙铁头拆元器件!!!
  4. git 撤销挂起的更改_Timer计时任务因系统时间的修改导致挂起解决方案
  5. java 置位_java安全编码指南之:Mutability可变性详解
  6. 推荐一款免费开源的javascript电子表格:x-sheet
  7. 和差测角天线方向图仿真matlab 含代码
  8. 示例程序:关于双目视觉,标定,立体匹配(视差算法),点云,双目三维重建的原理以及代码
  9. 华为鸿蒙国内厂商适配,华为再放大招!鸿蒙系统将适配高通/联发科手机:获国产厂商力挺...
  10. Zookeeper 客户端之 Curator
  11. 2019 最烂密码排行榜大曝光!网友:已中招
  12. 基于单片机的车速控制语音报警系统
  13. 微信小程序—半圆(弧形)进度条
  14. 硬件结构框架_北桥_带宽
  15. *5-1 CCF 2015-03-1 图像旋转
  16. 迅为IMX6ULL开发板搭建Web服务器(二)
  17. 关于Python中的lambda,这篇阅读量10万+的文章可能是你见过的最完整的讲解
  18. 对数公式大全(及其Markdown语法)
  19. 使用正则表达式实现注册表单验证(包括下拉列表二级联动、密码显示和隐藏)...
  20. 检测服务器的远程端口开启和关闭状态

热门文章

  1. 请谨慎使用预训练的深度学习模型
  2. ZooKeeper学习笔记(八):ZooKeeper集群写数据原理
  3. C语言实现动态二维数组及相乘
  4. ubuntu平台下编译vlc-android视频播放器实践
  5. linux中利用k键杀死进程号,linux下杀死进程的若干方法
  6. python if多个条件并列_Python中if有多个条件处理方法
  7. 计算机显示屏怎么加密,怎样给电脑设置密码的屏幕保护
  8. uniapp中登录注册页面以视频为背景
  9. 户外直播、慢直播、赛事直播等直播行业的未来发展趋势
  10. 如何搞定你喜欢的美术妹纸?