11

I am trying to use QMediaPlayer to create a.. media player. I want to have an ability to rewind videos on press of a button.

But setting a negative playbackRate via QMediaPlayer.setPlaybackRate doesn't seem to put video on rewind. It just keeps playing forward.

I don't want to change the position of the video, I want the video to play at negative speed. Through some logic of mine, setting playbackRate to a negative value would make the video play in reverse. But that just doesn't happen. If you can't understand me clearly, here is a video of what the playback should look like.

Here is some barebones code to reproduce the problem:

import sys

from PyQt5.QtCore import Qt, QUrl, QEvent
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication

class VideoWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        videoWidget = QVideoWidget()
        self.setCentralWidget(videoWidget)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.setMedia(
            QMediaContent(QUrl.fromLocalFile(r"<some video file>.mp4"))
        )
        self.mediaPlayer.play()

        app.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QEvent.KeyPress:
            key = event.key()

            if key == Qt.Key_A:
                self.mediaPlayer.setPlaybackRate(1.0)
            elif key == Qt.Key_Y:
                self.mediaPlayer.setPlaybackRate(-1.0) # This doesn't work! :(

        return super().eventFilter(source, event)

    def closeEvent(self, event):
        self.mediaPlayer.setMedia(QMediaContent())

if __name__ == '__main__':
    app = QApplication(sys.argv)

    player = VideoWindow()
    player.resize(640, 480)
    player.show()

    exitCode = app.exec_()
    sys.exit(exitCode)

I tried searching for a solution, but I got nothing more than what documentation says (emphasis mine):

Values less than zero can be set and indicate the media will rewind at the multiplier of the standard pace.

However, I am not seeing this effect.

I did notice this:

Not all playback services support change of the playback rate.

Is it possible that I can't rewind an mp4? Perhaps I need to install / change something?

Božo Stojković
  • 2,893
  • 1
  • 27
  • 52
  • to me it works correctly in Linux with PyQt5 5.11.2, what is your OS and your version of PyQt5? – eyllanesc Sep 03 '18 at 21:25
  • please see https://github.com/baoboa/pyqt5/blob/master/examples/multimediawidgets/player.py – S. Nick Sep 03 '18 at 23:38
  • @eyllanesc I have Windows 10 (1803 I believe, if relevant) and the same version of PyQt. – Božo Stojković Sep 04 '18 at 05:06
  • @S.Nick I tried the example, and added `self.rateBox.addItem("-2.0x", -2.0)`, but choosing it doesn't rewind the video. It just keeps playing with last positive speed it was set to, just like in my code. – Božo Stojković Sep 04 '18 at 14:57
  • @eyllanesc Do you have any idea why it would work in Linux but not Windows? Could I be missing a program / package / setting / anything? – Božo Stojković Sep 12 '18 at 15:26
  • @BožoStojković I think the backend does not support it, report it as a bug – eyllanesc Sep 12 '18 at 15:35
  • I had the same problem in the past and I solved make a custom method https://github.com/All4Gis/QGISFMV/blob/master/code/player/QgsFmvPlayer.py#L608 – Fran Raga Sep 12 '18 at 17:37
  • @eyllanesc I opened up a [thread on Riverbank mailing list](https://www.riverbankcomputing.com/pipermail/pyqt/2018-September/040859.html) – Božo Stojković Sep 13 '18 at 08:51
  • @FranciscoRaga Do you mean the `rewindMedia` method? If yes, that's not what I am looking for. Please read [my comment on S. Nick's answer](https://stackoverflow.com/questions/52155722/qmediaplayer-negative-playbackrate-doesnt-rewind-video/52264919#comment91544583_52264919) – Božo Stojković Sep 13 '18 at 08:53

1 Answers1

3

QMediaPlayer.playbackRate property holds the playback rate of the current media. This value is a multiplier applied to the media's standard play rate.

Press the Key_A, Key_Z, Key_Y keys to see how it works.


If you want to rewind the video, you should use QMediaPlayer.position property, which holds the playback position of the current media. The value is the current playback position, expressed in milliseconds since the beginning of the media.

Press the Key_M, Key_P keys to see how it works.

import sys

from PyQt5.QtCore import Qt, QUrl, QEvent
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication

class VideoWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        videoWidget = QVideoWidget()
        self.setCentralWidget(videoWidget)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.setMedia(
            QMediaContent(QUrl.fromLocalFile(r"<some video file>.mp4"))
        )
        self.mediaPlayer.play()

        app.installEventFilter(self)

    def eventFilter(self, source, event):
        if event.type() == QEvent.KeyPress:
            key = event.key()

            # It Playback Rate !
            if key == Qt.Key_A:
                #self.mediaPlayer.setPlaybackRate(1.0)
                self.mediaPlayer.setPlaybackRate(1.5)
            elif key == Qt.Key_Z:
                self.mediaPlayer.setPlaybackRate(0.8)
            elif key == Qt.Key_Y:
                self.mediaPlayer.setPlaybackRate(1.0)                        

            # setPosition(int), argument is in milliseconds.
            elif key == Qt.Key_M:
                self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000)
            elif key == Qt.Key_P:
                self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000)                

        return super().eventFilter(source, event)


    def closeEvent(self, event):
        self.mediaPlayer.setMedia(QMediaContent())

if __name__ == '__main__':
    app = QApplication(sys.argv)

    player = VideoWindow()
    player.resize(640, 480)
    player.show()

    exitCode = app.exec_()
    sys.exit(exitCode)
Božo Stojković
  • 2,893
  • 1
  • 27
  • 52
S. Nick
  • 12,879
  • 8
  • 25
  • 33
  • Unfortunately, this is not what I wanted. I don't want to change position of the video, I want the video to _play_ at negative speed. Through some logic of mine, setting `playbackRate` to negative number would make the video **play in reverse**. But that just doesn't happen. If you can't understand me clearly, here is a [video](https://www.youtube.com/watch?v=UBnI-oH0YtI&t=49s) of what should happen to my videos. – Božo Stojković Sep 12 '18 at 15:11