如何用Python进行屏幕录制?

文章目录

    • 引言
    • gpt3.5给出的代码
    • 更换截图函数——ImageGrab.grab
    • 禁用imshow解决递归现象
    • 摄像头录制代码
    • 后期需求

引言

关于屏幕录制这个功能需求,之前用过基于ffmpeg的Capture录屏软件,但是fps拉高以后会变得很卡,声音也同样出现卡顿。也自己尝试过在python中调用ffmpeg的库函数,效果也不尽人意。网络上下载了几款录屏软件,不是要收费就是下载到捆绑软件或广告很是心累,因此想借此机会重新研究一下屏幕录制软件的工作原理,同时当作一个小项目练手。

gpt3.5给出的代码

当我还在犹豫是否要精心翻阅一下ffmpeg的说明书时,没想到gpt已果断给出了参考答案,可以使用Python的PyAutoGUI库来实现录屏功能。以下是一个简单的示例代码:

import pyautogui
import cv2
import numpy as np

# 获取屏幕分辨率
screen_size = (1920, 1080)

# 设置视频编码器
fourcc = cv2.VideoWriter_fourcc(*"XVID")

# 创建视频写入对象
out = cv2.VideoWriter("output.avi", fourcc, 20.0, screen_size)

# 开始录屏
while True:
    # 获取屏幕截图
    img = pyautogui.screenshot()

    # 将截图转换为OpenCV格式
    frame = np.array(img)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # 写入视频
    out.write(frame)

    # 按下q键退出录屏
    if cv2.waitKey(1) == ord("q"):
        break

# 释放资源
out.release()
cv2.destroyAllWindows()

从给出的代码看来,屏幕录制的工作原理就是以一定的帧率不断地截图,然后将截取的图片以相同的帧率合成一个视频
放在安装了pyautogui的python环境里运行后,果然不出意外的话就要出意外了。gpt3.5给出的代码卡在运行中的界面纹丝不动,按’q’回车也并未退出循环,再问gpt也死活给不出修改方案。

查阅资料后发现要先imshow()之后,在ui窗口区域内按键才能有效终止循环:

import numpy as np
import pyautogui
import cv2

# 设置录制参数
SCREEN_SIZE = (1920, 1080)
FILENAME = 'recorded_video.avi'
FPS = 30.0

# 开始录制
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter(FILENAME, fourcc, FPS, SCREEN_SIZE)

while True:
    # 获取屏幕截图
    img = pyautogui.screenshot()
    # 转换为OpenCV格式
    frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
    # 写入视频文件
    out.write(frame)
    cv2.imshow('Frame', frame)
    cv2.resizeWindow('Frame', 1920, 1080)

    # 检测按键
    if cv2.waitKey(1) == ord('q'):
        break

# 停止录制
out.release()
cv2.destroyAllWindows()

程序是能运行了,但是效果依旧不好,窗口一直有递归的效果,而且导出的视频其实是无法播放的。
在这里插入图片描述

更换截图函数——ImageGrab.grab

pyautogui虽然能实现截图,并在imshow里展示出来,但是导出的视频却无法播放,考虑肯能涉及到具体视频编解码参数问题,有懂的朋友请在评论区分享。这里采用更换PIL库中的截图函数ImageGrab.grab,可以实现截图并导出视频了,接下来最大的问题就是解决递归现象。

import numpy as np
from PIL import ImageGrab
import cv2

# 设置录制参数
SCREEN_SIZE = (1920, 1080)
FILENAME = 'recorded_video.avi'
FPS = 30.0

# 开始录制
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter(FILENAME, fourcc, FPS, SCREEN_SIZE)

while True:
    # 获取屏幕截图
    # img = pyautogui.screenshot()
    img = ImageGrab.grab(bbox=(0, 0, 1920, 1080))
    print('recordin..')
    # 转换为OpenCV格式
    frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
    # 写入视频文件
    out.write(frame)
    cv2.imshow('Frame', frame)
    cv2.resizeWindow('Frame', 1920, 1080)

    # 检测按键
    if cv2.waitKey(1) == ord('q'):
        break

# 停止录制
out.release()
cv2.destroyAllWindows()

在这里插入图片描述

禁用imshow解决递归现象

视频处理时的递归现象其实非常常见,除了物理中的镜面效应(观察两个平行放置的镜子会出现递归的现象),

将摄像头对准显示器,显示器上的画面也会观察到递归的现象:
在这里插入图片描述
经尝试,将imshow()禁用后,改为帧计数的方式自定义终止循环就不会出现递归的问题了:

import numpy as np
from PIL import ImageGrab
import cv2

# 设置录制参数
SCREEN_SIZE = (1920, 1080)
FILENAME = 'recorded_video.avi'
FPS = 30.0

# 开始录制
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter(FILENAME, fourcc, FPS, SCREEN_SIZE)

