1, Write in front
As a test, sometimes it is often necessary to record their own operation on the screen, so as to facilitate the follow-up development and positioning of students. In the past, screen to GIF was used to record the screen and make dynamic pictures. Occasionally, python can also be realized. Then hurry to learn.
2, Effect display
3, Knowledge collusion
There may be more to talk about this time, involving the production of pyqt5 GUI software, the use of QThread multithreading, the graphic operation of Sikuli library, the analog keyboard operation of win32 library, the writing of video files of cv2 library, etc. Now let's nibble at the code I wrote this time.
1. GUI interface making
This time I used the ready-made Pyqt5 interface layout class, QVBoxLayout. This class can help me quickly complete the vertical distribution of buttons, and it is more convenient to add buttons.
button1 = QPushButton("Custom recording") layout.addWidget(button1)
Two lines of code completes the naming and adding of the button. When I used to play qt, I used the UI of qt, and the generated component code was also complex. Therefore, the QVBoxLayout class can be used when developing a few buttons and simple layouts. If you like horizontal layout, you can use the QHBoxLayout class. The method is the same.
In addition, when clicking the function associated with the button, i.e. the work() method, if you want to take parameters, you can implement it through the lambda anonymous function. It's also a trick.
# Without parameters button1.clicked.connect(self.work) # Band parameters button1.clicked.connect(lambda: self.work(1))
2. Multithreading of QThread class
Because the screen recorder has two functions: start and stop. At the beginning, I used a single thread and found that the tool would be stuck. After checking some data, it is found that in this case, multithreading should be used, and QT library itself has multithreading class - QThread.
The method is implemented by inheriting the QThread class and overriding the run method.
(but in fact, QT gods do not approve of this method. I will explain a better way to use multithreading in the second article.)
Note here that the work() function must be a UI ﹣ MainWindow class method, because if it is not a class method, it will directly end the life cycle when the GUI is running, resulting in the error exit when the screen recording code is not running.
class WorkThread(QThread): def __init__(self, n): super(WorkThread, self).__init__() self.n = n def run(self): XXXXX
3. Figure recognition of sikuli Library
Because of the usage and introduction of this library, I have mentioned it in my previous blog. So just simply render the code. This code is mainly used to obtain the coordinate value of the selected range and pass the value to the recording function when the screen recording is customized, so as to complete the customized screen recording function.
def SelectRegion(): jvmPath = jpype.get_default_jvm_path() jpype.startJVM(jvmPath, '-ea', '-Djava.class.path=F:\\sikuli\\1\\sikulixapi.jar') #Load jar Packet path Screen = jpype.JClass('org.sikuli.script.Screen') myscreen = Screen() region = myscreen.selectRegion() # Custom get screen range return region
4. win32 library simulating keyboard operation
In fact, it's OK to use this library. Why should I use it? It is mainly for the convenience of the user to automatically reduce the tool interface when recording the screen. All for users!
The following code is to narrow the tool window, where 91 represents the left win key and 40 represents the direction down key. ****That is to say, win + down key can reduce the window. ****Keybd [event (91, 0, 0, 0) means to press win key,
Keybd? Event (91, 0, win32con. Keyeventf? Keyup, 0) is to release the win key.
In addition, why do we add sleep(0.5)? This is because you need to delay pressing the direction key after pressing the win key, otherwise it will not work.
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. Recording main code
In fact, there are many similar codes on the Internet, and I have added comments. I believe you can understand them. Here I'd like to note how to stop recording.
If you go to the Internet to find out how to stop screen recording, many people will write the following code:
if cv2.waitKey(1) & 0xFF == ord('q'): break
Then I'll tell you that pressing the q key will stop the recording. But you will find that the actual situation can not stop. Why? Because there is another code on the screen:
cv2.imshow('imm', img_bgr) if cv2.waitKey(1) & 0xFF == ord('q'): break
If you don't do it yourself, you think everything will be OK, but you are wrong. If you write like this, your computer screen will be blown up by every frame! Because of the while True, every frame will be displayed, that is, 1S 25 frame will be displayed on your desktop constantly!
Therefore, to sum up the problems, I used a shortcut method: generate a tag file at the beginning of screen recording, and judge whether to stop the screen recording function by whether the tag file is deleted.
4, Sample code
1. Tool GUI interface code:
# coding=utf-8 # @Software : PyCharm #Python Learning group 827513319 import sys from PyQt5.QtCore import * from PyQt5.QtWidgets import * import time import win32api,win32con from 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): # Vertical layout class QVBoxLayout layout = QVBoxLayout(top) # Add screen recording related buttons button1 = QPushButton("Custom recording") layout.addWidget(button1) button2 = QPushButton("Full screen recording") layout.addWidget(button2) button3 = QPushButton("Stop recording") layout.addWidget(button3) self.text = QPlainTextEdit('Welcome to use!') 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('Custom recording selected:') self.text.setPlainText('Recording screen, please wait') elif n == 2 : print('Full screen recording selected:') self.text.setPlainText('Recording screen, please wait') else: print('End recording selected:') self.text.setPlainText('End of recording!(Click the close button to exit the program!)') self.workThread = WorkThread(n) self.workThread.start() if __name__ == "__main__": app = QApplication(sys.argv) top = QWidget() top.setWindowTitle('Video recorder') top.resize(300, 170) ui = Ui_Mainwindow() ui.setupUi(top) top.show() sys.exit(app.exec_())# coding=utf-8
2. Screen recording function
# coding=utf-8 # @Software : PyCharm from PIL import ImageGrab import numpy as np import cv2 import os import jpype def Recording(tag=1): # Create at the beginning of recording test.txt,As a condition for ending recording #Python Learning group 827513319 if not os.path.exists('test.txt'): f = open('test.txt', 'w') f.close() # according to tag Value judgment user defined recording screen or full recording screen if tag == 1: r = SelectRegion() record_region = (r.x, r.y, r.w + r.x, r.h + r.y) # Range of custom recording screen (upper left coordinate, lower right coordinate) elif tag == 2: record_region = None image = ImageGrab.grab(record_region) # Gets the screen object for the specified range width, height = image.size fourcc = cv2.VideoWriter_fourcc(*'XVID') video = cv2.VideoWriter('test.avi', fourcc, 25, (width, height)) # Default video is 25 frames while True: captureImage = ImageGrab.grab(record_region) # Grab the screen in the specified range frame = cv2.cvtColor(np.array(captureImage), cv2.COLOR_RGB2BGR) video.write(frame) # Write video file for each frame # Conditions for stopping screen recording: test.txt Be deleted 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') #Load jar Packet path Screen = jpype.JClass('org.sikuli.script.Screen') myscreen = Screen() region = myscreen.selectRegion() # Custom get screen range return region def StopRecording(): os.remove('test.txt') #Trigger conditions for stopping screen recording if __name__ == "__main__": Recording()
Five, summary
At this point, the basic realization of the code development of screen recording gadgets. But if you are not familiar with the relevant libraries in the code or haven't downloaded them, I believe you will encounter many pitfalls. Therefore, in order to facilitate some small partners to run the code quickly, I will talk about some pits I encountered in the development in the next article, so that you can avoid these problems. OK, let's get here first! Bye!