Сигнал обновления видеокадра PyQt (функция триггера после каждого видеокадра) - PullRequest
0 голосов
/ 12 декабря 2018

Я создаю видеоплеер, и мне нужно нарисовать несколько полигонов поверх него.Я использую QGraphicsScene, чтобы создать это, и мне нужно обновлять полигоны на экране после каждого кадра.В настоящее время я использую QMediaPlayer в паре с QGraphicsVideoItem для создания этого.У меня проблема в том, что QMediaPlayer не имеет сигнала, который активируется в каждом кадре.У него есть positionChanged (), но, похоже, он срабатывает только раз в секунду.

Я пытался использовать QMovie, поскольку он отправляет обновления для каждого кадра, но ничего не отображал.Это код, который я использовал для реализации этого.

    video_view = QGraphicsView()#view to hold video
    video_item = QGraphicsVideoItem()#video item for scene
    video_scene = QGraphicsScene()#scene for Qgraphics view
    video_view.setScene(video_scene)

    label = QLabel()
    movie = QMovie(self.video_paths[index]) #contains file path
    label.setMovie(movie)
    video_scene.addWidget(label)
    self.vlayout_main_video.addWidget(video_view)

Используемый мной видеофайл - это файл .avi, его размер составляет 72 МБ.

Я был бы очень признателен, если бы кто-нибудь смогукажи мне правильное направление, как я могу это сделать.Я сейчас использую PyQt5.

Спасибо

1 Ответ

0 голосов
/ 12 декабря 2018

Существует 2 варианта:

  • positionChanged испускается каждую секунду, поскольку в этот период установлено свойство notifyInterval для QMediaPlayer.Таким образом, вы можете изменить это свойство, например, на 60 мс.

from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        scene = QtWidgets.QGraphicsScene(self)
        self.video_view = QtWidgets.QGraphicsView(scene)
        self.setCentralWidget(self.video_view)

        self.player = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
        self.video_item = QtMultimediaWidgets.QGraphicsVideoItem()
        self.player.setVideoOutput(self.video_item)
        scene.addItem(self.video_item)
        file = "/path/of/video"
        self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file)))
        self.player.positionChanged.connect(self.on_positionChanged)
        self.player.setNotifyInterval(60)
        self.player.play()

    @QtCore.pyqtSlot('qint64')
    def on_positionChanged(self, p):
        print(p, QtCore.QTime.currentTime().toString("hh:mm:ss.zzz"))

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())
  • Использовать сигнал VideoFrameProbed от QVideoProbe:

from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia, QtMultimediaWidgets

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        scene = QtWidgets.QGraphicsScene(self)
        self.video_view = QtWidgets.QGraphicsView(scene)
        self.setCentralWidget(self.video_view)

        self.player = QtMultimedia.QMediaPlayer(self, QtMultimedia.QMediaPlayer.VideoSurface)
        self.video_item = QtMultimediaWidgets.QGraphicsVideoItem()
        self.player.setVideoOutput(self.video_item)
        scene.addItem(self.video_item)
        file = "/path/of/video"
        self.player.setMedia(QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(file)))
        self.player.play()

        probe = QtMultimedia.QVideoProbe(self)
        probe.videoFrameProbed.connect(self.on_videoFrameProbed)
        probe.setSource(self.player)

    @QtCore.pyqtSlot()
    def on_videoFrameProbed(self):
        print(QtCore.QTime.currentTime().toString("hh:mm:ss.zzz"))

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.resize(640, 480)
    w.show()
    sys.exit(app.exec_())
...