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
才能停止程序在关闭时挂起。
我的测试视频:
- 工作正常:
- 1080p 60fps vp9/opus webm
- 1080p 30fps vp9/opus webm
- 480p 30fps vp9/opus webm
- 仅播放音频(出现空白 window):
- 1080p 30fps H.264/aac mp4
- 480p 30fps H.264/aac mp4
- 1080p 23.98fps H.264/ac3 mp4
- 1080p 23.98fps H.264/ac3 mkv
- 1080p 23.98fps vp9/opus webm
- 720x404 23.98fps vp9/opus webm
我在 windows 上使用 qt5 并安装了适当的编解码器(K-Lite 编解码器包)来播放这些文件(它们可以在 windows 媒体播放器中正常播放)。
编辑:
我已经按照@ekhumoro 的建议连接到 mediaStatusChanged
、videoAvailableChanged
和 error
信号。只要我 运行 程序,我就会立即将视频设为 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
注册一个信号处理程序并调用 updateGeometry
和 adjustSize
.
最后,程序在退出时挂起的另一个问题是因为我没有在我的 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()
我正在根据 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
才能停止程序在关闭时挂起。
我的测试视频:
- 工作正常:
- 1080p 60fps vp9/opus webm
- 1080p 30fps vp9/opus webm
- 480p 30fps vp9/opus webm
- 仅播放音频(出现空白 window):
- 1080p 30fps H.264/aac mp4
- 480p 30fps H.264/aac mp4
- 1080p 23.98fps H.264/ac3 mp4
- 1080p 23.98fps H.264/ac3 mkv
- 1080p 23.98fps vp9/opus webm
- 720x404 23.98fps vp9/opus webm
我在 windows 上使用 qt5 并安装了适当的编解码器(K-Lite 编解码器包)来播放这些文件(它们可以在 windows 媒体播放器中正常播放)。
编辑:
我已经按照@ekhumoro 的建议连接到 mediaStatusChanged
、videoAvailableChanged
和 error
信号。只要我 运行 程序,我就会立即将视频设为 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
注册一个信号处理程序并调用 updateGeometry
和 adjustSize
.
最后,程序在退出时挂起的另一个问题是因为我没有在我的 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()