title: How can I implement a media player (music) that shows the playback time in realtime in PyQt5?
body: <p>I am trying to implement a simple media player widget in PyQt5. My widget has a Play/Pause and a Stop button, a vertical slider for the volume and an horizontal slider (posSlider) that shows and modifies playback progress. I would like to add a label (posLabel) that shows the playback time in realtime. I have tried using the time library and QTimer from Pyqt5.QtCore but the run crashes. Any idea?</p>
  <p>Notes on the code:</p>
  <ul>
  <li><p>AudioFile is a class I implemented that represents audio files and that has different properties, such as title, thumbnail, path, duration...</p>
  </li>
  <li><p>Under my widget class there is the python file from ChannelModifier.ui</p>
  <pre><code>  from PyQt5.QtWidgets import QApplication, QWidget
    from PyQt5.QtCore import QUrl, QTimer
    from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
    from PyQt5.QtGui import QPixmap
    from PyQt5.uic import loadUi
  
    import sys
    import time
  
  
    class ChannelModifier(QWidget):
  
    def __init__(self, af: AudioFile):
        super(ChannelModifier, self).__init__()
        loadUi(&quot;ChannelModifier.ui&quot;, self)
  
        self.setFixedSize(500, 500)
        self.af = af
        # self.play = False
        self.posLabel.setText(&quot;0:00&quot;)
        self.start_time = 0
        self.elapsed_time = 0
  
        if self.af.get_thumb_path():
            self.thumb.setPixmap(QPixmap(self.af.get_thumb_path()))
        else:
            self.thumb.setText(self.af.get_title())
  
        self.player = QMediaPlayer()
        url = QUrl.fromLocalFile(self.af.get_path())
        self.content = QMediaContent(url)
        self.player.setMedia(self.content)
        self.player.positionChanged.connect(self.change_position)
        self.player.durationChanged.connect(self.change_duration)
  
        self.playPauseButton.clicked.connect(self.play_pause_player)
        self.stopButton.clicked.connect(self.stop_player)
        self.volumeSlider.valueChanged.connect(self.change_volume)
        self.posSlider.sliderMoved.connect(self.set_position)
  
    def set_time_label(self):
        t = self.elapsed_time
        dur_in_secs = self.af.get_duration()[0] * 60 + self.af.get_duration()[1]
        while t &lt; dur_in_secs:
            mins = t // 60
            secs = t % 60
            timer = '{:02d}:{:02d}'.format(mins, secs)
            self.posLabel.setText(timer)
            time.sleep(1)
            t += 1
  
    def change_position(self, position):
        self.posSlider.setValue(position)
  
    def change_duration(self, duration):
        self.posSlider.setRange(0, duration)
        # self.player.duration() = 217286 in millisecs!!
  
    def set_position(self, position):
        self.player.setPosition(position)
  
    def play_pause_player(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
            self.elapsed_time = time.perf_counter() - self.start_time
        else:
            self.player.play()
            # NOT WORKING
            # if self.elapsed_time:
            #     self.set_time_label(self.elapsed_time)
            # else:
            #     self.start_time = time.perf_counter()
            #     self.set_time_label(0)
  
    def stop_player(self):
        self.player.stop()
        self.posLabel.setText(&quot;0:00&quot;)
        self.start_time = 0
        self.elapsed_time = 0
  
    def change_volume(self):
        vol = self.volumeSlider.value()
        self.player.setVolume(vol)
  
  
    # ChannelModifier.py
    class Ui_Form(object):
        def setupUi(self, Form):
            Form.setObjectName(&quot;Form&quot;)
            Form.resize(302, 261)
            self.playPauseButton = QtWidgets.QPushButton(Form)
            self.playPauseButton.setGeometry(QtCore.QRect(10, 170, 111, 41))
            self.playPauseButton.setObjectName(&quot;playPauseButton&quot;)
            self.thumb = QtWidgets.QLabel(Form)
            self.thumb.setGeometry(QtCore.QRect(20, 20, 211, 131))
            font = QtGui.QFont()
            font.setFamily(&quot;Cantarell&quot;)
            font.setPointSize(14)
            font.setBold(False)
            font.setItalic(False)
            font.setWeight(9)
            self.thumb.setFont(font)
            self.thumb.setStyleSheet(&quot;background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 rgba(165, 165, 247, 255), stop:1 rgba(255, 255, 255, 255));\n&quot;
    &quot;font: 75 14pt \&quot;Cantarell\&quot;;&quot;)
            self.thumb.setText(&quot;&quot;)
            self.thumb.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
            self.thumb.setObjectName(&quot;thumb&quot;)
            self.stopButton = QtWidgets.QPushButton(Form)
            self.stopButton.setGeometry(QtCore.QRect(130, 170, 111, 41))
            self.stopButton.setObjectName(&quot;stopButton&quot;)
            self.layoutWidget = QtWidgets.QWidget(Form)
            self.layoutWidget.setGeometry(QtCore.QRect(260, 10, 26, 241))
            self.layoutWidget.setObjectName(&quot;layoutWidget&quot;)
            self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget)
            self.verticalLayout.setContentsMargins(0, 0, 0, 0)
            self.verticalLayout.setObjectName(&quot;verticalLayout&quot;)
            self.volumeSlider = QtWidgets.QSlider(self.layoutWidget)
            self.volumeSlider.setOrientation(QtCore.Qt.Orientation.Vertical)
            self.volumeSlider.setObjectName(&quot;volumeSlider&quot;)
            self.verticalLayout.addWidget(self.volumeSlider)
            self.volumeLabel = QtWidgets.QLabel(self.layoutWidget)
            self.volumeLabel.setObjectName(&quot;volumeLabel&quot;)
            self.verticalLayout.addWidget(self.volumeLabel)
            self.posLabel = QtWidgets.QLabel(Form)
            self.posLabel.setGeometry(QtCore.QRect(195, 230, 51, 21))
            self.posLabel.setText(&quot;&quot;)
            self.posLabel.setObjectName(&quot;posLabel&quot;)
            self.posSlider = QtWidgets.QSlider(Form)
            self.posSlider.setGeometry(QtCore.QRect(9, 230, 181, 24))
            self.posSlider.setOrientation(QtCore.Qt.Orientation.Horizontal)
            self.posSlider.setObjectName(&quot;posSlider&quot;)
  
            self.retranslateUi(Form)
            QtCore.QMetaObject.connectSlotsByName(Form)
  
        def retranslateUi(self, Form):
            _translate = QtCore.QCoreApplication.translate
            Form.setWindowTitle(_translate(&quot;Form&quot;, &quot;Form&quot;))
            self.playPauseButton.setText(_translate(&quot;Form&quot;, &quot;Play/Pause&quot;))
            self.stopButton.setText(_translate(&quot;Form&quot;, &quot;Stop&quot;))
            self.volumeLabel.setText(_translate(&quot;Form&quot;, &quot;Vol&quot;))
  </code></pre>
  </li>
  </ul>