在树莓上想用PyQt5写一个视频播放器,PyQt5自带一个库PyQt5.QtMultimedia和PyQt5.QtMultimediaWidgets可以实现视频的播放,可是树莓上安装总是有问题,所以这里采取的是和OpenCV结合的方法。
视频功能的实现主要是调用cv2.VideoCapture(fn)和cap.read(),滑动条的实现是通过cap.set(cv2.CAP_PROP_POS_FRAMES, 视频的帧数)函数实现的。暂停就是一直cv2.waitKey。
文中用到的视频和图标要修改。
注意因为全屏了所以这里的退出方法是"Ctrl+q,或者在其他中退出"
#!/usr/bin/python3
#-*- coding:utf-8 -*-
import sys
import cv2
from time import sleep
from itertools import count
from threading import Thread
import pyaudio
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtGui
class PlayVideo(QWidget):
bClose = False
fn_list = ["/home/pi/Documents/垃圾分类图片和视频/movie/movie1.mp4","/home/pi/Documents/垃圾分类图片和视频/movie/movie2.mp4","/home/pi/Documents/垃圾分类图片和视频/movie/movie3.mp4"]
play_index = 0
def __init__(self, parent=None):
super(PlayVideo, self).__init__(parent)
self.setWindowTitle('视频播放')
self.setWindowIcon(QIcon("/home/pi/Documents/垃圾分类图片和视频/pic/ico1.png"))
self.screen = QDesktopWidget().screenGeometry()
self.resize(self.screen.width(), self.screen.height())
#设置菜单栏
bar = QMenuBar(self)
bar.setFixedSize(self.screen.width(),30)
#设置选项二
play_menu = bar.addMenu("播放选项")
#设置按钮一
play_video = QAction("打开视频文件",self)
play_video.setShortcut("Ctrl+1")
play_video.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/播放视频'))
play_video.triggered.connect(self.manual_choose)
play_menu.addAction(play_video)
#设置按钮二
play_pictures = QAction("自动播放视频",self)
play_pictures.setShortcut("Ctrl+2")
play_pictures.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/播放图片'))
play_pictures.triggered.connect(self.auto_choose)
play_menu.addAction(play_pictures)
#设置停止按钮
play_stop = QAction("停止",self)
play_stop.setShortcut("Ctrl+3")
play_stop.triggered.connect(self.video_stop)
play_menu.addAction(play_stop)
#设置退出按钮
exit_menu = bar.addMenu("其他")
exit_option = QAction("退出",self)
exit_option.setShortcut("Ctrl+Q")
exit_option.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/退出'))
exit_option.triggered.connect(self.exit_stop)
exit_menu.addAction(exit_option)
#设置菜单栏的位置
bar.move(0,0)
#用来显示视频画面的Label组建,自带双缓冲,不闪烁
layout = QGridLayout()
self.lbVideo = QLabel()
self.lbVideo.setFixedSize(1000,620)
self.lbVideo.setAlignment(Qt.AlignCenter)
layout.addWidget(self.lbVideo,0,0,3,3)
#设置滑动条
self.s1 = QSlider(Qt.Horizontal)
self.s1.setToolTip("滑动条")
self.s1.setMinimum(0)#设置最大值
self.s1.setMaximum(50)#设置最小值
self.s1.setSingleStep(1)#设置间隔
self.s1.setValue(0)#设置当前值
self.s1.sliderMoved.connect(self.start_drag)
self.s1.sliderReleased.connect(self.drag_action)
self.moving_flag = 0
self.stop_flag = 0#如果当前为播放值为0,如果当前为暂停值为1
layout.addWidget(self.s1,3,1,1,1)
#设置两个标签分别是当前时间和结束时间
self.label_start = QLabel("00:00")
layout.addWidget(self.label_start,3,0,1,1)
self.label_end = QLabel("00:00")
layout.addWidget(self.label_end,3,2,1,1)
#设置暂停播放和下一个按钮
self.stop_button = QPushButton()
self.stop_button.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/暂停.png'))
self.stop_button.setIconSize(QSize(40,40))
self.stop_button.clicked.connect(self.stop_action)
layout.addWidget(self.stop_button,4,0,1,1)
self.next_button = QPushButton()
self.next_button.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/下一个.png'))
self.next_button.setIconSize(QSize(40,40))
self.next_button.clicked.connect(self.next_action)
layout.addWidget(self.next_button,4,2,1,1)
self.setLayout(layout)
def cvImgtoQtImg(self,cvImg):#定义将opencv图像转PyQt图像的函数
QtImgBuf = cv2.cvtColor(cvImg, cv2.COLOR_BGR2BGRA)
QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0],QtGui.QImage.Format_RGB32)
return QtImg
def playVideoFile(self,fn):#播放影片
self.cap = cv2.VideoCapture(fn)
frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
self.settingSlider(frames)
fps = 24
self.loop_flag = 0
if not self.cap.isOpened():
print("Cannot open Video File")
exit()
while not self.bClose:
ret, frame = self.cap.read()#逐帧读取影片
if not ret:
if frame is None:
print("The video has end.")
else:
print("Read video error!")
break
if self.moving_flag==0:
self.label_start.setText(self.int2time(self.loop_flag))
self.s1.setValue(int(self.loop_flag/24))#设置当前值
self.loop_flag += 1
QtImg = self.cvImgtoQtImg(frame)
self.lbVideo.setPixmap(QtGui.QPixmap.fromImage(QtImg).scaled(self.lbVideo.size()))
self.lbVideo.show()#刷新界面
while self.stop_flag == 1:#暂停的动作
cv2.waitKey(int(1000/fps))#休眠一会,因为每秒播放24张图片,相当于放完一张图片后等待41ms
cv2.waitKey(int(1000/fps))#休眠一会,因为每秒播放24张图片,相当于放完一张图片后等待41ms
#释放
self.cap.release()
def stop_action(self):
if self.stop_flag == 0:
self.stop_flag = 1
self.stop_button.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/播放.png'))
else:
self.stop_flag = 0
self.stop_button.setIcon(QIcon('/home/pi/Documents/垃圾分类图片和视频/图标/暂停.png'))
def next_action(self):
self.bClose = True
self.play_index = (self.play_index+1)%3
self.bClose = False
self.playVideoFile(self.fn_list[self.play_index])
def start_drag(self):
self.moving_flag = 1
def drag_action(self):
self.moving_flag = 0
print('当前进度为%d,被拉动到的进度为%d'%(self.s1.value(), int(self.loop_flag/24)))
if self.s1.value()!=int(self.loop_flag/24):
print('当前进度为:'+str(self.s1.value()))
self.loop_flag = self.s1.value()*24
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.loop_flag)
def video_stop(self):
self.bClose = True
def manual_choose(self):#手动选择视频播放
fn,_ = QFileDialog.getOpenFileName(self,'Open file','/home/pi/Documents/垃圾分类图片和视频/movie',"Video files (*.mp4 *.avi)")
self.playVideoFile(fn)
def auto_choose(self):#自动选择视频播放,如何自动视频播放?
self.playVideoFile(self.fn_list[self.play_index])
def settingSlider(self,maxvalue):
self.s1.setMaximum(int(maxvalue/24))
self.label_end.setText(self.int2time(maxvalue))
def int2time(self,num):
#每秒刷新24帧
num = int(num/24)
minute = int(num/60)
second = num - 60*minute
if minute < 10:
str_minute = '0'+str(minute)
else:
str_minute = str(minute)
if second < 10:
str_second = '0'+str(second)
else:
str_second = str(second)
return str_minute+":"+str_second
def exit_stop(self):
self.stop_flag = 0
self.bClose = True
self.close()
if __name__=="__main__":
app = QApplication(sys.argv)
form = PlayVideo()
form.showFullScreen()
sys.exit(app.exec_())