PyQt5:QMediaplayer,QVideowidget播放视频(3)

2024-06-01 22:48

本文主要是介绍PyQt5:QMediaplayer,QVideowidget播放视频(3),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

PyQt5:QMediaplayer,QVideowidget播放视频(3)

简介

在 PyQt5:QMediaplayer,QVideowidget播放视频(2)上一篇中完善了界面的布局,快进,慢进。在本篇更新中做了代码做了重构,架构的好坏就另说了,python 没有做过成熟的项目,一直自己写的玩。在本篇中主要更新了UI播放列表配置项媒体文件管理布局子控件,还有快进、快退、音量等等一些基础功能。

代码结构

模块架构

文件结构
Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----        2020/9/21     20:52                __pycache__
-a----        2020/5/18     22:28            761 audio.py
-a----        2020/5/18     22:23           2008 audio.ui
-a----        2020/9/22     22:13            379 config.json
-a----         2020/5/6     23:31           2371 itemWidget.ui
-a----        2020/9/22     22:15           7805 MediaPlayer.py
-a----        2020/5/18     23:03           1776 MediaPlayer.pyproj
-a----        2020/9/21     20:52           9788 MediaPlayer.ui
-a----        2020/9/21     20:52           8664 ui.py
-a----        2020/5/18     22:01           2281 ui_audio.py
-a----        2020/5/14     21:10           5533 ui_url.py
-a----        2020/5/18     23:03            991 urlWidget.py
-a----        2020/5/14     21:10           7030 urlWidget.ui

在上图中可以看到,主要分为三个模块,MediaPlayer、audio、urlWidget 三个模块。其中 MediaPlayer为主窗口,主体界面布局、逻辑功能、播放窗口、播放列表都在其中实现。audio模块主要负责音量条。urlWidget模块主要负责网络url弹窗输入。

源码介绍

Audio

在文件结构中可以看到,主要有三个文件。audio.ui,ui_audio.py,audio.py 分别是 UI设计文件,UIpy文件,code文件。

Audio.ui

UI设计文件:

在这里插入图片描述

Widget类型,布局全部用UI布局,不使用代码,原则是,尽量少用代码设置,方便后期修改维护。布局时,使用Frame嵌套,方便子控件修改。提高易用性,可读性。

Audio_ui.py

FileName = os.path.basename(sys.argv[0])
FilePath = sys.argv[0].replace(FileName,"")
UiName = FileName.replace(".py",".ui")
UiPath = FilePath +UiName
Ui_pyName = FilePath+"ui_audio.py"
FileFlag = os.path.isfile(Ui_pyName)if FileFlag == 0:sys_cmd	 = os.popen("pyuic5"+" -o "+Ui_pyName+" "+UiPath)time.sleep(1)

还是采用之前的方法,使用命令转换,在更新UI后,删除之前的 ui_xxx.py文件,下次会自动生成。记得将对应的audio.py 设置为启动文件。然后在切回去。

audio.py

from ui_audio import Ui_Audio
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *class audioWidget(QWidget):def __init__(self):super(audioWidget,self).__init__()global uiui = Ui_Audio()ui.setupUi(self)self.audio = uidef getSlider(self):return self.audio.verticalSliderdef getMuteBtn(self):return self.audio.pushButton

对外接口主要有两个 音量输出,静音输出。

urlWidget

与audio模块相同也是拥有三个对应文件. ui 和 ui.py 不做介绍

urlWidget.ui

urlWidget_ui.py

urlWidget.py

from ui_url import Ui_urlWidget
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *class urlWidget(QWidget):fileInfo_Signle = pyqtSignal(list)def __init__(self):super(urlWidget,self).__init__()global uiui = Ui_urlWidget()ui.setupUi(self)self.url = uiui.pushButton_2.clicked.connect(self.sltConfirm)def getFileInfo(self):return [self.url.lineEdit_url.text(),self.url.lineEdit.text()]def sltConfirm(self):self.fileInfo_Signle.emit([self.url.lineEdit_url.text(),self.url.lineEdit.text()])self.hide()def sltCancel(self):self.hide()

其功能主要是添加网络媒体资源时,提供单独的窗口,有两个输入的LineEidt ,一个是 url 路径,一个 媒体资源名称。

