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