如何创建具有 2 windows 相同视频的视频播放器?

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

我需要用 PyQt 做一个视频播放器。这个视频播放器的特别之处在于我需要 2 windows 具有相同的视频,一个在我的界面中,另一个在另一台显示器中,两者都应该从界面控制。我曾经用视频(鸟所在的地方)做一个单独的寡妇,但我无法处理那个白色小部件中的另一个。 这是代码:

    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)

视频播放器

QMediaPlayer 是媒体源的控制器,也就是说,它控制播放、暂停等时间,而 QVideoWidget 是 QMediaPlayer 提供的内部显示的帧的众多查看器之一QAbstractVideoSurface。因此,如果 QMediaPlayer 将帧提供给 N 个输出,应该没有问题,为此您必须使用 setVideoOutput() 方法:

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()