TransWikia.com

Pyqt5 QMediaPlayer.position после проигрывания не соответствует реальной позиции в видео

Stack Overflow на русском Asked by Luchunpen on December 14, 2021

Я хочу сделать покадровый переход по видеофайлу, но проблема в том, что после проигрывания, достаточно пары секунд, реальная позиция видео не соответствует значению из QMediaPlayer.position(), а именно отставание на 1-2 кадра. Это легко наблюдается если проиграть видео с каким нибудь счетчиком или быстрыми действиями. При этом если продолжить проигрывать видео сняв его с паузы без перехода, плеер ожидаемо продолжает с места остановки.

Для теста выкладываю рабочий скрипт, который по нажатии кнопки "Seek to current position" позволяет перейти на текущую позицию полученную из QMediaPlay.position().

Буду благодарен любым ответам и возможности решения этой проблемы.

import sys

from PyQt5.QtCore import QUrl, QSize
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QVBoxLayout, QWidget


class VideoWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMinimumSize(QSize(500, 500))
        self.setGeometry(0, 0, 500, 500)

        self.mainLayout = QVBoxLayout()
        self.centralWidget = QWidget()
        self.centralWidget.setLayout(self.mainLayout)
        self.setCentralWidget(self.centralWidget)

        video_widget = QVideoWidget()
        button = QPushButton('Play', self)
        button.clicked.connect(self.playMedia)

        button2 = QPushButton("Seek to current position", self)
        button2.clicked.connect(self.seekToCurrentPosition)

        self.mainLayout.addWidget(video_widget)
        self.mainLayout.addWidget(button)
        self.mainLayout.addWidget(button2)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVideoOutput(video_widget)
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile("1.mp4")))

    def playMedia(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
            print("current_position: ", self.mediaPlayer.position())
        else:
            self.mediaPlayer.play()

    def seekToCurrentPosition(self):
        if self.mediaPlayer.state() != QMediaPlayer.PausedState:
            return

        current_pos = self.mediaPlayer.position()
        self.mediaPlayer.setPosition(current_pos)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    player = VideoWindow()
    player.show()

    exitCode = app.exec_()
    sys.exit(exitCode)

One Answer

С трудом понял о чем вы говорите и то после кучи принтов и установления сигнала

self.mediaPlayer.positionChanged.connect(self.positionChanged)

да self.mediaPlayer.position() отличается от self._position. используйте то что вам надо.

import sys

from PyQt5.QtCore import QUrl, QSize
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import QMainWindow, QApplication, QPushButton, QVBoxLayout, QWidget


class VideoWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setMinimumSize(QSize(500, 500))
        self.resize(500, 500)
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)

        self.button = QPushButton('Play', self)
        self.button.clicked.connect(self.playMedia)
        button2 = QPushButton("Искать в текущей позиции", self)
        button2.clicked.connect(self.seekToCurrentPosition)
        
        video_widget = QVideoWidget(self)                                 # self
     
        self.mediaPlayer = QMediaPlayer(self, QMediaPlayer.VideoSurface)  # self
        self.mediaPlayer.setVideoOutput(video_widget)
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile("Samonastrojka.avi")))
        
        self._position = 0                                                                 # +++ !!!
        self.mediaPlayer.positionChanged.connect(self.positionChanged)                     # +++ !!!

        self.mainLayout = QVBoxLayout(self.centralWidget)
        self.mainLayout.addWidget(video_widget)
        self.mainLayout.addWidget(self.button)
        self.mainLayout.addWidget(button2)

    def playMedia(self):
        print(f'nplayMedia state 1: {self.mediaPlayer.state()} - '
              f'{self.mediaPlayer.position()} <--> {self._position}')
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
            self.button.setText('Play')
            print(f"current_position:      {self.mediaPlayer.position()} <--> {self._position}")
        else:
            self.mediaPlayer.play()
            self.button.setText('Pause')
        print(f'playMedia state 2: {self.mediaPlayer.state()} - {self.mediaPlayer.position()}'
              f' <--> {self._position}')

    def seekToCurrentPosition(self):
        print(f'nseekToCurrentPosition state:      {self.mediaPlayer.state()}- '
              f'{self.mediaPlayer.position()}<--> {self._position}')
        if self.mediaPlayer.state() != QMediaPlayer.PausedState:
            return
        
        current_pos = self.mediaPlayer.position()
        print(f'seekToCurrentPosition current_pos 1: {current_pos}<--> {self._position}')
        self.mediaPlayer.setPosition(current_pos)
        print(f'seekToCurrentPosition current_pos 2: {self.mediaPlayer.position()}<--> {self._position}')

# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv        
    def positionChanged(self, position):
        self._position = position                                          # <<<-------<
#        print(self._position)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


if __name__ == '__main__':
    app = QApplication(sys.argv)
    player = VideoWindow()
    player.show()
    exitCode = app.exec_()
    sys.exit(exitCode)

введите сюда описание изображения

Answered by S. Nick on December 14, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP