PyQt5 -- 无法从流中播放视频 [英] PyQt5 -- Unable to playback video from stream

查看:69
本文介绍了PyQt5 -- 无法从流中播放视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到许多其他类似的问题,但似乎其中许多问题都没有解决或与我的情况无关,所以这里是.

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.

我正在尝试在 mongodb 集合中播放存储为序列化数据(通过 pickle)的视频.

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

代码如下:

    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 条目,'binary video' 是腌制视频条目的字典键.这还假设在我的用户界面中正确创建和初始化了 mediaPlayer,即

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)

我还尝试使用QMediaPlayer.StreamPlayback"标志初始化 mediaPlayer,但同样没有.

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

当我在 Windows 上尝试时它崩溃了,当我在 mac 上尝试时它只是一个黑屏.没有错误日志或任何东西(无论如何都没有启发).

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?

谢谢!-马克

推荐答案

你需要同时保留对缓冲区和底层数据的引用,否则它们会在播放器启动后被垃圾收集.

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.

请注意,在您的示例中,对视频数据进行酸洗是完全没有意义的,因为它只是字节,因此没有什么值得序列化的.Pickle 仅对结构化的 Python 对象有用,例如 listdict.

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

<小时>

更新:

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

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

这篇关于PyQt5 -- 无法从流中播放视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