提供了两种方式对外输出urlhe 媒体文件名称。调用接口与信号槽

	def getFileInfo(self):return [self.url.lineEdit_url.text(),self.url.lineEdit.text()]
	fileInfo_Signle = pyqtSignal(list)def sltConfirm(self):self.fileInfo_Signle.emit([self.url.lineEdit_url.text(),self.url.lineEdit.text()])self.hide()
MediaPlayer

该模块主窗口模块,主要负责逻辑部分即业务部分。还有一些 listwdiget,videowidget 主要功能实现,其实按照设计模式应该也做单独的 模块,主窗口负责调用。

下面介绍MediaPlayer

初始化

init

	def __init__(self):super(m_window,self).__init__()self.setupUi(self)self.videoframe = QVideoWidget(self) # videoWidget 初始化self.layout_videoframe.addWidget(self.videoframe) # 布局添加videoWidgetself.player = QMediaPlayer(self) #播放器初始化 -- 只负责播放功能self.player.setVideoOutput(self.videoframe)  #设置播放窗体self.playListInit() #播放列表初始化self.connectBind() # 初始化槽函数绑定,适用于全局,以及全流程self.bindPlaylistAnddListWidget() # 绑定播放列表与ListWidgetself.initAudioAndFile() #音频设置初始化self.fileBtnMenuInit() # 文件菜单初始化self.readConfig() #载入配置文件

音频设置初始化,文件添加初始化

	#音频设置初始化,文件添加初始化def initAudioAndFile(self):self.urlWidget = urlWidget()self.urlWidget.fileInfo_Signle.connect(self.sltUrlWidget)self.audio = audioWidget()self.audio.getSlider().valueChanged.connect(self.sltSetAudioValue)self.audio.getMuteBtn().clicked.connect(self.sltSetAudioMute)

播放列表初始化

	#播放列表初始化 - 声明/定义/播放模式设置def playListInit(self):self.playList = QMediaPlaylist()self.player.setPlaylist(self.playList)self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)self.player.positionChanged.connect(self.sltShowPlayTime)

文件菜单初始化

	#文件按钮绑定菜单/本地文件/网络资源def fileBtnMenuInit(self):btnMenu=QMenu(self)btnMenu.addAction("本地文件")btnMenu.addAction("网络资源")self.pushButton_file.setMenu(btnMenu)btnMenu.triggered.connect(self.sltFile)
全局信号槽
	#信号槽绑定函数 -- 主要功能按键 播放/上一个/下一个/音频/文件/设置def connectBind(self):self.pushButton_play.clicked.connect(self.sltPlayState)self.pushButton_befor.clicked.connect(self.sltPlayBefore)self.pushButton_next.clicked.connect(self.sltPlayNext)self.pushButton_audio.clicked.connect(self.sltAudio)self.pushButton_setup.clicked.connect(self.sltSetup)# 设置ListWidget 右键菜单模式self.listWidget_playlist.setContextMenuPolicy(Qt.CustomContextMenu)self.listWidget_playlist.customContextMenuRequested.connect(self.listWidgetRightMenu)
文件添加

按钮初始化

	#文件按钮绑定菜单/本地文件/网络资源def fileBtnMenuInit(self):btnMenu=QMenu(self)btnMenu.addAction("本地文件")btnMenu.addAction("网络资源")self.pushButton_file.setMenu(btnMenu)btnMenu.triggered.connect(self.sltFile)

本地资源添加

	#添加本地文件def addLoadFile(self):str = QFileDialog.getOpenFileName(self,"选择媒体文件","D:/","video files(*.avi *.mp4 *.wmv)")filePath = str[0]fileName = (filePath.split('/')[-1]).split('.')[0]return [filePath,fileName]

网络资源

	#添加网络文件def addNetFile(self):self.urlWidget.show()def sltUrlWidget(self,list):config['playlist'].append({'filepath':list[0],'filename':list[1]})self.addFile(list[0],list[1])

