1

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 i.e.

 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

1 Answer 1

4

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:

Sign up to request clarification or add additional context in comments.

8 Comments

That was exactly it. Works perfectly. In my case I didn't explain it well enough for brevity's sake. I still needed to unpickle the data in order for it to work. Unpickling basically took the place of the 'with open(path, 'rb') as stream:' etc line of your code. Thanks again!!
So I encountered a bit of an issue with this method. It works fine on a windows machine but going to OSX I just get a black screen. No noticeable error. Is this some sort of mac-specific bug perhaps?
@huitlacoche. I only tried it Linux, and I cannot test it myself on OSX. It may be the media itself that is causing the problem, so I suggest you try a few different video formats. Have you tried loading the same media directly using a file url? I don't know how reliable Qt Multimedia is in general, as I've never really used it in a serious project. (PS: I just tried a few more files on Linux, and one or two didn't load successfully - not sure why).
@huitlacoche. PPS: I tried loading the problematic files directly using a file url, and they still didn't load - so it's not reading from a buffer that is causing the problem. And the same files load okay using mplayer, so there seems to be some internal Qt issue.
I'm not sure that it's the source. I can load the videos just fine from the file url. I'll keep playing with it. At least I know it can work. Thanks!
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.