首页 > 解决方案 > 如何在 PyQt5 中制作像 WhatsApp/YouTube 这样的视频播放器?

问题描述

我用 pyqt5 制作了一个视频播放器,但问题是它无法运行一个不完整的视频或被当前下载或解密等其他进程使用的视频。所以有什么方法可以制作像 WhatsApp 或 YouTube 这样的播放器,我的意思是它会获取我们已经拥有的数据,然后加载其余的数据。如果用户尝试使用滑块滑动,它将像 WhatsApp 或 YouTube 播放器一样缓冲(显示加载屏幕)。我不知道该怎么做。但是我很好奇在 pyqt5 中这样做。任何帮助将不胜感激。

编辑-

我发现了一些使用 PyQt5 中的 QBuffer 的基本想法:QMediaPlayer 无法从 QBuffer 重播音频以及如何从内存中读取视频数据使用 pyqt5并在我的代码上实现,但即使使用 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_())

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

标签: pythonpython-3.xqtpyqt5media-player

解决方案


推荐阅读