槽函数 -按钮添加文件

	#槽函数-添加文件def sltFile(self,action):if action.text() == "本地文件":fileInfo = self.addLoadFile()config['playlist'].append({'filepath':fileInfo[0],'filename':fileInfo[1]})self.addFile(fileInfo[0],fileInfo[1])elif action.text() == "网络资源":self.addNetFile()def addFile(self,filePath,fileName):self.playList.addMedia(QMediaContent(QUrl.fromLocalFile(filePath)))self.createItem(fileName)
音频设置
	#音频设置def sltAudio(self):pos = self.pushButton_audio.mapTo(self,QPoint(0,0)) #获取相对主窗口坐标#计算 X ,Yx = pos.x() + self.pushButton_audio.width()/2 - self.audio.width() / 2y = pos.y() - self.audio.height() - 6self.audio.move(x,y)if self.audio.isHidden() == True:self.audio.show()else:self.audio.hide()def sltSetAudioValue(self,value): #设置音量值self.player.setVolume(value)def sltSetAudioMute(self): #设置静音self.player.setMuted(bool(1 - self.player.isMuted()))
播放列表

QMediaPlayList

	#播放列表初始化 - 声明/定义/播放模式设置def playListInit(self):self.playList = QMediaPlaylist()self.player.setPlaylist(self.playList) #播放器绑定播放列表self.playList.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop) #设置播放模式self.player.positionChanged.connect(self.sltShowPlayTime) #显示播放位置即进度

添加列表文件

	#创建QListWidgetItemdef createItem(self,str):self.item = QListWidgetItem(str)self.listWidget_playlist.addItem(self.item)#绑定QPlayList与QListWidget -- 利用playlist与widgetlist 的 index 索引 一一对应即实现绑定def bindPlaylistAnddListWidget(self):self.listWidget_playlist.itemDoubleClicked.connect(self.doublePressPlayMedia)

ListWidget-双击播放

	def doublePressPlayMedia(self,item):self.player.stop()self.playList.setCurrentIndex(self.listWidget_playlist.row(item))self.player.play()self.pushButton_play.setText("暂停")

ListWidget-右键菜单

	def listWidgetRightMenu(self,point):self.menu = QMenu(self.listWidget_playlist)self.currentItem = self.listWidget_playlist.itemAt(point)play_action = QAction('播放')del_action = QAction('删除')self.menu.addAction(play_action)self.menu.addAction(del_action)play_action.triggered.connect(self.actionPlay)del_action.triggered.connect(self.actionDel)self.menu.exec(QCursor.pos())#右键播放槽函数def actionPlay(self):self.player.stop()self.playList.setCurrentIndex(self.listWidget_playlist.row(self.currentItem))self.player.play()self.pushButton_play.setText("暂停")#右键删除槽函数def actionDel(self):index = self.listWidget_playlist.row(self.currentItem)if index == self.playList.currentIndex():self.player.stop()self.delCurrentIndex(index)def delCurrentIndex(self,index):current = self.playList.currentIndex()if current == index:self.playList.setCurrentIndex(0)self.player.stop()self.playList.removeMedia(index)self.listWidget_playlist.takeItem(index)
播放设置

播放状态设置

	def sltPlayState(self):if self.player.state() == QMediaPlayer.StoppedState or self.player.state() == QMediaPlayer.PausedState:self.player.play()self.pushButton_play.setText("暂停")else:self.player.pause()self.pushButton_play.setText("播放")

上一首、下一首

	def sltPlayBefore(self):self.player.stop()self.playList.setCurrentIndex((self.playList.currentIndex()-1 < 0) and 0 or self.playList.currentIndex()-1 )self.player.play()def sltPlayNext(self):self.player.stop()self.playList.setCurrentIndex((self.playList.currentIndex() + 1 == self.playList.mediaCount()) and 0 or (self.playList.currentIndex() + 1))self.player.play()

播放进度

	#显示播放时长def sltShowPlayTime(self,postion):self.lcdNumber_progress.display(round(postion/1000))
配置文件

配置文件格式

config = {'playlist':[],'playCurrent':{'index':0,'audio':30,'postion':0}}	
{"playlist": [{"filepath": "D:/13-\u5c0f\u53ef\u7231/df839b27228fa56f81925bd3a619dc96.mp4","filename": "df839b27228fa56f81925bd3a619dc96"}, {"filepath": "D:/13-\u5c0f\u53ef\u7231/1569254169777.mp4","filename": "1569254169777"}, {"filepath": "D:/13-\u5c0f\u53ef\u7231/1569254169777.mp4","filename": "1569254169777"}],"playCurrent": {"index": 0,"audio": 30,"postion": 2.035}
}

