I'm trying to play a media file. This is the example on the python-vlc
repository:
import platform
import os
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
import vlc
class Player(QtWidgets.QMainWindow):
"""A simple Media Player using VLC and Qt
"""
def __init__(self, master=None):
QtWidgets.QMainWindow.__init__(self, master)
self.setWindowTitle("Media Player")
# Create a basic vlc instance
self.instance = vlc.Instance()
self.media = None
# Create an empty vlc media player
self.mediaplayer = self.instance.media_player_new()
self.create_ui()
self.is_paused = False
def create_ui(self):
"""Set up the user interface, signals & slots
"""
self.widget = QtWidgets.QWidget(self)
self.setCentralWidget(self.widget)
# In this widget, the video will be drawn
if platform.system() == "Darwin": # for MacOS
self.videoframe = QtWidgets.QMacCocoaViewContainer(0)
else:
self.videoframe = QtWidgets.QFrame()
self.palette = self.videoframe.palette()
self.palette.setColor(QtGui.QPalette.Window, QtGui.QColor(0, 0, 0))
self.videoframe.setPalette(self.palette)
self.videoframe.setAutoFillBackground(True)
self.positionslider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
self.positionslider.setToolTip("Position")
self.positionslider.setMaximum(1000)
self.positionslider.sliderMoved.connect(self.set_position)
self.positionslider.sliderPressed.connect(self.set_position)
self.hbuttonbox = QtWidgets.QHBoxLayout()
self.playbutton = QtWidgets.QPushButton("Play")
self.hbuttonbox.addWidget(self.playbutton)
self.playbutton.clicked.connect(self.play_pause)
self.stopbutton = QtWidgets.QPushButton("Stop")
self.hbuttonbox.addWidget(self.stopbutton)
self.stopbutton.clicked.connect(self.stop)
self.hbuttonbox.addStretch(1)
self.volumeslider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self)
self.volumeslider.setMaximum(100)
self.volumeslider.setValue(self.mediaplayer.audio_get_volume())
self.volumeslider.setToolTip("Volume")
self.hbuttonbox.addWidget(self.volumeslider)
self.volumeslider.valueChanged.connect(self.set_volume)
self.vboxlayout = QtWidgets.QVBoxLayout()
self.vboxlayout.addWidget(self.videoframe)
self.vboxlayout.addWidget(self.positionslider)
self.vboxlayout.addLayout(self.hbuttonbox)
self.widget.setLayout(self.vboxlayout)
menu_bar = self.menuBar()
# File menu
file_menu = menu_bar.addMenu("File")
# Add actions to file menu
open_action = QtWidgets.QAction("Load Video", self)
close_action = QtWidgets.QAction("Close App", self)
file_menu.addAction(open_action)
file_menu.addAction(close_action)
open_action.triggered.connect(self.open_file)
close_action.triggered.connect(sys.exit)
self.timer = QtCore.QTimer(self)
self.timer.setInterval(100)
self.timer.timeout.connect(self.update_ui)
def play_pause(self):
"""Toggle play/pause status
"""
if self.mediaplayer.is_playing():
self.mediaplayer.pause()
self.playbutton.setText("Play")
self.is_paused = True
self.timer.stop()
else:
if self.mediaplayer.play() == -1:
self.open_file()
return
self.mediaplayer.play()
self.playbutton.setText("Pause")
self.timer.start()
self.is_paused = False
def stop(self):
"""Stop player
"""
self.mediaplayer.stop()
self.playbutton.setText("Play")
def open_file(self):
"""Open a media file in a MediaPlayer
"""
dialog_txt = "Choose Media File"
filename = QtWidgets.QFileDialog.getOpenFileName(self, dialog_txt, os.path.expanduser('~'))
if not filename:
return
# getOpenFileName returns a tuple, so use only the actual file name
self.media = self.instance.media_new(filename[0])
# Put the media in the media player
self.mediaplayer.set_media(self.media)
# Parse the metadata of the file
self.media.parse()
# Set the title of the track as window title
self.setWindowTitle(self.media.get_meta(0))
# The media player has to be 'connected' to the QFrame (otherwise the
# video would be displayed in it's own window). This is platform
# specific, so we must give the ID of the QFrame (or similar object) to
# vlc. Different platforms have different functions for this
if platform.system() == "Linux": # for Linux using the X Server
self.mediaplayer.set_xwindow(int(self.videoframe.winId()))
elif platform.system() == "Windows": # for Windows
self.mediaplayer.set_hwnd(int(self.videoframe.winId()))
elif platform.system() == "Darwin": # for MacOS
self.mediaplayer.set_nsobject(int(self.videoframe.winId()))
self.play_pause()
def set_volume(self, volume):
"""Set the volume
"""
self.mediaplayer.audio_set_volume(volume)
def set_position(self):
"""Set the movie position according to the position slider.
"""
# 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 suffice).
# Set the media position to where the slider was dragged
self.timer.stop()
pos = self.positionslider.value()
self.mediaplayer.set_position(pos / 1000.0)
self.timer.start()
def update_ui(self):
"""Updates the user interface"""
# Set the slider's position to its corresponding media position
# Note that the setValue function only takes values of type int,
# so we must first convert the corresponding media position.
media_pos = int(self.mediaplayer.get_position() * 1000)
self.positionslider.setValue(media_pos)
# No need to call this function if nothing is played
if not self.mediaplayer.is_playing():
self.timer.stop()
# After the video finished, the play button stills shows "Pause",
# which is not the desired behavior of a media player.
# This fixes that "bug".
if not self.is_paused:
self.stop()
def main():
"""Entry point for our simple vlc player
"""
app = QtWidgets.QApplication(sys.argv)
player = Player()
player.show()
player.resize(640, 480)
sys.exit(app.exec_())
if __name__ == "__main__":
main()
However, when I select a file from my phone connected with USB, I get this warning.
libdvdread: Attempting to use device /dev/sda4 mounted on / for CSS authentication
libdvdread: Could not open input: Permission denied
libdvdread: Can't open /dev/sda4 for reading
libdvdread: Device /dev/sda4 inaccessible, CSS authentication not available.
libdvdread:DVDOpenFilePath:findDVDFile /VIDEO_TS/VIDEO_TS.IFO failed
libdvdread:DVDOpenFilePath:findDVDFile /VIDEO_TS/VIDEO_TS.BUP failed
libdvdread: Can't open file VIDEO_TS.IFO.
libdvdnav: vm: failed to read VIDEO_TS.IFO
Do I have to copy over the files temporarily to play them? Or is there another way?
If the device is mass storage you don't have to copy over but for phones that don't have a feature like that I had to copy over the file before playing. I used shutil
for it. In a thread other than the main thread, of course.
import shutil
copied_file = shutil.copyfile(src_filepath, dest_filepath)
self.media = self.instance.media_new(copied_file)