Почему QMediaPlayer неправильно устанавливает положение в MacOS? - PullRequest
0 голосов
/ 04 марта 2019

В моем текущем приложении я пытаюсь синхронизировать 3 QMediaPlayer, следя за тем, чтобы каждый игрок всегда находился в одном и том же состоянии и чтобы каждое изменение, внесенное в одного из игроков, реплицировалось на всех игроков.

Я использую QMediaPlayer.setPosition () для этого, но, похоже, он не дает последовательных или точных результатов.

Минимальный рабочий пример, демонстрирующий эту проблему, приведен ниже.

import os
import sys
from pathlib import Path

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


class Player(QMainWindow):
    def __init__(self):
        super(Player, self).__init__()

        # video player
        self.__player = QMediaPlayer()
        self.__player.setMuted(True)

        # player widget
        self.__playerWidget = QVideoWidget()
        self.__player.setVideoOutput(self.__playerWidget)

        # controls
        self.__seekBackwardBtn = QPushButton()
        self.__seekBackwardBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaSeekBackward))
        self.__seekBackwardBtn.clicked.connect(self.__onSeekBackwardBtnClicked)

        self.__playBtn = QPushButton()
        self.__playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.__playBtn.clicked.connect(self.__onPlayBtnClicked)

        self.__stopBtn = QPushButton()
        self.__stopBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.__stopBtn.clicked.connect(self.__onStopBtnClicked)

        self.__seekForwardBtn = QPushButton()
        self.__seekForwardBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaSeekForward))
        self.__seekForwardBtn.clicked.connect(self.__onSeekForwardBtnClicked)

        self.__buttons = QHBoxLayout()
        self.__buttons.addWidget(self.__seekBackwardBtn)
        self.__buttons.addWidget(self.__playBtn)
        self.__buttons.addWidget(self.__stopBtn)
        self.__buttons.addWidget(self.__seekForwardBtn)

        # layout
        self.__layout = QVBoxLayout()
        self.__layout.addWidget(self.__playerWidget)
        self.__layout.addLayout(self.__buttons)

        self.__centralWidget = QWidget()
        self.__centralWidget.setLayout(self.__layout)
        self.setCentralWidget(self.__centralWidget)
        self.resize(800, 600)
        self.show()

    def __onPlayBtnClicked(self):
        state = self.__player.state()
        if state == QMediaPlayer.PlayingState:
            self.__player.pause()
            self.__playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        else:
            self.__player.play()
            self.__playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPause))

    def __onStopBtnClicked(self):
        self.__player.stop()
        self.__playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

    def __onSeekForwardBtnClicked(self):
        currentPosition = self.__player.position()
        newPosition = currentPosition + 1500
        self.__setPlayerPosition(newPosition)

    def __onSeekBackwardBtnClicked(self):
        currentPosition = self.__player.position()
        newPosition = max(0, currentPosition - 1500)
        self.__setPlayerPosition(newPosition)

    def __setPlayerPosition(self, position):
        print('Current player position: {}'.format(self.__player.position()))
        print('Position to set: {}'.format(position))
        self.__player.setPosition(position)
        print('New player position: {}\n'.format(self.__player.position()))

    def setMedia(self, path):
        content = QMediaContent(QUrl.fromLocalFile(path))
        self.__player.setMedia(content)


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

    currentDirectory = os.path.abspath(os.path.dirname(__file__))
    pathToMedia = str(Path(os.path.join(currentDirectory, './media.mp4')).resolve())
    player.setMedia(pathToMedia)

    sys.exit(app.exec_())

Вниманиедля метода __setPlayerPosition, приведенного выше, вывод, полученный, например, при использовании кнопки Seek Forward - добавление 1500 мс к текущей позиции игрока, выглядит следующим образом:

Current player position: 0
Position to set: 1500
New player position: 0

Current player position: 1766
Position to set: 3266
New player position: 1766

Current player position: 3433
Position to set: 4933
New player position: 3433

Current player position: 5166
Position to set: 6666
New player position: 5166

Я не уверен, включен ли QMediaPlayerMacOS выполняет обновление позиций в фоновом режиме (что объясняет неточность линии «Позиция нового игрока», но эти позиции игрока по-прежнему не соответствуют предоставленным.

Одна интересная вещь заключается в том, что эти цифры одинаковыкаждый раз они кажутся зависимыми от типа предоставленного медиа-файла, но я неen в состоянии точно понять, почему.

Протестировал код на Ubuntu 16.04.5 с правильными результатами:

Current player position: 0
Position to set: 1500
New player position: 1500

Current player position: 1500
Position to set: 3000
New player position: 3000

etc.

Системная информация:

  • MacOS High Sierra 10.13.6
  • Python 3.6.6
  • PyQt5 == 5.12.(также протестировано с 5.9)
  • Файл, используемый в примере здесь
...