I’m creating a special purpose video player in Python 3.6 using OpenCV3 and ffmepg for handling the images and using PyQt5 for the Windows environment. I chose this combination of packages because ffmpeg handles a wider variety of codecs than QtMultimedia. I’ve run into one snag. My player does not play at regular speed – it plays at roughly ¾ of normal speed. I use QTimer.timer to loop my display engine (nextFrameSlot) at a speed of 1/framerate. Any suggestions on how to get the video to play at regular speed? Here is an abbreviated set of code that demonstrates my problem. import sys from PyQt5.QtWidgets import QWidget, QLabel, QFormLayout, QPushButton, QMainWindow from PyQt5.QtWidgets import QAction, QMessageBox, QApplication, QFileDialog from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer import cv2 class VideoCapture(QWidget): def __init__(self, filename, parent): super(QWidget, self).__init__() self.cap = cv2.VideoCapture(str(filename[0])) self.length = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT)) self.frame_rate = self.cap.get(cv2.CAP_PROP_FPS) #self.codec = self.cap.get(cv2.CAP_PROP_FOURCC) self.video_frame = QLabel() parent.layout.addWidget(self.video_frame) def nextFrameSlot(self): ret, frame = self.cap.read() frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) img = QImage(frame, frame.shape[1], frame.shape[0], QImage.Format_RGB888) pix = QPixmap.fromImage(img) self.video_frame.setPixmap(pix) def start(self): self.timer = QTimer() self.timer.timeout.connect(self.nextFrameSlot) self.timer.start(1000.0/self.frame_rate) def pause(self): self.timer.stop() def deleteLater(self): self.cap.release() super(QWidget, self).deleteLater() class VideoDisplayWidget(QWidget): def __init__(self,parent): super(VideoDisplayWidget, self).__init__(parent) self.layout = QFormLayout(self) self.startButton = QPushButton('Start', parent) self.startButton.clicked.connect(parent.startCapture) self.startButton.setFixedWidth(50) self.pauseButton = QPushButton('Pause', parent) self.pauseButton.setFixedWidth(50) self.layout.addRow(self.startButton, self.pauseButton) self.setLayout(self.layout) class ControlWindow(QMainWindow): def __init__(self): super(ControlWindow, self).__init__() self.setGeometry(50, 50, 800, 600) self.setWindowTitle("PyTrack") self.capture = None self.isVideoFileLoaded = False self.quitAction = QAction("&Exit", self) self.quitAction.setShortcut("Ctrl+Q") self.quitAction.triggered.connect(self.closeApplication) self.openVideoFile = QAction("&Open Video File", self) self.openVideoFile.setShortcut("Ctrl+Shift+V") self.openVideoFile.triggered.connect(self.loadVideoFile) self.mainMenu = self.menuBar() self.fileMenu = self.mainMenu.addMenu('&File') self.fileMenu.addAction(self.openVideoFile) self.fileMenu.addAction(self.quitAction) self.videoDisplayWidget = VideoDisplayWidget(self) self.setCentralWidget(self.videoDisplayWidget) def startCapture(self): if not self.capture and self.isVideoFileLoaded: self.capture = VideoCapture(self.videoFileName, self.videoDisplayWidget) self.videoDisplayWidget.pauseButton.clicked.connect(self.capture.pause) self.capture.start() def endCapture(self): self.capture.deleteLater() self.capture = None def loadVideoFile(self): try: self.videoFileName = QFileDialog.getOpenFileName(self, 'Select a Video File') self.isVideoFileLoaded = True except: print ("Please Select a Video File") def closeApplication(self): choice = QMessageBox.question(self, 'Message','Do you really want to exit?',QMessageBox.Yes | QMessageBox.No) if choice == QMessageBox.Yes: print("Closing....") sys.exit() else: pass if __name__ == '__main__': app = QApplication(sys.argv) window = ControlWindow() window.show() sys.exit(app.exec_()) Continue reading...