Mari
Mari

Reputation: 25

How to create a video player with 2 windows with the same video?

I need to do a video player in PyQt. What is special at this video player is that I need 2 windows with the same video one in my interface and another in another monitor and both should be controlled from interface. I reused to do one separate widow with the video(that where the bird is), but I can't handle to do another one in that white widget. This is the code:

    self.player = QMediaPlayer()
    self.player.play()

    # Setup the playlist.
    self.playlist = QMediaPlaylist()
    self.player.setPlaylist(self.playlist)
    # # Add viewer for video playback, separate floating window.
    self.viewer = ViewerWindow(self)
    self.viewer.setWindowFlags(self.viewer.windowFlags() | Qt.WindowStaysOnTopHint)
    self.viewer.setMinimumSize(QSize(480, 360))
    self.viewer.setWindowTitle("VR Therapy")

    self.videoWidget = QVideoWidget(self)
    self.viewer.setCentralWidget(self.videoWidget)
    self.player.setVideoOutput(self.videoWidget)

    # Connect control buttons/slides for media player.
    self.playButton_2.pressed.connect(self.player.play)
    self.pauseButton_2.pressed.connect(self.player.pause)
    self.stopButton_2.clicked.connect(self.player.stop)
    self.volumeSlider_2.valueChanged.connect(self.player.setVolume)
    self.viewButton_2.toggled.connect(self.toggle_viewer)
    self.viewer.state.connect(self.viewButton_2.setChecked)


    self.previousButton_2.pressed.connect(self.playlist.previous)
    self.nextButton_2.pressed.connect(self.playlist.next)

    self.model = PlaylistModel(self.playlist)
    self.playlistView_2.setModel(self.model)
    self.playlist.currentIndexChanged.connect(self.playlist_position_changed)
    selection_model = self.playlistView_2.selectionModel()
    selection_model.selectionChanged.connect(self.playlist_selection_changed)


    self.player.durationChanged.connect(self.update_duration)
    self.player.positionChanged.connect(self.update_position)
    self.timeSlider_2.valueChanged.connect(self.player.setPosition)

videoplayer

Upvotes: 2

Views: 756

Answers (1)

eyllanesc
eyllanesc

Reputation: 244252

The QMediaPlayer is the controller of the media source, that is, it controls when it is played, paused, etc. and the QVideoWidget is one of the many viewers of the frames that the QMediaPlayer provides that is internally displayed using the QAbstractVideoSurface. So there should be no problems if a QMediaPlayer provides the frames to N outputs, for this you must use the setVideoOutput() method:

void QMediaPlayer::setVideoOutput(const QVector<QAbstractVideoSurface *> &surfaces)
Sets multiple video surfaces as the video output of a media player. This allows the media player to render video frames on different surfaces.

All video surfaces must support at least one shared QVideoFrame::PixelFormat.

If a video output has already been set on the media player the new surfaces will replace it.

This function was introduced in Qt 5.15.

from functools import cached_property
import sys

from PyQt5 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setCentralWidget(self.video_widget)

        self.viewer.show()

        self.player.setVideoOutput(
            [self.video_widget.videoSurface(), self.viewer.videoSurface()]
        )
        self.player.setPlaylist(self.playlist)

        self.playlist.addMedia(
            QtMultimedia.QMediaContent(
                QtCore.QUrl("http://techslides.com/demos/sample-videos/small.mp4")
            )
        )
        self.player.play()

    @cached_property
    def player(self):
        return QtMultimedia.QMediaPlayer()

    @cached_property
    def video_widget(self):
        return QtMultimediaWidgets.QVideoWidget()

    @cached_property
    def viewer(self):
        view = QtMultimediaWidgets.QVideoWidget()
        view.setWindowFlags(view.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
        view.setMinimumSize(480, 360)
        view.setWindowTitle("VR Therapy")
        return view

    @cached_property
    def playlist(self):
        return QtMultimedia.QMediaPlaylist()


def main():
    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    w.resize(640, 480)
    w.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

Upvotes: 1

Related Questions