用Python進行屏幕錄制的實現
引言
關于屏幕錄制這個功能需求,之前用過基于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")
# 創(chuàng)建視頻寫入對象
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環(huán)境里運行后,果然不出意外的話就要出意外了。gpt3.5給出的代碼卡在運行中的界面紋絲不動,按’q’回車也并未退出循環(huán),再問gpt也死活給不出修改方案。
查閱資料后發(fā)現要先imshow()之后,在ui窗口區(qū)域內按鍵才能有效終止循環(huán):
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里展示出來,但是導出的視頻卻無法播放,考慮肯能涉及到具體視頻編解碼參數問題,有懂的朋友請在評論區(qū)分享。這里采用更換PIL庫中的截圖函數ImageGrab.grab,可以實現截圖并導出視頻了,接下來最大的問題就是解決遞歸現象。
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()

禁用imshow解決遞歸現象
視頻處理時的遞歸現象其實非常常見,除了物理中的鏡面效應(觀察兩個平行放置的鏡子會出現遞歸的現象),
將攝像頭對準顯示器,顯示器上的畫面也會觀察到遞歸的現象:

經嘗試,將imshow()禁用后,改為幀計數的方式自定義終止循環(huán)就不會出現遞歸的問題了:
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幀后終止循環(huán)
break
# 停止錄制
out.release()
cv2.destroyAllWindows()

通過修改img = ImageGrab.grab(bbox=(0, 0, 2560, 1600))中的參數可以自定義錄屏區(qū)域,x,y,w,h分別代表左上角坐標(起始坐標)和圖片寬度、高度。比如我的屏幕分辨率是2560*1600,那么設置為0, 0, 2560, 1600就是錄制全屏:

這樣,我們就可以基本實現用Python進行屏幕錄制的功能了。動態(tài)圖預覽看上去分辨率不高是因為用的格式工廠把錄制的視頻轉了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界面。
小結
到此這篇關于用Python進行屏幕錄制的實現的文章就介紹到這了,更多相關Python屏幕錄制內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python numpy中mat和matrix的區(qū)別
這篇文章主要介紹了python numpy中mat和matrix的區(qū)別,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03

