如何用Python进行屏幕录制?

news2024/11/25 20:34:32

文章目录

    • 引言
    • 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.coloradmin.cn/o/559504.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cpu 内核 逻辑处理器的关系

6核CPU,12个逻辑处理器 一颗内核在一个时间片内只能执行一个内核线程;当物理CPU使用了超线程技术后,在CPU的一颗内核中,利用就是利用其中空闲的执行单元,模拟出另外一个核心(并不是真正的物理运算核心&…

公司招人,面了一个5年经验不会自动化的测试人,他凭什么要18K?

在深圳这家金融公司也待了几年,被别人面试过也面试过别人,大大小小的事情也见识不少,今天又是团面的一天, 一百多个人都聚集在一起,因为公司最近在谈项目出来面试就2个人,无奈又被叫到面试房间。 整个过程…

【算法训练(day5)】前缀和与差分

目录 一.一维前缀 二.二维前缀和 三.一维差分 四.二维差分 一.一维前缀 1.前缀的作用 前缀用于在求一部分区间的和,比方说有一组数据a1,a2,a3,a4,我们想知道从第一个元素一直相加到最后一个元素的和或者是从第二个元素加到第三个元素,这种情况下就能…

docker部署elasticsearch:8.6.2, kibana,logstash 版本以及kibana的使用

文章目录 1、参考2、安装elasticsearch:8.6.22.1 创建网络2.2 创建无密码访问的elasticsearch服务2.3 访问验证2.4 建一个索引试试,此索引名为my-book,有六个字段2.5 用GET命令获取索引信息试试,如下,符合预期2.6 再试试批量导入一…

redis集群的架构、问题,附脑洞

本文首发自「慕课网」(www.imooc.com),想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"或慕课网公众号! 作者:一凡 | 慕课网讲师 Redis 是一种开源(BSD 许可&…

魔术表演-第14届蓝桥杯省赛Scratch中级组真题第1题

[导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成,后续会不定期解读蓝桥杯真题,这是Scratch蓝桥杯真题解析第136讲。 魔术表演,本题是2023年5月7日举行的第14届蓝桥杯省赛Scratch图形化编程中级组真题第1题&#xf…

【arxiv】论文找 idea : 关于 OVD 的论文扫读(四)

文章目录 一、DetCLIPv2: Scalable Open-Vocabulary Object Detection Pre-training via Word-Region Alignment二、Prompt-Guided Transformers for End-to-End Open-Vocabulary Object Detection三、Bridging the Gap between Object and Image-level Representations for Op…

2023年京东618预售数据免费开放(往年618热门品类数据回顾)

2023年618京东平台整体的活动节奏分为五个时期: 第一时期为预售期:2023年5月23日晚8点-5月31日 第二时期为开门红:5月31日20点-6月3日 第三时期为场景期:6月4日-6月15日 第四时期为高潮期:6月15日20点-6月18日 第五…

前端HTML之基础扫盲

博主简介:想进大厂的打工人博主主页:xyk:所属专栏: JavaEE初阶 本篇文章将讲解HTML的基础,认识HTML的基本结构,学会使用常用的HTML标签,愿诸位喜欢 目录 文章目录 一、创建第一个HTML程序 二、HTML基本标签介绍 2.1 HT…

AAAI2024 The Thirty-Eighth Conference on Artificial Intelligence

Past Conferences For information about past AAAI Conferences, please consult the following pages. https://aaai.org/conference/aaai/ Future Conferences https://aaai.org/aaai-conference/ 2024 年 2 月在加拿大温哥华举行的第 38 届 AAAI 人工智能年度会议 The…

Linkage Mapper 中 Climate Linkage Mapper功能解析(含实例分析)

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Linkage Mapper解密数字世界链接 Climate Linkage Mapper的输出结果,应用于华盛顿州和英属哥伦比亚省之间跨境地区的白松树效果图 图片来源地址 文

解决weekofyear跨年问题

目录 前言跨年问题计算当年第几周前言 前段时间,做了一个日期维度表的需求,发现 计算当年第几周 有误,发现 Hive 中 weekofyear 函数存在跨年问题! 跨年问题 这一周算上一年还是下一年,取决于这一周的大多数日期(4天及以上)在哪一年。算在前一年,就是前一年的最后一…

K8s in Action 阅读笔记——【1】Introducing Kubernetes

K8s in Action 阅读笔记——【1】Introducing Kubernetes 多年前,大多数软件应用程序都是庞大的单体应用,运行在单个进程或少量进程分布在几台服务器上。这些传统系统今天仍然广泛存在。它们具有缓慢的发布周期,更新相对不频繁。在每个发布周…

【软考数据库案例分析】(全)

目录 1.1 案例分析概述 1.2 数据流图设计 1.3 概念结构设计 1.4 关系模式设计 1.5 SQL语言设计 1.5.1 创建表(create table) 1.5.2 修改表 (alter table) 1.5.3 删除表 (drop table) 1.5.4 索引 1.5.5 视图 1.5.6 查询语句格式 1.6.7 分组查询 1.5.8 其他操作 1.5…

图书系统小练习

1.对于任何系统,我们最先想到的就是普通用户和管理员,所以我们第一件事情就是创建一个包,里面包含 管理员 Admin(继承User) 普通用户 NormalUser(继承User) abstract类的 User 2.然后就是我们的菜单了 我们将管…

“云端”医学馆 | 平行云助力拜科打造医疗虚仿新模式

“云端”医学馆——拜科医疗虚仿新体验 当前,各个行业都正经历着一场深刻的数字化变革,医疗领域也没有例外,很多医疗厂商都在积极拥抱数字化技术的融入与应用。拜科数字生物科技(中国)有限公司正是医疗虚仿潮流中的领…

数字图像处理 使用C#进行图像处理八 Unsharp Masking

一、Unsharp Masking简述 Unsharp Masking是一种线性图像处理技术,用于锐化图像。清晰的细节被识别为两者之间的差异原始图像及其模糊版本。然后缩放这些细节, 并添加回原始图像: 增强图像 = 原始图像 + 数量 *(原始图像 - 模糊) 模糊步骤可以使用任何图像滤波方法,例如…

AI绘画设计师专用单词表;游戏业AI正在疯抢工作;使用AI工具翻译整本英文书;用GPT-4搞定调研报告 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 『如果是皮克斯制作了哈利波特系列』又萌又暖还可爱,想 rua!! 皮克斯是美国顶级的电脑动画制作公司…

IMX6ULL裸机篇之DDR3实验总结

一. DDR实验 之前关于 IMX6ULL开发板,有关DDR实验。做了DDR内存芯片的初始化,校验与超频测试。 博文链接如下: IMX6ULL裸机篇之DDR3初始化_凌雪舞的博客-CSDN博客 IMX6ULL裸机篇之DDR3校验与超频测试_凌雪舞的博客-CSDN博客 经过了初始化…

修改linux中的grub和grub2.cfg文件重启服务器失败报错

文章目录 前言一、确认下root路径二、在引导界面进入grub 前言 修改了grub在服务器重启过程中发现系统起不来,且进入了紧急模式,相关报错如下: /dev/centos/root does not exist 总体原因就是找不到启动系统的文件位置导致的,解…