溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用Python來做一個屏幕錄制工具

發(fā)布時間:2021-10-27 16:50:13 來源:億速云 閱讀:343 作者:柒染 欄目:編程語言

如何使用Python來做一個屏幕錄制工具,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

一、寫在前面

作為一名測試,有時候經(jīng)常會遇到需要錄屏記錄自己操作,方便后續(xù)開發(fā)同學定位。以前都是用ScreenToGif來錄屏制作成動態(tài)圖,偶爾的機會看到python也能實現(xiàn)。那就趕緊學習下。

二、效果展示

三、知識串講

這次要講的東西可能比較多了,涉及到pyqt5 GUI軟件的制作、QThread多線程的使用、Sikuli庫的圖形操作、win32庫的模擬鍵盤操作、cv2庫的寫視頻文件等。下面我們一點點來蠶食我這次寫的代碼。

1、GUI界面制作

這次我用的是現(xiàn)成的Pyqt5界面布局類,QVBoxLayout。這個類可以快速協(xié)助我完成按鈕的垂直分布,而且按鈕添加也更方便。

button1 = QPushButton("自定義錄屏")layout.addWidget(button1)

兩行代碼就完成了按鈕的命名和添加。我之前玩qt時,用的都是qt的UI界面,對應(yīng)生成的組件代碼也比較復(fù)雜。因此,在開發(fā)一些少量按鈕、簡單布局時可以用QVBoxLayout類。如果喜歡水平布局,可以用QHBoxLayout類,使用方法是一樣的。

另外,在按鈕點擊關(guān)聯(lián)的功能函數(shù),即work()方法時,如果想帶參數(shù),可以通過lambda匿名函數(shù)來實現(xiàn)。這 也是個小技巧。

# 不帶參數(shù)button1.clicked.connect(self.work)# 帶參數(shù)button1.clicked.connect(lambda: self.work(1))

2、QThread類的多線程使用

因為錄屏工具有開始和停止兩個功能,一開始時我用的是單線程,發(fā)現(xiàn)工具就會卡死。查了一些資料,發(fā)現(xiàn)針對這種情況,應(yīng)該要使用多線程來實現(xiàn),而QT庫中本身就有多線程類--QThread。

使用方法是通過繼承QThread類,重寫run方法來實現(xiàn)的。

(但是其實這種使用方法,QT大神們是不贊成這樣使用的,我會在第2篇文章中再簡單說明更好的多線程使用方法)

這 里要注意,work()函數(shù)必須是Ui_Mainwindow類方法,因為如果不是類方法,會在運行GUI時導(dǎo)致生命周期直接結(jié)束,導(dǎo)致錄屏代碼沒見運行就報錯退出。

class WorkThread(QThread):  def __init__(self, n):    super(WorkThread, self).__init__()    self.n = n  def run(self):    XXXXX

3、sikuli庫圖形識別

由于這個庫的使用方法和介紹,我在之前的博客里已經(jīng)提過 了。因此只簡單地呈現(xiàn)下代碼。這段代碼主要是為了自定義錄屏時,可以獲取選擇范圍的坐標值,并傳值給recording函數(shù),從而完成自定義錄屏功能。

def SelectRegion():  jvmPath = jpype.get_default_jvm_path()  jpype.startJVM(jvmPath, '-ea', '-Djava.class.path=F:\\sikuli\\1\\sikulixapi.jar') #加載jar包路徑  Screen = jpype.JClass('org.sikuli.script.Screen')  myscreen = Screen()  region = myscreen.selectRegion() # 自定義獲取屏幕范圍  return region

4、win32庫模擬鍵盤操作

其實這個庫不用也是可以的,我為什么要用呢?主要是為了方便用戶在進行錄屏時,能自動將工具界面縮小。一切為了用戶嘛!

以下這段代碼 是為了縮小工具窗口,其中91表示左win鍵,40表示方向向下鍵。****即win+向下鍵是可以實現(xiàn)窗口縮小功能的。****keybd_event(91, 0, 0, 0)表示按下win鍵,

keybd_event(91, 0, win32con.KEYEVENTF_KEYUP, 0)則是松開win鍵。

另外,這里為什么要加 上sleep(0.5)?這是因為在按下win鍵后要延遲按方向鍵,不然是 不起作用的。

def Minimize_Window():  win32api.keybd_event(91, 0, 0, 0)  time.sleep(0.5)  win32api.keybd_event(40, 0, 0, 0)  time.sleep(0.5)  win32api.keybd_event(91, 0, win32con.KEYEVENTF_KEYUP, 0)  win32api.keybd_event(40, 0, win32con.KEYEVENTF_KEYUP, 0)

5、錄屏主代碼

這段代碼其實網(wǎng)上已經(jīng)有很多類似的代碼,并且我已經(jīng)加了注釋,相信大家應(yīng)該能理解。這里我想注明下的是:如何停止錄屏。

如果大家有去 網(wǎng)上查如何停止錄屏的方法,很多人都會寫以下代碼:

if cv2.waitKey(1) & 0xFF == ord('q'):  break

然后告訴你,按q鍵就會停止錄屏。但是你會發(fā)現(xiàn),實際情況根本停止不了,為什么呢?因為還 有一句屏幕顯示的代碼:

