PyQt5 - 无法从流中播放视频
Posted
技术标签:
【中文标题】PyQt5 - 无法从流中播放视频【英文标题】:PyQt5 -- Unable to playback video from stream 【发布时间】:2016-12-14 19:00:13 【问题描述】:我看到过很多类似这样的其他问题,但似乎其中许多问题没有解决或与我的情况无关,所以就这样吧。
我正在尝试在 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 条目,而 'binary video' 是腌制视频条目的字典键。 这还假设在我的用户界面中正确创建和初始化了 mediaPlayer,即
mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
videoPlayer = QVideoWidget()
mediaPlayer.setVideoOutput(videoPlayer)
我还尝试使用“QMediaPlayer.StreamPlayback”标志初始化 mediaPlayer,但同样没有。
当我在 windows 上尝试它时它崩溃了,当我在 mac 上尝试它时它只是一个黑屏。没有错误日志或任何东西(无论如何都没有启发性)。
有没有人成功地为他们工作,如果有,你是怎么做到的?
谢谢! -马克
【问题讨论】:
【参考方案1】:您需要保留对缓冲区和基础数据的引用,否则它们将在播放器启动后被垃圾回收。
请注意,在您的示例中,腌制视频数据完全没有意义,因为它只是字节,因此没有什么值得序列化的。 Pickle 仅对结构化的 Python 对象有用,例如 list
或 dict
。
下面是一个带有完整视频播放器的演示脚本。它最初从文件系统中获取视频资源,但如果它来自数据库,它的工作方式也一样:
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 上不支持流式传输:
见:Qt Multimedia Backends【讨论】:
就是这样。完美运行。就我而言,为了简洁起见,我没有很好地解释它。我仍然需要解开数据才能使其正常工作。 Unpickling 基本上取代了代码中的 'with open(path, 'rb') as stream:' 等行。再次感谢!! 所以我遇到了这个方法的一些问题。它在 Windows 机器上运行良好,但转到 OSX 我只是得到一个黑屏。没有明显的错误。这可能是某种特定于 mac 的错误吗? @huitlacoche。我只在 Linux 上试过,不能在 OSX 上自己测试。可能是媒体本身导致了问题,所以我建议您尝试几种不同的视频格式。您是否尝试过使用文件 url 直接加载相同的媒体?我不知道 Qt Multimedia 一般有多可靠,因为我从未在严肃的项目中真正使用过它。 (PS:我只是在Linux上多试了几个文件,一两个没有加载成功——不知道为什么)。 @huitlacoche。 PPS:我尝试使用文件 url 直接加载有问题的文件,但它们仍然没有加载 - 所以它没有从导致问题的缓冲区中读取。并且使用 mplayer 可以正常加载相同的文件,因此似乎存在一些内部 Qt 问题。 我不确定它的来源。我可以从文件 url 加载视频。我会继续玩它的。至少我知道它可以工作。谢谢!以上是关于PyQt5 - 无法从流中播放视频的主要内容,如果未能解决你的问题,请参考以下文章
基于pyqt5的QMediaPlayer实现视频播放器(拨动进度条,音量,更换播放模式,加入多个播放文件)