读取配置文件

	#配置文件初始化def readConfig(self):file = open("./config.json","r+",encoding='UTF-8')json_str_str = json.load(file)for fileInfo in json_str_str['playlist']:self.addFile(fileInfo["filepath"],fileInfo["filename"])config['playlist'].append({'filepath':fileInfo["filepath"],'filename':fileInfo["filename"]})self.playList.setCurrentIndex(json_str_str["playCurrent"]["index"])self.audio.getSlider().setValue(json_str_str["playCurrent"]["audio"])self.player.setVolume(json_str_str["playCurrent"]["audio"])self.player.setPosition(json_str_str["playCurrent"]["postion"] * 1000)

写入配置文件

	#写入配置文件def writeConfig(self):print("Write ConfigFile!")for i in range(0,self.playList.mediaCount()):path = ""if self.playList.media(i).canonicalUrl().isLocalFile():path = self.playList.media(i).canonicalUrl().toLocalFile()else:path = self.playList.media(i).canonicalUrl().toString()config['playlist'][i]["filepath"] = pathconfig['playlist'][i]["filename"] = self.listWidget_playlist.item(i).text()config['playCurrent']['index'] = self.playList.currentIndex()config['playCurrent']['audio'] = self.player.volume()config['playCurrent']['postion'] = self.player.position() / 1000with open("./config.json",'w') as f:json.dump(config,f)#关闭事件,再退出前重写config配置文件def closeEvent(self,event):self.writeConfig()
运行结果

UI布局

在这里插入图片描述

音频设置

在这里插入图片描述

本地文件导入

在这里插入图片描述

网络

在这里插入图片描述

下载

Git:https://github.com/WQuit/pyqt-qmediaplayer/tree/qmediaplayer-v0.1

CSDN:https://download.csdn.net/download/u011218356/12885123

后续

下期更新,不围着PyQt5 打转了,最近搭好了OpenCv 框架,将搭配OpenCv 进行 图像处理。

这篇关于PyQt5:QMediaplayer,QVideowidget播放视频(3)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1022313

相关文章

Java如何获取视频文件的视频时长

《Java如何获取视频文件的视频时长》文章介绍了如何使用Java获取视频文件的视频时长,包括导入maven依赖和代码案例,同时,也讨论了在运行过程中遇到的SLF4J加载问题,并给出了解决方案... 目录Java获取视频文件的视频时长1、导入maven依赖2、代码案例3、SLF4J: Failed to lo

Python实现多路视频多窗口播放功能

《Python实现多路视频多窗口播放功能》这篇文章主要为大家详细介绍了Python实现多路视频多窗口播放功能的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下... 目录一、python实现多路视频播放功能二、代码实现三、打包代码实现总结一、python实现多路视频播放功能服务端开

Python实现视频转换为音频的方法详解

《Python实现视频转换为音频的方法详解》这篇文章主要为大家详细Python如何将视频转换为音频并将音频文件保存到特定文件夹下,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5. 注意事项

Python视频处理库VidGear使用小结

《Python视频处理库VidGear使用小结》VidGear是一个高性能的Python视频处理库,本文主要介绍了Python视频处理库VidGear使用小结,文中通过示例代码介绍的非常详细,对大家的... 目录一、VidGear的安装二、VidGear的主要功能三、VidGear的使用示例四、VidGea

使用PyQt5编写一个简单的取色器

《使用PyQt5编写一个简单的取色器》:本文主要介绍PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16进制颜色编码,一款跟随鼠标刷新图像的RGB和16... 目录取色器1取色器2PyQt5搭建的一个取色器,一共写了两款应用,一款使用快捷键捕获鼠标附近图像的RGB和16

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT,这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频,并利用 SAM 2 进行 3D 空间分割,无需进一步训练或 2D-3D 投影。 我们的框架支持各种提示类型,包括 3D 点、框和掩模,并且可以泛化到不同的场景,例如 3D 对象、室