cv2.imshow('imm', img_bgr)if cv2.waitKey(1) & 0xFF == ord('q'):  break

如果你不親自執(zhí)行一次,你以為會萬事大吉,但你錯了。這樣寫,會導(dǎo)致你的電腦屏幕被每一幀畫面給撐暴!因為用的while True,因此每一幀畫面都會顯示,即1S 25幀畫面會不停地顯示在你桌面上!

因此,綜上的問題,我采用了一種取巧的方法:在錄屏開始時生成一個標記文件,通過標記文件是否被刪除來判斷是否要停止錄屏功能。

四、示例代碼

1、工具GUI界面代碼:

# coding=utf-8# @Software : PyCharm#Python學習群827513319import sysfrom PyQt5.QtCore import *from PyQt5.QtWidgets import *import timeimport win32api,win32confrom recording import *class WorkThread(QThread):  def __init__(self, n):    super(WorkThread, self).__init__()    self.n = n  def run(self):    if self.n == 1:      Minimize_Window()      Recording(1)    elif self.n == 2:      Minimize_Window()      Recording(2)    else:      StopRecording()def Minimize_Window():  win32api.keybd_event(91, 0, 0, 0)  time.sleep(0.5)  win32api.keybd_event(40, 0, 0, 0)  time.sleep(0.5)  win32api.keybd_event(91, 0, win32con.KEYEVENTF_KEYUP, 0)  win32api.keybd_event(40, 0, win32con.KEYEVENTF_KEYUP, 0)class Ui_Mainwindow():  def setupUi(self, top):    # 垂直布局類QVBoxLayout    layout = QVBoxLayout(top)    # 添加錄屏相關(guān)按鈕    button1 = QPushButton("自定義錄屏")    layout.addWidget(button1)    button2 = QPushButton("全屏錄屏")    layout.addWidget(button2)    button3 = QPushButton("停止錄屏")    layout.addWidget(button3)    self.text = QPlainTextEdit('歡迎使用!')    layout.addWidget(self.text)    button1.clicked.connect(lambda: self.work(1))    button2.clicked.connect(lambda: self.work(2))    button3.clicked.connect(lambda: self.work(3))  def work(self, n):    if n == 1 :      print('已選擇自定義錄屏:')      self.text.setPlainText('正在錄屏中,請等待……')    elif n == 2 :      print('已選擇全屏錄屏:')      self.text.setPlainText('正在錄屏中,請等待……')    else:      print('已選擇結(jié)束錄屏:')      self.text.setPlainText('錄屏結(jié)束!(點擊關(guān)閉按鈕,可退出程序!)')    self.workThread = WorkThread(n)    self.workThread.start()if __name__ == "__main__":  app = QApplication(sys.argv)  top = QWidget()  top.setWindowTitle('錄屏小工具')  top.resize(300, 170)  ui = Ui_Mainwindow()  ui.setupUi(top)  top.show()  sys.exit(app.exec_())# coding=utf-8

2、錄屏函數(shù)

# coding=utf-8# @Software : PyCharmfrom PIL import ImageGrabimport numpy as npimport cv2import osimport jpypedef Recording(tag=1):  # 錄屏開始時創(chuàng)建test.txt,作為結(jié)束錄屏的條件  #Python學習群827513319  if not os.path.exists('test.txt'):    f = open('test.txt', 'w')    f.close()  # 根據(jù)tag值判斷自定義錄屏或全錄屏  if tag == 1:    r = SelectRegion()    record_region = (r.x, r.y, r.w + r.x, r.h + r.y) # 自定義錄屏的范圍(左上坐標、右下坐標)  elif tag == 2:    record_region = None  image = ImageGrab.grab(record_region) # 獲取指定范圍的屏幕對象  width, height = image.size  fourcc = cv2.VideoWriter_fourcc(*'XVID')  video = cv2.VideoWriter('test.avi', fourcc, 25, (width, height)) # 默認視頻為25幀  while True:    captureImage = ImageGrab.grab(record_region) # 抓取指定范圍的屏幕    frame = cv2.cvtColor(np.array(captureImage), cv2.COLOR_RGB2BGR)    video.write(frame) # 將每幀畫面寫視頻文件    # 停止錄屏的條件:test.txt被刪除    if not os.path.exists('test.txt'):      break  video.release()  cv2.destroyAllWindows()def SelectRegion():  jvmPath = jpype.get_default_jvm_path()  jpype.startJVM(jvmPath, '-ea', '-Djava.class.path=F:\\sikuli\\1\\sikulixapi.jar') #加載jar包路徑  Screen = jpype.JClass('org.sikuli.script.Screen')  myscreen = Screen()  region = myscreen.selectRegion() # 自定義獲取屏幕范圍  return regiondef StopRecording():  os.remove('test.txt') #停止錄屏的觸發(fā)條件if __name__ == "__main__":  Recording()

至此,基本實現(xiàn)了錄屏小工具的代碼開發(fā)。但是如果你是對代碼中的相關(guān)庫不熟悉,或者都沒下載相關(guān)的庫,那我相信你還會遇到很多坑。

看完上述內(nèi)容,你們掌握如何使用Python來做一個屏幕錄制工具的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI