简体   繁体   中英

PyQt5 — Unable to playback video from stream

I've seen a number of other questions like this floating around but it seems many of them are unresolved or unrelated to my situation, so here goes.

I'm attempting to play back a video stored as serialized data (through pickle) on a mongodb collection.

Here's the code:

    binary_file = my_database_entry['binary video']
    unpickle = pickle.dumps(binary_file)

    outByteArray = QByteArray(unpickle)
    mediaStream = QBuffer()
    mediaStream.setBuffer(outByteArray)
    mediaStream.open(QIODevice.ReadWrite)

    mediaPlayer.setMedia(QMediaContent(), mediaStream)
    mediaPlayer.play()

where 'my_database_entry' is the mongoDB entry and 'binary video' is the dictionary key for the pickled video entry. This also assumes that mediaPlayer is properly created and initialized within my user interface ie

    mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
    videoPlayer = QVideoWidget()
    mediaPlayer.setVideoOutput(videoPlayer)

I also tried initializing mediaPlayer with a 'QMediaPlayer.StreamPlayback' flag but again, nothing.

It crashes when I try it on windows and it's just a black screen when I try it on mac. No error logs or anything (nothing enlightening at any rate).

Has anyone gotten this to successfully work for them and if so, how did you do it?

Thanks! -Mark

You need to keep a reference to both the buffer and the underlying data, otherwise they will just be garbage-collected after the player starts.

And note that in your example, it is utterly pointless pickling the video data, as it is just bytes and so there's nothing worth serializing. Pickle is only useful for structured python objects, such as a list or dict .

Below is a demo script with a complete video player. It initally gets the video resource from the file-system, but it would work just the same if it came from a database:

from PyQt5 import QtCore, QtWidgets
from PyQt5 import QtMultimedia, QtMultimediaWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.player = QtMultimedia.QMediaPlayer(self)
        self.viewer = QtMultimediaWidgets.QVideoWidget(self)
        self.player.setVideoOutput(self.viewer)
        self.player.stateChanged.connect(self.handleStateChanged)
        self.button1 = QtWidgets.QPushButton('Play', self)
        self.button2 = QtWidgets.QPushButton('Stop', self)
        self.button1.clicked.connect(self.handleButton)
        self.button2.clicked.connect(self.player.stop)
        self.button2.setEnabled(False)
        layout = QtWidgets.QGridLayout(self)
        layout.addWidget(self.viewer, 0, 0, 1, 2)
        layout.addWidget(self.button1, 1, 0)
        layout.addWidget(self.button2, 1, 1)
        self._buffer = QtCore.QBuffer(self)
        self._data = None

    def handleButton(self):
        path = QtWidgets.QFileDialog.getOpenFileName(self)[0]
        if path:
            self.button1.setEnabled(False)
            self.button2.setEnabled(True)
            with open(path, 'rb') as stream:
                self._data = stream.read()
                self._buffer.setData(self._data)
                self._buffer.open(QtCore.QIODevice.ReadOnly)
                self.player.setMedia(
                    QtMultimedia.QMediaContent(), self._buffer)
                self.player.play()

    def handleStateChanged(self, state):
        if state == QtMultimedia.QMediaPlayer.StoppedState:
            self._buffer.close()
            self._data = None
            self.button1.setEnabled(True)
            self.button2.setEnabled(False)

if __name__ == '__main__':

    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(500, 50, 640, 480)
    window.show()
    sys.exit(app.exec_())

UPDATE :

The solution above will only work on Windows and Linux, because there is currently no support for streaming on OSX:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM