I want to develop a python application to read an MPEG-TS file with 4 video stream and 2 audio stream. I use Qt for the interface and vlc.py for teh libvlc
The application seems like a mosaic (with 4 Qframe to draw the streams).
For now, I declare 4 instances each with 1 player and there own settings (to extract each stream separately).
I give the code I use
Code: Select all
import sys
import os.path
import vlc
import time
from PyQt4 import QtGui, QtCore
class Player(QtGui.QMainWindow):
"""A Media Player using VLC and Qt for EVN video"""
def __init__(self, master=None):
QtGui.QMainWindow.__init__(self, master)
self.setWindowTitle("Media Player for EVN video")
# creating a basic vlc instance
self.instance1 = vlc.Instance('--demux=ts --no-audio --sout-all --sout=#duplicate{dst=display,select="es=257"]')#,dst=display,select="es=17"}')
self.instance2 = vlc.Instance('--demux=ts --no-audio --sout-all --sout=#duplicate{dst=display,select="es=258"')
self.instance3 = vlc.Instance('--demux=ts --no-audio --sout-all --sout=#duplicate{dst=display,select="es=822"}')
self.instance4 = vlc.Instance('--demux=ts --no-audio --sout-all --sout=#duplicate{dst=display,select="es=1031"}')
# creating an empty vlc media player
self.mediaplayer1 = self.instance1.media_player_new()
self.mediaplayer2 = self.instance2.media_player_new()
self.mediaplayer3 = self.instance3.media_player_new()
self.mediaplayer4 = self.instance4.media_player_new()
self.createUI()
self.isPaused = False
def createUI(self):
"""Set up the user interface, signals & slots"""
self.widget = QtGui.QWidget(self)
self.setCentralWidget(self.widget)
# In this widget, the video will be drawn
if sys.platform == "darwin": # for MacOS
self.videoframe1 = QtGui.QMacCocoaViewContainer(0)
self.videoframe2 = QtGui.QMacCocoaViewContainer(0)
self.videoframe3 = QtGui.QMacCocoaViewContainer(0)
self.videoframe4 = QtGui.QMacCocoaViewContainer(0)
else:
self.videoframe1 = QtGui.QFrame()
self.videoframe2 = QtGui.QFrame()
self.videoframe3 = QtGui.QFrame()
self.videoframe4 = QtGui.QFrame()
self.palette = self.videoframe1.palette()
self.palette.setColor (QtGui.QPalette.Window,QtGui.QColor(0,0,0))
self.videoframe1.setPalette(self.palette)
self.videoframe1.setAutoFillBackground(True)
self.videoframe2.setPalette(self.palette)
self.videoframe2.setAutoFillBackground(True)
self.videoframe3.setPalette(self.palette)
self.videoframe3.setAutoFillBackground(True)
self.videoframe4.setPalette(self.palette)
self.videoframe4.setAutoFillBackground(True)
self.positionslider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
self.positionslider.setToolTip("Position")
self.positionslider.setMaximum(1000)
self.connect(self.positionslider,QtCore.SIGNAL("sliderMoved(int)"), self.setPosition)
self.hbuttonbox = QtGui.QHBoxLayout()
self.playbutton = QtGui.QPushButton("Play")
self.hbuttonbox.addWidget(self.playbutton)
self.connect(self.playbutton, QtCore.SIGNAL("clicked()"),self.PlayPause)
self.stopbutton = QtGui.QPushButton("Stop")
self.hbuttonbox.addWidget(self.stopbutton)
self.connect(self.stopbutton, QtCore.SIGNAL("clicked()"),self.Stop)
self.gettimebutton = QtGui.QPushButton("Get Time")
self.hbuttonbox.addWidget(self.gettimebutton)
self.connect(self.gettimebutton, QtCore.SIGNAL("clicked()"),self.getTime)
self.hbuttonbox.addStretch(1)
self.volumeslider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
self.volumeslider.setMaximum(100)
self.volumeslider.setValue(self.mediaplayer1.audio_get_volume())
self.volumeslider.setToolTip("Volume")
self.hbuttonbox.addWidget(self.volumeslider)
self.connect(self.volumeslider,QtCore.SIGNAL("valueChanged(int)"),self.setVolume)
self.splitter1 = QtGui.QSplitter(QtCore.Qt.Horizontal)
self.splitter1.addWidget(self.videoframe1)
self.splitter1.addWidget(self.videoframe2)
self.splitter1.setSizes([100,100])
self.splitter2 = QtGui.QSplitter(QtCore.Qt.Horizontal)
self.splitter2.addWidget(self.videoframe3)
self.splitter2.addWidget(self.videoframe4)
self.splitter2.setSizes([100,100])
self.vboxlayout = QtGui.QVBoxLayout()
self.vboxlayout.addWidget(self.splitter1)
self.vboxlayout.addWidget(self.splitter2)
self.vboxlayout.addWidget(self.positionslider)
self.vboxlayout.addLayout(self.hbuttonbox)
self.widget.setLayout(self.vboxlayout)
open = QtGui.QAction("&Open", self)
self.connect(open, QtCore.SIGNAL("triggered()"), self.OpenFile)
exit = QtGui.QAction("&Exit", self)
self.connect(exit, QtCore.SIGNAL("triggered()"), sys.exit)
menubar = self.menuBar()
filemenu = menubar.addMenu("&File")
filemenu.addAction(open)
filemenu.addSeparator()
filemenu.addAction(exit)
self.timer = QtCore.QTimer(self)
self.timer.setInterval(200)
self.connect(self.timer, QtCore.SIGNAL("timeout()"),self.updateUI)
def PlayPause(self):
"""Toggle play/pause status"""
if self.mediaplayer1.is_playing():
self.mediaplayer1.pause()
self.mediaplayer2.pause()
self.mediaplayer3.pause()
self.mediaplayer4.pause()
self.playbutton.setText("Play")
self.isPaused = True
else:
if self.mediaplayer1.play() == -1:
self.OpenFile()
return
self.mediaplayer1.play()
self.mediaplayer2.play()
self.mediaplayer3.play()
self.mediaplayer4.play()
self.playbutton.setText("Pause")
self.timer.start()
self.isPaused = False
def Stop(self):
"""Stop player"""
self.mediaplayer1.stop()
self.mediaplayer2.stop()
self.mediaplayer3.stop()
self.mediaplayer4.stop()
self.playbutton.setText("Play")
def OpenFile(self, filename=None):
"""Open a media file in a MediaPlayer"""
if filename is None:
filename = QtGui.QFileDialog.getOpenFileName(self, "Open File", os.path.expanduser('~'))
if not filename:
return
# create the media
if sys.version < '3':
filename = unicode(filename)
self.media1 = self.instance1.media_new(filename)
self.media2 = self.instance2.media_new(filename)
self.media3 = self.instance3.media_new(filename)
self.media4 = self.instance4.media_new(filename)
# put the media in the media player
self.mediaplayer1.set_media(self.media1)
self.mediaplayer2.set_media(self.media2)
self.mediaplayer3.set_media(self.media3)
self.mediaplayer4.set_media(self.media4)
# parse the metadata of the file
self.media1.parse()
# set the title of the track as window title
self.setWindowTitle(self.media1.get_meta(0))
# the media player has to be 'connected' to the QFrame
# (otherwise a video would be displayed in it's own window)
# this is platform specific!
# you have to give the id of the QFrame (or similar object) to
# vlc, different platforms have different functions for this
if sys.platform.startswith('linux'): # for Linux using the X Server
self.mediaplayer1.set_xwindow(self.videoframe1.winId())
self.mediaplayer2.set_xwindow(self.videoframe2.winId())
self.mediaplayer3.set_xwindow(self.videoframe3.winId())
self.mediaplayer4.set_xwindow(self.videoframe4.winId())
elif sys.platform == "win32": # for Windows
self.mediaplayer1.set_hwnd(self.videoframe1.winId())
self.mediaplayer2.set_hwnd(self.videoframe2.winId())
self.mediaplayer3.set_hwnd(self.videoframe3.winId())
self.mediaplayer4.set_hwnd(self.videoframe4.winId())
elif sys.platform == "darwin": # for MacOS
self.mediaplayer1.set_nsobject(self.videoframe1.winId())
self.mediaplayer2.set_nsobject(self.videoframe2.winId())
self.mediaplayer3.set_nsobject(self.videoframe3.winId())
self.mediaplayer4.set_nsobject(self.videoframe4.winId())
self.PlayPause()
def setVolume(self, Volume):
"""Set the volume"""
self.mediaplayer1.audio_set_volume(Volume)
def setPosition(self, position):
"""Set the position"""
# setting the position to where the slider was dragged
# the vlc MediaPlayer needs a float value between 0 and 1, Qt
# uses integer variables, so you need a factor; the higher the
# factor, the more precise are the results
# (1000 should be enough)
self.mediaplayer1.set_position(position / 1000.0)
self.mediaplayer2.set_position(position / 1000.0)
self.mediaplayer3.set_position(position / 1000.0)
self.mediaplayer4.set_position(position / 1000.0)
def getPosition(self):
"""Get the position"""
return self.mediaplayer1.get_position()
def getTime(self):
"""Get current time in ms"""
duration = self.media1.get_duration()
position = self.mediaplayer1.get_position()
return duration * position
def updateUI(self):
"""updates the user interface"""
# setting the slider to the desired position
self.positionslider.setValue(self.mediaplayer1.get_position() * 1000)
if not self.mediaplayer1.is_playing():
# no need to call this function if nothing is played
self.timer.stop()
if not self.isPaused:
# after the video finished, the play button stills shows
# "Pause", not the desired behavior of a media player
# this will fix it
self.Stop()
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
player = Player()
player.show()
player.resize(800, 600)
if sys.argv[1:]:
player.OpenFile(sys.argv[1])
sys.exit(app.exec_())
- Is it possible to have only one instance for all stream ? I tried to declare 1 instance with 4 players and open the file with different settings. But the application don't use the settings and show only the first video stream (on the 4 player)
- Is it possible to control all the players with only one command for each action (play, pause, stop, etc...) ? For now I use a command line for each player. Vlc can do that so I think it's possible but don't know how to.