Search code examples
pythonpyqt5video-player

how to create video player in pyqt5 for windows to play mp4 using python code?


I tried to create video player for mp4 in windows 10 os. it is always showing error. i tried multiple method. but always failing

  1. I tried code from this location https://pythonprogramminglanguage.com/pyqt5-video-widget/
    QMediaPlayer error:

enter image description here

  1. I tried python-vlc. it is working only when I already installed vlc player. if i uninstalled vlc player it is not working

vlc error :

File "<module1>", line 7, in <module>
  File "D:\Portable_Python\App\Python\lib\site-packages\vlc.py", line 210, in <module>
    dll, plugin_path  = find_lib()
  File "D:\Portable_Python\App\Python\lib\site-packages\vlc.py", line 173, in find_lib
    dll = ctypes.CDLL(p)
  File "D:\Portable_Python\App\Python\lib\ctypes\__init__.py", line 364, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 193] %1 is not a valid Win32 application
>>> 
  1. tkvideoplayer

I tried code from this location https://github.com/PaulleDemon/tkVideoPlayer/blob/master/examples/sample_player.py

it is working fine. but I couldn't able it embed to pyqt5 window.

I attached example video file in this location https://drive.google.com/file/d/1AaTzf3LBUMCztO8hYpF9muPUImVDX1s_/view?usp=sharing

please give me a best solution in any one module.

I added simple code below . this is playing .avi file and not playing .mp4 files

from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QPushButton
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
import sys

class VideoPlayer:
    def __init__(self):
        self.video = QVideoWidget()
        self.video.resize(300, 300)
        self.video.move(0, 0)
        self.player = QMediaPlayer()
        self.player.setVideoOutput(self.video)
        self.player.setMedia(QMediaContent(QUrl.fromLocalFile("D:/2.mp4")))

    def callback(self):
        self.player.setPosition(0) # to start at the beginning of the video every time
        self.video.show()
        self.player.play()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    v = VideoPlayer()
    b = QPushButton('start')
    b.clicked.connect(v.callback)
    b.show()
    sys.exit(app.exec_())

Solution

  • As couldn't able to find direct player. I used cv module and ffpyplayer to integrate with pyqt5. it is temporarily resolved my issue. the code is given below.

    from ffpyplayer.player import MediaPlayer
    
    from PyQt5 import QtGui,QtCore
    from PyQt5.QtWidgets import *
    from PyQt5.QtGui import *
    from PyQt5.QtCore import *
    import sys
    import threading
    import time
    import cv2
    from PIL import Image
    import numpy
    import os
    
    class VideoPlayer:
        def __init__(self, filename,volume = 1.0):
            if not os.path.exists(filename):raise FileNotFound(filename)
            self.close = False
            self.state = None
            self.frame = None
            self.l=None
            self.filename = filename
            self.skip_interval=5
    
            self.player = MediaPlayer(filename, ff_opts={'sync': 'audio', 'paused': False, 'volume': volume, 't': 1e7+1, 'ss': 0})
            time.sleep(1)
            self.duration=self.player.get_metadata()['duration']
            handler_thread = threading.Thread(target=self.play, args=(), daemon=True)
            handler_thread.start()
    
        def play(self):
            while True:
                frame, self.val = self.player.get_frame()
                if self.val == 'eof':self.close=True
                if self.close == True:
                    self.player.toggle_pause()
                    self.player.close_player()
                    time.sleep(2)
                    break
    
                if isinstance(self.val, str) or self.val == 0.0:waitkey = 32
                else:waitkey = int(self.val * 100)
                pressed_key = cv2.waitKey(waitkey) & 0xFF
    
                if frame is None:continue
    
                image, pts = frame
                self.frame = (image, self.val)
                x, y = image.get_size()
                data = image.to_bytearray()[0]
                image =  Image.frombytes("RGB", (x, y), bytes(data))
                image = cv2.cvtColor(numpy.array(image), cv2.COLOR_RGB2BGR)
                self.frame=frame
    
                if self.l!=None:
                    h, w, ch = image.shape
                    Image2 = QImage(image.data, w, h, ch * w, QImage.Format_RGB888)
                    self.pixmap=QPixmap.fromImage(Image2)
                    self.l.setPixmap(self.pixmap)
                    self.l.setFixedWidth(self.l.pixmap().width())
                    self.l.setFixedHeight(self.l.pixmap().height())
                    self.l.parent().update()
                del image
    
    
        def seek_p(self):
                if int(self.player.get_pts()) + self.skip_interval < int(self.duration):
                    self.player.seek(self.skip_interval, relative=True, accurate=False)
        def seek_m(self):
            if int(self.player.get_pts()) - self.skip_interval > 0:
                self.player.seek(-self.skip_interval, relative=True, accurate=False)
    
    
    
    class ed(QWidget):
        def __init__(self,parent=None):
            super().__init__()
            vl=QVBoxLayout()
            self.setLayout(vl)
            pb=QPushButton('play');vl.addWidget(pb);pb.clicked.connect(self.play)
            pb=QPushButton('stop');vl.addWidget(pb);pb.clicked.connect(self.close)
            pb=QPushButton('pause');vl.addWidget(pb);pb.clicked.connect(self.pause)
            pb=QPushButton('seek+');vl.addWidget(pb);pb.clicked.connect(self.seek_p)
            pb=QPushButton('seek-');vl.addWidget(pb);pb.clicked.connect(self.seek_m)
            pb=QPushButton('mute');vl.addWidget(pb);pb.clicked.connect(self.mute)
            pb=QPushButton('vol+');vl.addWidget(pb);pb.clicked.connect(self.vol_p)
            pb=QPushButton('vol-');vl.addWidget(pb);pb.clicked.connect(self.vol_m)
            self.l=QLabel();vl.addWidget(self.l)
        def play2(self):
            self.player=VideoPlayer('D:/2.mp4')
            self.player.l=self.l
    
        def play(self):
            self.t1=threading.Thread(target=self.play2)
            self.t1.start()
    
        def pause(self):self.player.player.toggle_pause()
        def seek_p(self):self.player.seek_p()
        def seek_m(self):self.player.seek_m()
        def mute(self):
            try:
                if (self.player.player.get_volume()>0.0):self.player.player.set_volume(0.0)
                else:self.player.player.set_volume(1.0)
            except:pass
        def vol_p(self):
            self.player.player.set_volume(self.player.player.get_volume() + 0.1)
            print(self.player.player.get_volume())
        def vol_m(self):
            self.player.player.set_volume(self.player.player.get_volume() - 0.1)
            print(self.player.player.get_volume())
    
        def close(self):
            try:
                self.player.close=True
                time.sleep(1)
            except:pass
    
        def closeEvent(self, event):
            try:
                self.player.close=True
                time.sleep(1)
            except:pass
    
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        window=ed()
        window.showMaximized()
        sys.exit(app.exec_())