cnt = 0
while True:
    # 获取屏幕截图
    # img = pyautogui.screenshot()
    img = ImageGrab.grab(bbox=(0, 0, 1920, 1080))
    print('recordin..')
    # 转换为OpenCV格式
    frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
    # 写入视频文件
    out.write(frame)
    # cv2.imshow('Frame', frame)
    # cv2.resizeWindow('Frame', 1920, 1080)

    # # 检测按键
    # if cv2.waitKey(1) == ord('q'):
    #     break

    cnt = cnt + 1

    if cnt == 100:  #满100帧后终止循环
        break

# 停止录制
out.release()
cv2.destroyAllWindows()

在这里插入图片描述
通过修改img = ImageGrab.grab(bbox=(0, 0, 2560, 1600))中的参数可以自定义录屏区域,x,y,w,h分别代表左上角坐标(起始坐标)和图片宽度、高度。比如我的屏幕分辨率是2560*1600,那么设置为0, 0, 2560, 1600就是录制全屏:
在这里插入图片描述
这样,我们就可以基本实现用Python进行屏幕录制的功能了。动态图预览看上去分辨率不高是因为用的格式工厂把录制的视频转了gif,压缩前录制的视频其实蛮清楚的。

通过修改fps的值,我们还可以自行录制一些高刷新率的电影、游戏画面,fps越高,画面越流畅哦。

摄像头录制代码

类似的,也可以用python实现相机录像的功能:

import cv2
import cv2 as cv

# 打开摄像头
cap = cv2.VideoCapture(0)

fourcc = cv.VideoWriter_fourcc(*'XVID')
file_name = 'output'
output = cv.VideoWriter((file_name + '.avi'), fourcc, 24.0, (640, 480))  #设置文件名,fps,分辨率

while cap.isOpened():

    res, frame = cap.read()
    if not res:
        print("Frame Cannot Be Received")
        break

    # Flipping the frame horizontally to get correct orientation
    frame = cv2.flip(frame, 90)

    # Displaying the current frame
    output.write(frame)
    cv2.imshow('Frame', frame)

    # If no input is received for 1ms, or if the key 'x' is pressed, interpreter goes outside of the loop
    if cv2.waitKey(1) == ord('x'):
        break

# Releasing everything after coming out of loop
cap.release()
output.release()
cv2.destroyAllWindows()

后期需求

现在屏幕录制的问题基本解决了,要想做一个实用的屏幕录制软件,还需要加上音频录制,并设计一个便捷的UI界面。

参考文档:
[1] python视频操作——python实现读取和保存视频
[2] 择一柳 python 怎样实现屏幕视频录制?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/22353.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

nodej+vues汽车销售4s店服务平台商城系统购物车积分兑换7z9d2

在经济快速发展的带动下,汽车服务平台的发展也是越来越快速。用户对汽车服务信息的获取需求很大。在互联网飞速发展的今天,制作一个汽车服务平台系统是非常必要的。本系统是借鉴其他人的开发基础上,用MySQL数据库和nodejs定制了汽车服务平台系…

【MySQL】事务

事务是一组操作的集合,我们将一组操作视为一个整体,所以事务里面的操作的时候要么同时成功,要么同时失败,之所以会有事务也是因为我们在实际生活中会用到 最典型的例子就是转账操作:A向B进行转账,A这边扣款成功的同时B那边一定是收款成功的,如果没有事务的话就会出现A扣款成功但…

LMS,RGB,XYZ色彩空间转换

前言 首先需要指明本文中描述的R,G,B并非通常的sRGB中的三个分量R,G,B,而是波长分别为700nm,546.1nm,435.8nm的单色红光,单色绿光,单色蓝光。sRGB中的RGB中的红色、绿色、蓝色已经不是单色光了。虽然习惯上大家都叫RGB…

网络安全里的主要岗位有哪些?小白如何快速入门?

入门Web安全、安卓安全、二进制安全、工控安全还是智能硬件安全等等,每个不同的领域要掌握的技能也不同。 当然入门Web安全相对难度较低,也是很多人的首选。主要还是看自己的兴趣方向吧。 本文就以下几个问题来说明网络安全大致学习过程👇 网…

SpringCloud微服务调用方式(RestTemplate)

服务调用方式 RPC和HTTP 无论是微服务还是SOA,都面临着服务间的远程调用。那么服务间的远程调用方式有哪些呢? 常见的远程调用方式有以下2种: RPC:Remote Produce Call远程过程调用,类似的还有 。自定义数据格式&am…

learn C++ NO.4 ——类和对象(2)

1.类的6个默认成员函数 1.1.默认成员函数的概念 在 C 中,如果没有显式定义类的构造函数、析构函数、拷贝构造函数和赋值运算符重载函数,编译器会自动生成这些函数,这些函数被称为默认成员函数。 class Date { };初步了解了默认成员函数&am…

STL-常用算法(二.拷贝 替换 算术 集合)

开篇先附上STL-常用算法(一)的链接 STL-常用算法(一.遍历 查找 排序)_小梁今天敲代码了吗的博客-CSDN博客 目录 常用拷贝和替换算法: copy函数示例:(将v1容器中的元素复制给v2) replace函数示例&#…

