用Python進(jìn)行屏幕錄制的實(shí)現(xiàn)
引言
關(guān)于屏幕錄制這個(gè)功能需求,之前用過(guò)基于ffmpeg的Capture錄屏軟件,但是fps拉高以后會(huì)變得很卡,聲音也同樣出現(xiàn)卡頓。也自己嘗試過(guò)在python中調(diào)用ffmpeg的庫(kù)函數(shù),效果也不盡人意。網(wǎng)絡(luò)上下載了幾款錄屏軟件,不是要收費(fèi)就是下載到捆綁軟件或廣告很是心累,因此想借此機(jī)會(huì)重新研究一下屏幕錄制軟件的工作原理,同時(shí)當(dāng)作一個(gè)小項(xiàng)目練手。
gpt3.5給出的代碼
當(dāng)我還在猶豫是否要精心翻閱一下ffmpeg的說(shuō)明書(shū)時(shí),沒(méi)想到gpt已果斷給出了參考答案,可以使用Python的PyAutoGUI庫(kù)來(lái)實(shí)現(xiàn)錄屏功能。以下是一個(gè)簡(jiǎn)單的示例代碼:
import pyautogui import cv2 import numpy as np # 獲取屏幕分辨率 screen_size = (1920, 1080) # 設(shè)置視頻編碼器 fourcc = cv2.VideoWriter_fourcc(*"XVID") # 創(chuàng)建視頻寫(xiě)入對(duì)象 out = cv2.VideoWriter("output.avi", fourcc, 20.0, screen_size) # 開(kāi)始錄屏 while True: # 獲取屏幕截圖 img = pyautogui.screenshot() # 將截圖轉(zhuǎn)換為OpenCV格式 frame = np.array(img) frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 寫(xiě)入視頻 out.write(frame) # 按下q鍵退出錄屏 if cv2.waitKey(1) == ord("q"): break # 釋放資源 out.release() cv2.destroyAllWindows()
從給出的代碼看來(lái),屏幕錄制的工作原理就是以一定的幀率不斷地截圖,然后將截取的圖片以相同的幀率合成一個(gè)視頻。
放在安裝了pyautogui的python環(huán)境里運(yùn)行后,果然不出意外的話(huà)就要出意外了。gpt3.5給出的代碼卡在運(yùn)行中的界面紋絲不動(dòng),按’q’回車(chē)也并未退出循環(huán),再問(wèn)gpt也死活給不出修改方案。
查閱資料后發(fā)現(xiàn)要先imshow()之后,在ui窗口區(qū)域內(nèi)按鍵才能有效終止循環(huán):
import numpy as np import pyautogui import cv2 # 設(shè)置錄制參數(shù) SCREEN_SIZE = (1920, 1080) FILENAME = 'recorded_video.avi' FPS = 30.0 # 開(kāi)始錄制 fourcc = cv2.VideoWriter_fourcc(*"XVID") out = cv2.VideoWriter(FILENAME, fourcc, FPS, SCREEN_SIZE) while True: # 獲取屏幕截圖 img = pyautogui.screenshot() # 轉(zhuǎn)換為OpenCV格式 frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) # 寫(xiě)入視頻文件 out.write(frame) cv2.imshow('Frame', frame) cv2.resizeWindow('Frame', 1920, 1080) # 檢測(cè)按鍵 if cv2.waitKey(1) == ord('q'): break # 停止錄制 out.release() cv2.destroyAllWindows()
程序是能運(yùn)行了,但是效果依舊不好,窗口一直有遞歸的效果,而且導(dǎo)出的視頻其實(shí)是無(wú)法播放的。
更換截圖函數(shù)——ImageGrab.grab
pyautogui雖然能實(shí)現(xiàn)截圖,并在imshow里展示出來(lái),但是導(dǎo)出的視頻卻無(wú)法播放,考慮肯能涉及到具體視頻編解碼參數(shù)問(wèn)題,有懂的朋友請(qǐng)?jiān)谠u(píng)論區(qū)分享。這里采用更換PIL庫(kù)中的截圖函數(shù)ImageGrab.grab,可以實(shí)現(xiàn)截圖并導(dǎo)出視頻了,接下來(lái)最大的問(wèn)題就是解決遞歸現(xiàn)象。
import numpy as np import pyautogui import cv2 # 設(shè)置錄制參數(shù) SCREEN_SIZE = (1920, 1080) FILENAME = 'recorded_video.avi' FPS = 30.0 # 開(kāi)始錄制 fourcc = cv2.VideoWriter_fourcc(*"XVID") out = cv2.VideoWriter(FILENAME, fourcc, FPS, SCREEN_SIZE) while True: # 獲取屏幕截圖 img = pyautogui.screenshot() # 轉(zhuǎn)換為OpenCV格式 frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) # 寫(xiě)入視頻文件 out.write(frame) cv2.imshow('Frame', frame) cv2.resizeWindow('Frame', 1920, 1080) # 檢測(cè)按鍵 if cv2.waitKey(1) == ord('q'): break # 停止錄制 out.release() cv2.destroyAllWindows()
禁用imshow解決遞歸現(xiàn)象
視頻處理時(shí)的遞歸現(xiàn)象其實(shí)非常常見(jiàn),除了物理中的鏡面效應(yīng)(觀察兩個(gè)平行放置的鏡子會(huì)出現(xiàn)遞歸的現(xiàn)象),
將攝像頭對(duì)準(zhǔn)顯示器,顯示器上的畫(huà)面也會(huì)觀察到遞歸的現(xiàn)象:
經(jīng)嘗試,將imshow()禁用后,改為幀計(jì)數(shù)的方式自定義終止循環(huán)就不會(huì)出現(xiàn)遞歸的問(wèn)題了:
import numpy as np from PIL import ImageGrab import cv2 # 設(shè)置錄制參數(shù) SCREEN_SIZE = (1920, 1080) FILENAME = 'recorded_video.avi' FPS = 30.0 # 開(kāi)始錄制 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..') # 轉(zhuǎn)換為OpenCV格式 frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) # 寫(xiě)入視頻文件 out.write(frame) # cv2.imshow('Frame', frame) # cv2.resizeWindow('Frame', 1920, 1080) # # 檢測(cè)按鍵 # if cv2.waitKey(1) == ord('q'): # break cnt = cnt + 1 if cnt == 100: #滿(mǎn)100幀后終止循環(huán) break # 停止錄制 out.release() cv2.destroyAllWindows()
通過(guò)修改img = ImageGrab.grab(bbox=(0, 0, 2560, 1600))
中的參數(shù)可以自定義錄屏區(qū)域,x,y,w,h分別代表左上角坐標(biāo)(起始坐標(biāo))和圖片寬度、高度。比如我的屏幕分辨率是2560*1600,那么設(shè)置為0, 0, 2560, 1600就是錄制全屏:
這樣,我們就可以基本實(shí)現(xiàn)用Python進(jìn)行屏幕錄制的功能了。動(dòng)態(tài)圖預(yù)覽看上去分辨率不高是因?yàn)橛玫母袷焦S把錄制的視頻轉(zhuǎn)了gif,壓縮前錄制的視頻其實(shí)蠻清楚的。
通過(guò)修改fps的值,我們還可以自行錄制一些高刷新率的電影、游戲畫(huà)面,fps越高,畫(huà)面越流暢哦。
攝像頭錄制代碼
類(lèi)似的,也可以用python實(shí)現(xiàn)相機(jī)錄像的功能:
import cv2 import cv2 as cv # 打開(kāi)攝像頭 cap = cv2.VideoCapture(0) fourcc = cv.VideoWriter_fourcc(*'XVID') file_name = 'output' output = cv.VideoWriter((file_name + '.avi'), fourcc, 24.0, (640, 480)) #設(shè)置文件名,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()
后期需求
現(xiàn)在屏幕錄制的問(wèn)題基本解決了,要想做一個(gè)實(shí)用的屏幕錄制軟件,還需要加上音頻錄制,并設(shè)計(jì)一個(gè)便捷的UI界面。
小結(jié)
到此這篇關(guān)于用Python進(jìn)行屏幕錄制的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python屏幕錄制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用Python實(shí)現(xiàn)簡(jiǎn)單的人臉識(shí)別功能步驟詳解
這篇文章主要介紹了用Python實(shí)現(xiàn)簡(jiǎn)單的人臉識(shí)別功能步驟詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03python numpy中mat和matrix的區(qū)別
這篇文章主要介紹了python numpy中mat和matrix的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03Django 開(kāi)發(fā)環(huán)境配置過(guò)程詳解
這篇文章主要介紹了Django 開(kāi)發(fā)環(huán)境配置過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07numpy求解線(xiàn)性代數(shù)相關(guān)問(wèn)題
本文主要介紹了numpy求解線(xiàn)性代數(shù)相關(guān)問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-01-01python利用拉鏈法實(shí)現(xiàn)字典方法示例
這篇文章主要介紹了python利用拉鏈法實(shí)現(xiàn)字典的方法,文中給出了詳細(xì)的示例代碼,相信對(duì)大家具有一定的參考價(jià)值,需要的朋友可以們下面來(lái)一起看看吧。2017-03-03Django上使用數(shù)據(jù)可視化利器Bokeh解析
這篇文章主要介紹了Django上使用數(shù)據(jù)可視化利器Bokeh解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07使用Python實(shí)現(xiàn)下載并保存網(wǎng)絡(luò)圖片
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)下載并保存網(wǎng)絡(luò)圖片,不需要有編程經(jīng)驗(yàn),本文將以最簡(jiǎn)單的方式一步步教你完成,快了跟隨小編一起學(xué)習(xí)一下吧2024-12-12Python輕松實(shí)現(xiàn)2位小數(shù)隨機(jī)生成
在Python中,我們經(jīng)常需要生成隨機(jī)數(shù),特別是2位小數(shù)的隨機(jī)數(shù),這在模擬實(shí)驗(yàn)、密碼學(xué)、游戲開(kāi)發(fā)等領(lǐng)域都很有用,下面是如何在Python中生成2位小數(shù)的隨機(jī)數(shù)的代碼示例,需要的朋友可以參考下2023-11-11