【问题标题】:PyQt playing video repeat endless(using QMediaPlayer, QMediaPlaylist)PyQt 播放视频无限重复(使用 QMediaPlayer、QMediaPlaylist)
【发布时间】:2021-07-09 10:21:56
【问题描述】:

我创建了我的 VideoPlayer 类,它可以正常播放一次。

但是当我尝试多次重复播放视频时(无休止),它不起作用。我打电话给video_player.mediaPlayer.play() play(),但他们只打印了黑色。

我认为是QMediaPlaylist的问题,但是我找不到任何问题。

 class VideoPlayer(QWidget):
  def __init__(self, video_path, parent=None):
    super(VideoPlayer, self).__init__(parent)
    self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

    videoWidget = QVideoWidget()

    layout = QVBoxLayout()
    layout.addWidget(videoWidget)

    self.setLayout(layout)

    self.mediaPlayer.setVideoOutput(videoWidget)

    playlist = QMediaPlaylist()
    playlist.addMedia(QMediaContent(QUrl.fromLocalFile(video_path)))
    playlist.setCurrentIndex(1)
    playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
    self.mediaPlayer.setPlaylist(playlist)

只玩一次的代码是self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(video_path)))。效果很好。

【问题讨论】:

标签: python qt user-interface pyqt


【解决方案1】:

与许多其他 Qt 对象一样,如果它们没有父对象或持久引用,它们就会被删除。

您的问题是,__init__ 返回后,playlist 就会被垃圾回收,导致 QMediaPlayer 没有可播放的内容。

使播放列表对象成为实例的成员,或使用父级(例如,窗口)创建它:

    self.playlist = QMediaPlaylist()
    # or
    playlist = QMediaPlaylist(self)

【讨论】:

  • 这是一个非常严重但很难发现的问题。采用您的代码后,它完全可以正常工作。
  • @HansuKim 需要记住的重要一点是 PyQt 对象只是对其 C++ 对象的引用,因此,有时垃圾收集可能会导致不直观。例如,像QPushButton(self) 这样的简单行(没有创建对它的引用,甚至没有像button = QPushButton() 这样的局部变量)创建一个按钮,它是self 的子按钮(当前小部件实例,它充当parent):它显示为“嵌入”在小部件中,并且不会在该父小部件存在时立即被删除;这是因为使用父对象创建 QObjects 也会创建持久引用。
  • QMediaPlayer 也会发生同样的情况:如果你不让它成为self 的成员,那么即使尝试使用setMedia() 直接播放文件也不会起作用。相反,如果您将媒体播放器创建为 local,但 with 是父级 (mediaPlayer = QMediaPlayer(self, ...)),它会起作用。对于添加到布局的小部件,可以观察到类似的行为:即使它们没有获得持久引用,在现有小部件上设置的布局上使用 addWidget(...) 也不会删除它们,因为 addWidget() 会自动更改所有权给父母。
  • 不确定时,请查看文档:如果您使用的是someObject.setSomething(something),则有关setSomething 的文档会告诉您someObject 是否会获得该文件的所有权 something 与否(如果未指定,通常不会)。在这种特定情况下,setPlaylist 不会更改播放列表的所有权,并且由于 QMediaPlayer 也是一个异步对象,所以该播放列表将在 __init__ 返回后立即删除,从而“清空”QMediaPlayer 的内容:当控制权回到事件队列时,就没有什么可玩的了。
  • 你的建议对我很有帮助。尤其是你提到addWidget(),我可以发现我的代码是另一个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-08
  • 1970-01-01
  • 2017-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
相关资源
最近更新 更多