PyQt5 - 无法从流中播放视频

时间:2016-12-14 19:00:13

标签: python qt pyqt pyqt5

我已经看到其他一些问题如此流传,但似乎很多问题都没有得到解决或与我的情况无关,所以就这样了。

我试图在mongodb集合上播放存储为序列化数据(通过pickle)的视频。

以下是代码:

    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()

其中' my_database_entry'是mongoDB条目和'二进制视频'是pickle视频条目的字典键。 这也假设mediaPlayer在我的用户界面中正确创建和初始化,即

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

我还尝试使用' QMediaPlayer.StreamPlayback'来初始化mediaPlayer。旗帜但又一次没有。

当我在Windows上试用它时会崩溃,当我在Mac上试用它时,它只是一个黑屏。没有错误记录或任何事情(无论如何都没有任何启发)。

有没有人能够成功地为他们工作,如果是这样,你是怎么做到的?

谢谢! -Mark

1 个答案:

答案 0 :(得分:3)

您需要保留对缓冲区和基础数据的引用,否则它们将在播放器启动后进行垃圾收集。

请注意,在你的例子中,视频数据是完全没有意义的,因为它只是字节,所以没有什么值得序列化的。 Pickle仅对结构化python对象有用,例如listdict

下面是一个带有完整视频播放器的演示脚本。它最初从文件系统获取视频资源,但如果它来自数据库,它将会起作用:

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_())

<强>更新

上述解决方案仅适用于Windows和Linux,因为目前OSX上不支持流式传输: