Alright friends welcome back, lets make a very flexible screen recorder today. The target platform for this GUI is Windows 10. For direct installation to windows 10, please download these three parts in a folder and then extract (using winRAR) the PyShine Recorder setup.zip file:
IMPORTANT
Please run the code below only from PowerShell and not use any IDE, such as PyCharm or others, because it will not work in them properly. Copy the code below in a Python file as main.py and save it to a location. Then go to that location open up the Windows PowerShell as Shift+ Right click “open PowerShell window here” then run it as:
python3 main.py
main.py
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
# Subscribe to pyshine youtube channel for more learning videos.
# Its an Audio Video Screen Recoder in Python 3.
# -*- coding: utf-8 -*-
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
from PyQt5 import QtCore, QtGui, QtWidgets # pip install pyqt5
from PyQt5.QtWidgets import QFileDialog
import os
import pyautogui # pip install pyautogui
import cv2
import numpy as np
import pygetwindow as gw
import _thread
import imutils
import time
import signal
from threading import Thread
import shlex
import psutil
import subprocess
from subprocess import Popen
from dateutil.relativedelta import relativedelta # Install it via: pip install python-dateutil
try:
os.remove("output_video.mp4")
except:
pass
drawing = False
global x1, y1, x2,y2,num,h,w,windowRegion
x1,y1,x2,y2,h,w = 0,0,0,0,0,0
windowRegion=0
num = 0
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.threadpool = QtCore.QThreadPool()
MainWindow.setObjectName("MainWindow")
sizeObject = QtWidgets.QDesktopWidget().screenGeometry(-1)
H = (sizeObject.height())
W = (sizeObject.width())
self.W = W
self.H = H
MainWindow.resize(W//8, H//10)
MainWindow.setMinimumSize(QtCore.QSize(W//5, H//7))
MainWindow.setAcceptDrops(True)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.comboBox = QtWidgets.QComboBox(self.centralwidget)
self.comboBox.setObjectName("comboBox")
self.comboBox.addItem('')
self.cmd = ""
""" AUDIO and VIDIO DEVICES """
from PyQt5.QtMultimedia import QAudioDeviceInfo,QAudio,QCameraInfo
# List of Audio Input Devices
input_audio_deviceInfos = QAudioDeviceInfo.availableDevices(QAudio.AudioInput)
for device in input_audio_deviceInfos:
self.comboBox.addItem(device.deviceName())
""" ---------------------- """
self.comboBox.setCurrentIndex(1)
self.Mic = input_audio_deviceInfos[0].deviceName()
self.gridLayout.addWidget(self.comboBox, 1, 0, 1, 1)
self.radioButton = QtWidgets.QRadioButton(self.centralwidget)
self.radioButton.setObjectName("radioButton")
self.gridLayout.addWidget(self.radioButton, 2, 0, 1, 1)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setMinimumSize(QtCore.QSize(0, 23))
self.pushButton.setIconSize(QtCore.QSize(16, 25))
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 3, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.actionNew = QtWidgets.QAction(MainWindow)
self.actionNew.setObjectName("actionNew")
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.clicked = False
self.pushButton.clicked.connect(self.takeSnapNow)
self.radioButton.toggled.connect(self.setStatus)
self.comboBox.currentIndexChanged[str].connect(self.setAudioDevice)
self.th={}
self.cap = ""
self.useCam = False
self.st = 0
self.arguments = ''
self.process = None
def setAudioDevice(self,audioD):
self.Mic = audioD
def setStatus(self):
if self.useCam ==False:
self.useCam = True
else:
self.useCam = False
def draw_rect(self,event, x, y, flags, param):
global x1, y1, drawing, num, img, img2,x2,y2
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
x1, y1 = x, y
elif event == cv2.EVENT_MOUSEMOVE:
if drawing == True:
a, b = x, y
if a != x & b != y:
img = img2.copy()
cv2.rectangle(img, (x1,y1),(x,y), (0, 255, 0), 2)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
num += 1
font = cv2.FONT_HERSHEY_SIMPLEX
x2 = x
y2= y
def takeSnap(self):
global x1, y1, drawing, num, img, img2,x2,y2,h,w
global windowRegion
if self.useCam==False:
key=ord('a')
im1 = pyautogui.screenshot()
im1.save(r"monitor-1.png")
img= cv2.imread('monitor-1.png') # reading image
try:
os.remove('monitor-1.png')
except:
pass
cv2.putText(img,"Click and select the Region, Press w to confirm selection ",(self.W//8,self.H//2),cv2.FONT_HERSHEY_TRIPLEX, 1.3, (20,255,0), 2, cv2.LINE_AA)
img2=img.copy()
cv2.namedWindow("main", cv2.WINDOW_NORMAL)
cv2.setMouseCallback("main", self.draw_rect)
cv2.setWindowProperty("main", cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN);
while key!=ord('w'):
cv2.imshow("main",img)
key = cv2.waitKey(1)&0xFF
(h, w) = ((y2-y1),(x2-x1))
if key==ord('w'):
cv2.destroyAllWindows()
else:
x1,y1,w,h = ( 0, 0, self.W, self.H )
if w%2 ==0:
pass
else:
w=w+1
if h%2 ==0:
pass
else:
h=h+1
windowRegion = ( x1, y1, w, h )
return x1,y1,w,h
def run(self,inp,out):
global windowRegion
self.st = time.time()
cnt = 0
while (True):
if self.useCam ==True:
windowRegion = ( 0, 0, self.W, self.H )
frame = np.array(pyautogui.screenshot(region=windowRegion),dtype="uint8")
frame = imutils.resize(frame, width=480)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
cv2.imshow("Preview",frame)
rt = relativedelta(seconds=time.time()-self.st)
st = ('{:02d}:{:02d}:{:02d}'.format(int(rt.hours), int(rt.minutes), int(rt.seconds)))
self.pushButton.setText('Stop Recording: '+st)
if cv2.waitKey(1) == 27:
w = gw.getWindowsWithTitle('Windows PowerShell')[0]
w.close()
cv2.destroyAllWindows()
break
def takeSnapNow(self):
if self.clicked ==False:
filename = QtWidgets.QFileDialog.getSaveFileName( self.centralwidget,"Save video to file", os.sep.join((os.path.expanduser('~'), 'Desktop')), "MP4(*.mp4);;AVI(*.avi);;MKV(*.mkv);;MOV(*.mov)")
while filename[0] == '':
pyautogui.alert(text='Please write a video name', title='File name required', button='OK')
filename = QtWidgets.QFileDialog.getSaveFileName( self.centralwidget,"Save video to file", os.sep.join((os.path.expanduser('~'), 'Desktop')), "MP4(*.mp4);;AVI(*.avi);;MKV(*.mkv);;MOV(*.mov)")
try:
os.remove(filename[0])
except:
pass
x1,y1,w,h = self.takeSnap()
# self.cmd = r'"ffmpeg -rtbufsize 100M -f dshow -i audio="{}" -f -y -rtbufsize 100M -f gdigrab -framerate 30 -offset_x {} -offset_y {} -video_size {}x{} -draw_mouse 1 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p "{}"'.format(self.Mic,x1,y1,w,h,filename[0])
self.cmd = """ffmpeg -rtbufsize 1500M -f dshow -i audio="{}" -f -y -rtbufsize 1500M -f gdigrab -framerate ntsc -offset_x {} -offset_y {} -video_size {}x{} -draw_mouse 1 -i desktop -c:v libx264 -r 30 -preset ultrafast -tune zerolatency -crf 1 -pix_fmt yuv420p "{}" """.format(self.Mic,x1,y1,w,h,filename[0])
self.arguments = shlex.split(self.cmd)
self.th[0] = Thread(target = self.run,args = (1,1))
self.th[1] = Thread(target = self.makeVideo,args = (1,))
self.th[0].start()
self.th[1].start()
self.clicked =True
self.pushButton.setShortcut("Ctrl+r")
self.radioButton.setEnabled(False)
else:
self.pushButton.setEnabled(False)
self.pushButton.setText('Finalizing...')
w = gw.getWindowsWithTitle('Windows PowerShell')[0]
w.close()
self.clicked =False
def makeVideo(self,inp):
#self.process = subprocess.Popen(self.arguments, shell=True)
FNULL = open(os.devnull, 'w')
retcode = subprocess.call(self.arguments, stdout=FNULL, stderr=subprocess.STDOUT)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "PyShine Video Recorder"))
self.comboBox.setItemText(0, _translate("MainWindow", "Select Audio Device"))
self.radioButton.setText(_translate("MainWindow", "Full Screen"))
self.pushButton.setText(_translate("MainWindow", "Start Recording"))
self.pushButton.setShortcut(_translate("MainWindow", "Ctrl+r"))
self.actionNew.setText(_translate("MainWindow", "New"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
# Subscribe to pyshine youtube channel for more learning videos.
# Its an Audio Video Screen Recoder in Python 3.
# -*- coding: utf-8 -*-
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""