QMediaPlayer 仅显示某些视频的音频

QMediaPlayer displays audio only for certain videos

我正在根据 docs 中的示例使用 QMediaPlayer。

这是我的代码:

from PySide2 import QtWidgets
from PySide2 import QtCore
from PySide2.QtMultimedia import QMediaPlayer
from PySide2.QtMultimediaWidgets import QVideoWidget


class App(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer()
        self.video = QVideoWidget(self)
        self.player.setMedia(QtCore.QUrl.fromLocalFile("D:/path/to/file.webm"))
        self.player.setVideoOutput(self.video)
        self.video.show()
        self.player.play()

    def closeEvent(self, event):
        self.player.stop()
        event.accept()


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    window = App()
    window.show()
    app.exec_()

必须覆盖 closeEvent 才能停止程序在关闭时挂起。

我的测试视频:

我在 windows 上使用 qt5 并安装了适当的编解码器(K-Lite 编解码器包)来播放这些文件(它们可以在 windows 媒体播放器中正常播放)。

编辑:
我已经按照@ekhumoro 的建议连接到 mediaStatusChangedvideoAvailableChangederror 信号。只要我 运行 程序,我就会立即将视频设为 True 并将 mediaStatus 设为 BufferedMedia,无论它是否实际显示视频。 error 信号处理程序永远不会被触发。

在这些进一步的测试中,"worked fine" 部分的视频偶尔无法显示视频,或者更奇怪的是,显示正常但最小 window 大小:

调整 window 的大小不会增加视频的大小。到目前为止,我的原始测试的 "played audio only" 部分中没有视频显示过视频。

编辑 2:

重新启动(并更新了图形驱动程序)后,第一个 运行 最初根本不显示视频的视频显示在奇怪的小 window 中。随后的 运行 秒(我已经完成了 10 次左右)已恢复为无视频。类似地,最初运行良好的视频最初 运行 没有视频,但现在一直很小。另一个原本有效的视频仍在正常播放。

问题与@ekhumoro 建议的大小有关。

当我继承的 QWidget 试图计算出它的大小时,它询问 QVideoWidget 这是它唯一的 child 大小。有时 QVideoWidget 加载了它的视频,因此提供了正确的大小,但其他时候它没有加载,因此给出 (-1, -1)sizeHint。因为 QVideoWidget 不在布局中,所以它无法自行调整大小并且卡得太小了。

此外,window 本身不会在布局创建后自动调整大小(只能由用户调整,或通过 adjustSize 明确调整),因此 window 保持其原始大小即使在布局中使用 QVideoWidget。解决方案是为 mediaStatusChanged 注册一个信号处理程序并调用 updateGeometryadjustSize.

最后,程序在退出时挂起的另一个问题是因为我没有在我的 window 上添加 QMediaPlayer

我修改的class:

class App(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.player = QMediaPlayer(self)
        self.video = QVideoWidget(self)
        self.player.setMedia(QtCore.QUrl.fromLocalFile("D:/path/to/video.webm"))
        self.player.setVideoOutput(self.video)
        self.player.mediaStatusChanged.connect(self.video_available_changed)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.video)
        self.player.play()

    def video_available_changed(self, available):
        if available:
            self.video.updateGeometry()
            self.video.adjustSize()
            self.adjustSize()