python - 如何在 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_())
这是具有一些基本功能的基本媒体播放器代码。
解决方案
推荐阅读
- mysql - Apache 中的 PHPMyAdmin 500 内部服务器错误
- python - 如何将特定字母添加到变量然后使其成为字符串
- laravel - 尝试使用 laravel 8 获取非对象的属性“id”
- php - Laravel 雄辩错误期望参数 1 在尝试使用 sum 时为字符串
- scikit-learn - 绘制决策树未给出预期结果
- html - 出现不需要的左边距
- python - 如何一次创建多个数组
- html - 如何在移动视图中使 Bulma 框元素中的元素全宽
- react-native - useEffect 在没有刷新的情况下无法在自定义抽屉组件中工作
- javascript - 如何在 asp.net 核心中使用 JavaScript 创建倒数计时器?