如何在PyQt5中制作像WhatsApp/YouTube这样的视频播放器?

2024-09-29 23:17:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我用pyqt5制作了一个视频播放器,但问题是它不能运行一个不完整的视频,也不能被其他进程使用,比如当前的下载或解密。那么有没有办法制作一个像WhatsApp或YouTube这样的播放器呢?我的意思是,它将获取我们已经拥有的数据,然后加载其余的数据。如果用户尝试滑动,那么在这段时间内使用滑块它将缓冲(显示加载屏幕),如WhatsApp或YouTube播放器。我不知道如何做到这一点。但我非常好奇在pyqt5中做到这一点。任何帮助都将不胜感激

编辑-

我发现了一些基本的想法,使用来自PyQt5 : QMediaPlayer can't replay audio from QBufferhow to read video data from memory use pyqt5的QBuffer并在我的代码上实现,但是它可以播放小文件而不是大文件,即使使用Qthread它也会崩溃。我不知道这是实现这一点的唯一方法还是有更好的方法。这是我的代码

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtCore import QDir, Qt, QUrl
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtWidgets import (QApplication, QFileDialog, QHBoxLayout, QLabel,
        QPushButton, QSizePolicy, QSlider, QStyle, QVBoxLayout, QWidget)
from PyQt5.QtWidgets import QMainWindow,QWidget, QPushButton, QAction
from PyQt5.QtGui import QIcon
import sys     
class Worker(QtCore.QObject):
    word=QtCore.pyqtSignal(str)
    def encrypt(self,path,obj):
        try:
            with open(path, 'rb') as stream:
                    obj.setData(stream.read())
            if obj.open(QtCore.QIODevice.ReadOnly):
                self.word.emit('hi')
        except Exception as e:
                print(e)        
class Player(QMainWindow):
    speak=QtCore.pyqtSignal(str,object)
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("PyQt Video Player Widget Example") 

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        videoWidget = QVideoWidget()

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                QSizePolicy.Maximum)

        # Create new action
        openAction = QAction(QIcon('open.png'), '&Open', self)        
        openAction.setShortcut('Ctrl+O')
        openAction.setStatusTip('Open movie')
        openAction.triggered.connect(self.openFile)

        # Create exit action
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)        
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.exitCall)

        # Create menu bar and add action
        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        #fileMenu.addAction(newAction)
        fileMenu.addAction(openAction)
        fileMenu.addAction(exitAction)

        # Create a widget for window contents
        wid = QWidget(self)
        self.setCentralWidget(wid)

        # Create layouts to place inside widget
        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        layout.addLayout(controlLayout)
        layout.addWidget(self.errorLabel)

        # Set widget to contain window contents
        wid.setLayout(layout)

        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)
#######
#Here is the main part
#####
        self.worker = Worker()
        self.speak.connect(self.worker.encrypt)
        self.thread=QtCore.QThread(self)
        self.worker.moveToThread(self.thread)
        self.worker.word.connect(self.ready)
        self.buffer = QtCore.QBuffer()
    def ready(self):
        print('Ready')  
        self.mediaPlayer.setMedia(
                    QMediaContent(), self.buffer)
                  
    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                "C:/Users/mishra/Desktop/HiddenfilesWindow/")
        print(fileName)
        if fileName != '':
            try:
                self.buffer.close()
                self.thread.start()
                self.speak.emit(fileName,self.buffer)
                # self.mediaPlayer.setMedia(
                #         QMediaContent(QUrl.fromLocalFile(fileName)))
                self.playButton.setEnabled(True)
            except Exception as e:
                print(e)

    def exitCall(self):
        sys.exit(app.exec_())

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
          
if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    window = Player()
    window.show()
    sys.exit(app.exec_())

这是一个基本的媒体播放器代码,具有一些基本功能


Tags: fromimportselfifdefconnectcreatesys

热门问题