当前位置: 首页 > 后端技术 > Python

教你用opencv-python库做一个录屏工具(附源码)

时间:2023-03-26 11:54:51 Python

目录应用平台录屏部分计算视频最优fps和用numpy计算中间帧数组用pynput监控键盘按键如何保存MP4格式视频源码总结最近一直在用录屏软件录制桌面。在使用的过程中突然想到用python是不是可以作为录屏工具,也可以锻炼自己的动手能力。接下来我准备写一个系列文章介绍如何使用python制作录屏工具:录屏、制作视频、录制音频、合成视频、基于pyqt5的音频制作可视化窗口。关于以上四个部分,希望能尽快完善,然后开始使用python制作录屏部分。应用平台windows10python3.7屏幕录制屏幕录制部分可以简单理解为以动画的形式播放屏幕快照。这里我选择PIL下的ImageGrab来抓屏。首先,\pipinstallPillow\需要被捕获。数组组合成视频,cv2模块\pipinstallopencv-python\ImageGrab类无法直接存储为视频,使用numpy模块进行数组,然后通过cv2.COLOR_BGR2RGB转换为cv2颜色通道.pipinstallnumpy录屏主要代码:importnumpyasnpfromPILimportImageGrabimportcv2im=ImageGrab.grab()width,high=im.size#获取屏幕的宽高fourcc=cv2.VideoWriter_fourcc(*'I420')#设置视频编码格式fps=15#设置帧率video=cv2.VideoWriter('test.avi',fourcc,fps,(width,high))whileTrue:#开始录制im=ImageGrab.grab()im_cv=cv2.cvtColor(np.array(im),cv2.COLOR_BGR2RGB)#Imagewritevideo.write(im_cv)ifxx:#当满足一定条件时打破循环breakvideo.release()#释放缓存,并持久化视频试运行可以保存截图为视频,但操作不优雅,不利于后续操作。封装成一个类,继承thread父类,方便使用键盘控制录像结束。fromthreadingimportThreadclassScreenshotVideo(Thread):def__init__(self):"""初始化参数"""super().__init__()文末会给出详细代码。计算视频的最优fps,使用numpy计算中间帧数组。在实际操作中,视频录制在不同的电脑上会有不同的帧率,从而导致视频播放时快时慢。需要根据不同的电脑计算出对应的最佳fps值。.defvideo_best_fps(self,path):"""获取电脑录制视频的最佳帧率"""video=cv2.VideoCapture(path)#读取视频fps=video.get(cv2.CAP_PROP_FPS)#获取当前视频Frameratecount=video.get(cv2.CAP_PROP_FRAME_COUNT)#获取视频帧数,即视频有多少帧self.best_fps=int(fps*((int(count)/fps)/self.spend_time))#计算比较播放时间和录制时间得到最优帧率video.release()然后调整帧率参数录制视频会减弱视频播放过快或过慢。您还可以增加视频的帧数以延长播放时间。这里我用一个很简单的方法来增加视频帧数,仅供参考。fromnumbaimportjit#使用numpy计算相邻两帧图像和距离下一帧较近的图像#调用jit方法加速数组计算@jit(nopython=True)defaverage_n(x,y):"""numpycalculationtrendNearvalue"""return((x+y+y)//3).astype(x.dtype)此方法仅适用于当设置的fps高于最佳fps时,处理后的视频看起来和感觉,视频还是比较短,但是细节帧的数量增加了,所以播放时间会比未处理的长,而且会有轻微的残影。录制视频时使用pynput监听键盘按键,不知道视频什么时候结束,所以用while循环包裹录制代码,但也不可能让代码没完没了的跑,使用监听键盘模块中断录制代码的运行。frompynputimportkeyboard#pipinstallpynputdefhotkey(self):"""Hotkeylistener"""withkeyboard.Listener(on_press=self.on_press)aslistener:listener.join()defon_press(self,key):try:ifkey.char=='t':#录屏完成,保存视频self.flag=Trueelifkey.char=='k':#录屏停止,删除文件self.flag=TrueTrueself.kill=exceptExceptionase:print(e)当按下键盘“T”键时,录制结束并保存视频。“K”键是停止录音和删除缓存文件。如何将视频保存为MP4格式视频编码格式应该是('a','v','c','1'),文件后缀是'.mp4',去https://github.com/cisco录制前在/open...下下载对应平台的dll.bz2文件,解压压缩包放入工程文件夹。再次运行代码,会出现一行编码说明:OpenH264VideoCodecprovidedbyCiscoSystems,Inc.sourcecode本文实现的源代码如下:importtimefromPILimportImageGrabimportcv2frompathlibimportPathimportnumpyasnpfromnumbaimportjitfrompynputimportkeyboardfromthreadingimportThread@jit(nopython=True)defaverage_n(x,y):"""Numpy计算逼近值"""return((x+y+y)//3).astype(x.dtype)classScreenshotVideo(Thread):def__init__(self,width,high,path='',fps=15):"""初始化参数"""super().__init__()self.save_file=pathself.best_fps=fps.fps=selfself.width=widthself.high=highself.spend_time=1self.flag=Falseself.kill=Falseself.video=Nonedef"call"__"(self,path):calls"""self.save_file=Path(path)self.video=self.init_videowriter(self.save_file)@staticmethoddefscreenshot():"""静态方法,截图,并转换为np.array数组"""returnnp.ar射线(我magegrab.grab())@StaticMethoddefGet_fourcc(name):""""VideoCodeDictionary""Fourcc_maps={'.avi':I420','.m4v':'mp4v','.mp4':':':':':':':'。AVC1','.oV':'Theo','.flv':'FLV1',}returnFourcc_maps.get(name)deps_videowriter(seld,PATH):"获取视频编码并创建新的视频文件""""""""""ifnotpath:raiseException('视频路径未设置,请设置\nvideo=ScreenshotVideo(fps,width,high)\nvideo=video(video_path)')path=Path(path)ifisinstance(path,str)elsepathfourcc=cv2.VideoWriter_fourcc(*self.get_fourcc(path.suffix))返回cv2.VideoWriter(path.as_posix(),fourcc,self.fps,(self.width,self.high))defvideo_record_doing(self,img):"""ConvertBGRarraytoRGBarray"""im_cv=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)self.video.write(im_cv)defvideo_record_end(self):"""结束根据条件判断文件录音的是否保存"""self.video.release()cv2.destroyAllWindows()ifself.save_fileandself.kill:Path(self.save_file).unlink()defvideo_best_fps(self,path):Best"""获取录制视频的帧通过计算机Rate"""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(fps)(self.spend_time))video.release()defpre_video_record(self):"""预录最佳fps值"""self.video=self.init_videowriter('test.mp4')start_time=time.time()for_inrange(10):im=self.screenshot()self.video_record_doing(im)self.spend_time=round(time.time()-start_time,4)ordsletime2self.end_rec)(self.video_best_fps('test.mp4')Path('test.mp4').unlink()definsert_frame_array(self,frame_list):"""Numpy增强截图信息"""fps_n=round(self.fps/self.best_fps)如果fps_n<=0:返回frame_list次=int(np.log2(fps_n))#倍率for_in范围(时间):frame_list2=][average_n][,,frame_list)frame_list=[[x,y]forx,yinzip(frame_list2,frame_list)]frame_list=[jforiinframe_listforjini]returnframe_listdefframe2video_run(self):"c"c“self.video=self.init_videOwriter(self.save_file)start_time=time.time.time.time()frame_list=[]breakself.spend_time=round(time.time()-start_time,4)如果不是self.kill:#视频视频视频录制不被终止将图像图像frame_list=self.insert_frame_array(frame_list)forframe_list:self.video_record_doinginframe_list:frame_frame_array(frame_list)(im)self.video_record_end()defhotkey(self):"""Hotkeylistener"""withkeyboard.Listener(on_press=self.on_press)作为监听器:listener.join()defon_press(self,key):try:ifkey.char=='t':#recordAt画面结束,保存视频self.flag=trueelfkey.char=='k':#:#文件seld.flag=trueself.kill=trueexceptionexceptionase:prop(e):#运行函数#设置守护进程线程Thread(target=self.hotkey,daemon=True).start()#运行截图函数self.frame2video_run()screen=ImageGrab.grab()width,highV=hotscreen=osizevideo(width,high,fps=60)video.pre_video_record()#预录得到最优fpsvideo('test1.mp4')video.run()总结本文目前使用opencv及相关模块进行录屏并转为视频保存,学习将多个功能封装成类,方便后续功能开发学习。学道无止境,让我们勇往直前!小伙伴们赶紧练起来吧!如果你在学习过程中遇到什么问题,欢迎关注我,我会拉你进Python学习交流群一起讨论学习。