This article explains how to make a Video Player in PyQt5.
One of PyQt5’s most unique widgets (in my opinion anyway) is the QMediaPlayer with it’s ability to display videos in a PyQt5 GUI. Since it’s a pretty complex task, you’ll need other classes and widgets from the QMultimedia class (we’ll explain all these).
In any case, it’s cool to know how to so that’s something. It looks pretty good and modern looking too so that’s another bonus. By the end of this article we’ll show you an implementation that looks almost as good as fully fledged Video players like VLC.
In the event that the Video does not load and play correctly, there must be an Issue with your Graphic drivers or something similar. I experienced issues on my Laptop (an APU) with an AMD Vega graphic card, so I switch over to my PC which had an NVIDIA card and it worked just fine.
Playing Videos in PyQt5
In this section we’ll discuss how to get a simple video player up and running. It’s a very bare bone video player with only the ability to play/pause videos and select a file.
Clicking the play button once will start the Video and clicking it again will pause the Video.
from PyQt5.QtCore import QDir, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QMainWindow, QWidget, QPushButton, QApplication,
QLabel, QFileDialog, QStyle, QVBoxLayout)
import sys
class VideoPlayer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PyQt5 Video Player")
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
videoWidget = QVideoWidget()
self.playButton = QPushButton()
self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
self.playButton.clicked.connect(self.play)
self.openButton = QPushButton("Open Video")
self.openButton.clicked.connect(self.openFile)
widget = QWidget(self)
self.setCentralWidget(widget)
layout = QVBoxLayout()
layout.addWidget(videoWidget)
layout.addWidget(self.openButton)
layout.addWidget(self.playButton)
widget.setLayout(layout)
self.mediaPlayer.setVideoOutput(videoWidget)
def openFile(self):
fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
QDir.homePath())
if fileName != '':
self.mediaPlayer.setMedia(
QMediaContent(QUrl.fromLocalFile(fileName)))
def play(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
app = QApplication(sys.argv)
videoplayer = VideoPlayer()
videoplayer.resize(640, 480)
videoplayer.show()
sys.exit(app.exec_())
It’s alot of code, so we’ll try explaining it line by line. For explanations regarding the non-Video Player code, please refer to our PyQt5 tutorial series where all other widgets are explained.
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
videoWidget = QVideoWidget()
In the first line we create our MediaPlayer object by passing the required parameters in QMediaPlayer. In the second we create a video widget using QVideoWidget.
self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
self.playButton.clicked.connect(self.play)
The first line is actually an optional one simply for the “look” of the “play button we’ll be creating. This line gives it that special triangular icon that all play buttons have. The second line connects the button to the play
function. More on the play
function later.
self.openButton = QPushButton("Open Video")
self.openButton.clicked.connect(self.openFile)
This the “open button” which will allow the user to select a video of his choice from his computer. We connect this button to the function called openFile
where the File dialog code is stored.
self.mediaPlayer.setVideoOutput(videoWidget)
Remember that video widget we created earlier? We need to pass that into our MediaPlayer Video output function. Imagine a QMediaPlayer as the actual supporting software around the video, and the QVideoWidget is the actual PyQt5 video output.
def openFile(self):
fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
QDir.homePath())
if fileName != '':
self.mediaPlayer.setMedia(
QMediaContent(QUrl.fromLocalFile(fileName)))
This function is responsible for creating a File Dialog which allows the user to pick a local video file from his computer. The filepath of the video file is returned which we will be using to set the QMediaContent
. The setMedia()
function is used to insert the MediaContent
into the MediaPlayer object you created.
def play(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
The play function is pretty simple. If the Video is not playing, the Video will begin once the play function is called. If the Video is playing, the play function will pause the video.
You could make this even simpler if you wanted by removing the play button and the file dialog. However, this would come at the cost of two things. The loss of the ability to play and pause at will and the ability to select the file to be played.
There’s no (significant) limit to the size of the video that you load up, as I tested a full length (2 hours 20 min) movie with QMediaPlayer and it worked perfectly.
Full Video Player in PyQt5
Below is the full implementation of a proper Video Player in PyQt5. There is only really one big change, which is the addition of a slider bar. Changing the position of this Slider will change the current scene playing on the Screen, just like a regular video player.
Another change is the addition of an error handling system. In the event the Video File you loaded was unable to run or some error occurred, an error message will display.
from PyQt5.QtCore import QDir, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel,
QPushButton, QSizePolicy, QSlider, QStyle, QVBoxLayout, QWidget)
from PyQt5.QtWidgets import QMainWindow,QWidget, QPushButton, QAction
from PyQt5.QtGui import QIcon
import sys
class VideoPlayer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("PyQt5 Video Player")
self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
videoWidget = QVideoWidget()
self.playButton = QPushButton()
self.playButton.setEnabled(False)
self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
self.playButton.clicked.connect(self.play)
self.positionSlider = QSlider(Qt.Horizontal)
self.positionSlider.setRange(0, 0)
self.positionSlider.sliderMoved.connect(self.setPosition)
self.error = QLabel()
self.error.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
openButton = QPushButton("Open Video")
openButton.setToolTip("Open Video File")
openButton.setStatusTip("Open Video File")
openButton.setFixedHeight(24)
openButton.clicked.connect(self.openFile)
# Create a widget for window contents
wid = QWidget(self)
self.setCentralWidget(wid)
# Create layouts to place inside widget
controlLayout = QHBoxLayout()
controlLayout.setContentsMargins(0, 0, 0, 0)
controlLayout.addWidget(self.playButton)
controlLayout.addWidget(self.positionSlider)
layout = QVBoxLayout()
layout.addWidget(videoWidget)
layout.addLayout(controlLayout)
layout.addWidget(self.error)
layout.addWidget(openButton)
# Set widget to contain window contents
wid.setLayout(layout)
self.mediaPlayer.setVideoOutput(videoWidget)
self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
self.mediaPlayer.positionChanged.connect(self.positionChanged)
self.mediaPlayer.durationChanged.connect(self.durationChanged)
self.mediaPlayer.error.connect(self.handleError)
def openFile(self):
fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
QDir.homePath())
if fileName != '':
self.mediaPlayer.setMedia(
QMediaContent(QUrl.fromLocalFile(fileName)))
self.playButton.setEnabled(True)
def exitCall(self):
sys.exit(app.exec_())
def play(self):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.mediaPlayer.pause()
else:
self.mediaPlayer.play()
def mediaStateChanged(self, state):
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
self.playButton.setIcon(
self.style().standardIcon(QStyle.SP_MediaPause))
else:
self.playButton.setIcon(
self.style().standardIcon(QStyle.SP_MediaPlay))
def positionChanged(self, position):
self.positionSlider.setValue(position)
def durationChanged(self, duration):
self.positionSlider.setRange(0, duration)
def setPosition(self, position):
self.mediaPlayer.setPosition(position)
def handleError(self):
self.playButton.setEnabled(False)
self.error.setText("Error: " + self.mediaPlayer.errorString())
app = QApplication(sys.argv)
videoplayer = VideoPlayer()
videoplayer.resize(640, 480)
videoplayer.show()
sys.exit(app.exec_())
An screen shot from a movie that I tested in QMediaPlayer.
This marks the end of the PyQt5 Video Player with QMediaPlayer article. Any suggestions or contributions for CodersLegacy are more than welcome. Questions regarding the article content can be asked in the comments section below.