Java 9 - 18 各个版本新特性总结

【 Java 9 - 18 各个版本新特性总结,B站视频介绍】https://www.bilibili.com/video/BV1PT411P7Wn?vd_source5a3a58ca0e99223ffb58cddf2f3a7282 一、模块化引入 模块是 Java 9 中新增的一个组件,可以简单理解为是package的上级容器,是多个pa…

gitlab建立新分支提交,cherry-pick部分更新

gitlab介绍 GitLab是一个基于Git的在线代码托管和协作平台,提供源代码管理、单元测试、CI/CD构建、代码审查等功能。它是一个开放源代码的Git仓库管理系统,使用 Ruby on Rails 构建GitLab 不仅具有自己的 Git 仓库管理系统,还具有很多其他的…

网络协议与攻击模拟-11-DHCP协议原理

DHCP 协议 1、掌握 DHCP 的工作原理 2、会在 Windows server 上去部署 DHCP 服务 3、抓流量 .正常 收到攻击后 一、 DHCP 1、 DHCP 基本概念 dhcp (动态主机配置协议):主要就是给客户机提供 TCP / IP 参数( IP 地…

App外包开发上线Google Play流程

完成App开发后需要在各大应用市场上线,国内的应用市场比较多,各自的规则也不相同,上线审核也比较复杂;国外上线主要是Google Play市场,它更重视隐私的保护,必须严格按照规范来保护个人隐私,因此…

【C++】模板的一点简单介绍

模板 前言泛型编程函数模板概念格式函数模板的原理函数模板的实例化 类模板类模板的定义格式类模板的实例化 前言 这篇博客讲的是模板的一些基本知识,并没有那么深入,但是如果你是为了过期末考试而搜的这篇博客,我觉得下面讲的是够了的。 之…

阿里云、腾讯云、移动云飙“价”:智能普惠成新风向?

经过过去一年的“低迷”境况之后,2023年云服务商因为AI大模型的爆发,重新燃起了斗志。站在当下的时间节点,云服务商们也在重新思考如何在新形势下,让自己占据更大的优势,于是一场围绕“技术竞争与市场争夺”的新战争打…

【总结】Numpy2

Numpy 1. 数组和数的运算 array1 np.arange(1,10) array1 # array([1, 2, 3, 4, 5, 6, 7, 8, 9]) array1 10 # array([11, 12, 13, 14, 15, 16, 17, 18, 19]) array1 - 10 # array([-9, -8, -7, -6, -5, -4, -3, -2, -1]) array1 * 10 # array([10, 20, 30, 40, 50, 60, 70…

3-《安卓基础》

3-《安卓基础》 一.Android系统架构二.四大组件1. Activity1.1 生命周期1.2. Activity四种启动模式1.3.Activity任务栈的概念1.4 面试题面试题1:onSaveInstanceState(Bundle outState),onRestoreInstanceState(Bundle savedInstanceState) 的调用时机&am…

小黑子—Java从入门到入土过程:第十一章 - 网络编程、反射及动态代理

Java零基础入门11.0 网络编程1. 初识网络编程2. 网络编程三要素3.IP三要素3.1 IPV4的细节3.1.1特殊的IP地址3.1.2 常用的CMD命令 3.2 InetAddress 的使用3.3 端口号3.4 协议3.4.1 UDP协议3.4.1 - I UDP 发送数据3.4.1 - II UDP 接收数据3.4.1 - III UDP 练习(聊天室…

前端列表页+element-puls实现列表数据弹窗功能

效果图: 这是一个修改的弹窗,我们要实现的功能是,在列表,点击修改按钮时,将数据带入到弹窗里面,点击保存时关闭弹窗。 1,点击修改展开弹窗 使用 eldialog组件,v-model绑定的值为tru…

Godot引擎 4.0 文档 - 入门介绍 - 学习新功能

本文为Google Translate英译中结果,DrGraph在此基础上加了一些校正。英文原版页面: Learning new features — Godot Engine (stable) documentation in English 学习新功能 Godot 是一个功能丰富的游戏引擎。有很多关于它的知识。本页介绍了如何使用…

迪赛智慧数——柱状图(基本柱状图):全球自动化无人机智能支出预测

效果图 全球自动化无人机智能支出及预测分析,2022年机器人流程自动化支出10.4十亿美元,智能流程自动化支出13十亿美元,人工智能业务操作达10.8十亿美元,未来,这些数字将进一步增长,自动化无人机智能也将拥有…

华为OD机试真题 Java 实现【天然蓄水池】【2023Q1 200分】

一、题目描述 公元2919年,人类终于发现了一颗宜居星球——X星。现想在X星一片连绵起伏的山脉间建一个天然蓄水库,如何选取水库边界,使蓄水量最大? 要求: 山脉用正整数数组s表示,每个元素代表山脉的高度。…