编辑UI

编辑UI如下图所示:

新建视频播放类Display

定义如下初始化函数

def __init__(self, ui, mainWnd):
self.ui = ui
self.mainWnd = mainWnd # 默认视频源为相机
self.ui.radioButtonCam.setChecked(True)
self.isCamera = True # 信号槽设置
ui.Open.clicked.connect(self.Open)
ui.Close.clicked.connect(self.Close)
ui.radioButtonCam.clicked.connect(self.radioButtonCam)
ui.radioButtonFile.clicked.connect(self.radioButtonFile) # 创建一个关闭事件并设为未触发
self.stopEvent = threading.Event()
self.stopEvent.clear()

打开相机

防止UI卡死,需要单独用一个线程去显示视频,可以选中打开相机还是打开本机mp4文件。

    def Open(self):
if not self.isCamera:
self.fileName, self.fileType = QFileDialog.getOpenFileName(self.mainWnd, 'Choose file', '', '*.mp4')
self.cap = cv2.VideoCapture(self.fileName)
self.frameRate = self.cap.get(cv2.CAP_PROP_FPS)
else:
# 下面两种rtsp格式都是支持的
# cap = cv2.VideoCapture("rtsp://admin:Supcon1304@172.20.1.126/main/Channels/1")
self.cap = cv2.VideoCapture("rtsp://admin:Supcon1304@172.20.1.126:554/h264/ch1/main/av_stream") # 创建视频显示线程
th = threading.Thread(target=self.Display)
th.start()

关闭相机

启动线程可以直接调用start(),但是结束线程并没有现成的接口可以调用。

添加一个事件用来判断是否需要关闭相机

def Close():
# 关闭事件设为触发,关闭视频播放
stopEvent.set()

显示视频画面

注意:

  1. OpenCV获得的图像帧数据是RGB格式,QImage是BGR格式,所以需要进行格式转换;
  2. 每次显示完成后都去判断是否点击了关闭按钮。
    def Display(self):
self.ui.Open.setEnabled(False)
self.ui.Close.setEnabled(True) while self.cap.isOpened():
success, frame = self.cap.read()
# RGB转BGR
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
self.ui.DispalyLabel.setPixmap(QPixmap.fromImage(img)) if self.isCamera:
cv2.waitKey(1)
else:
cv2.waitKey(int(1000 / self.frameRate)) # 判断关闭事件是否已触发
if True == self.stopEvent.is_set():
# 关闭事件置为未触发,清空显示label
self.stopEvent.clear()
self.ui.DispalyLabel.clear()
self.ui.Close.setEnabled(False)
self.ui.Open.setEnabled(True)
break

完整源代码

文件VideoDisplay.py


import cv2
import threading
from PyQt5.QtCore import QFile
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtGui import QImage, QPixmap class Display:
def __init__(self, ui, mainWnd):
self.ui = ui
self.mainWnd = mainWnd # 默认视频源为相机
self.ui.radioButtonCam.setChecked(True)
self.isCamera = True # 信号槽设置
ui.Open.clicked.connect(self.Open)
ui.Close.clicked.connect(self.Close)
ui.radioButtonCam.clicked.connect(self.radioButtonCam)
ui.radioButtonFile.clicked.connect(self.radioButtonFile) # 创建一个关闭事件并设为未触发
self.stopEvent = threading.Event()
self.stopEvent.clear() def radioButtonCam(self):
self.isCamera = True def radioButtonFile(self):
self.isCamera = False def Open(self):
if not self.isCamera:
self.fileName, self.fileType = QFileDialog.getOpenFileName(self.mainWnd, 'Choose file', '', '*.mp4')
self.cap = cv2.VideoCapture(self.fileName)
self.frameRate = self.cap.get(cv2.CAP_PROP_FPS)
else:
# 下面两种rtsp格式都是支持的
# cap = cv2.VideoCapture("rtsp://admin:Supcon1304@172.20.1.126/main/Channels/1")
self.cap = cv2.VideoCapture("rtsp://admin:Supcon1304@172.20.1.126:554/h264/ch1/main/av_stream") # 创建视频显示线程
th = threading.Thread(target=self.Display)
th.start() def Close(self):
# 关闭事件设为触发,关闭视频播放
self.stopEvent.set() def Display(self):
self.ui.Open.setEnabled(False)
self.ui.Close.setEnabled(True) while self.cap.isOpened():
success, frame = self.cap.read()
# RGB转BGR
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
self.ui.DispalyLabel.setPixmap(QPixmap.fromImage(img)) if self.isCamera:
cv2.waitKey(1)
else:
cv2.waitKey(int(1000 / self.frameRate)) # 判断关闭事件是否已触发
if True == self.stopEvent.is_set():
# 关闭事件置为未触发,清空显示label
self.stopEvent.clear()
self.ui.DispalyLabel.clear()
self.ui.Close.setEnabled(False)
self.ui.Open.setEnabled(True)
break

文件main.py


import sys
import DisplayUI
from PyQt5.QtWidgets import QApplication, QMainWindow
from VideoDisplay import Display if __name__ == '__main__':
app = QApplication(sys.argv)
mainWnd = QMainWindow()
ui = DisplayUI.Ui_MainWindow() # 可以理解成将创建的 ui 绑定到新建的 mainWnd 上
ui.setupUi(mainWnd) display = Display(ui, mainWnd) mainWnd.show() sys.exit(app.exec_())

效果图

PyQt5播放实时视频流或本地视频文件的更多相关文章

  1. iOS开发- 获取本地视频文件

    下面具体介绍下实现过程.先看效果图.图1. 未实现功能前, iTunes截图 图2. 实现功能后, iTunes截图 图3. 实现功能后, 运行截图 好了, 通过图片, 我们可以看到实现的效果.功能包 ...

  2. iOS 本地视频和网络视频流播放

    需求:最近公司需要做一个楼宇对讲的功能:门口机(连接WIFI)拨号对室内机(对应的WIFI)的设备进行呼叫,室内机收到呼叫之后将对收到的数据进行UDP广播的转发,手机(连接对应的WIFI)收到视频流之 ...

  3. Supermap/Cesium 开发心得----本地视频接入播放

    在三维中,为了增加现实感.给人一种带入感,我们会采取接入视频的方式来实现,那么如何接入视频呢? 由于没有截至写文章为止,我没有视频流数据,所以只能采取本地视频文件的方式来做. 本文介绍结束视频的其中一 ...

  4. android 播放assets文件里视频文件的问题

    今天做了一个功能,就是播放项目工程里面的视频文件,不是播放SD卡视频文件. 因为之前写webview加载assets文件夹时,是这样写的: webView = new WebView(this); w ...

  5. 视频文件自动转rtsp流

    最近碰到一个项目需要用到 rtsp 视频流做测试, 由于真实环境的 摄像头 并不能满足需求,故尝试了一下用本地视频文件转换成rtsp视频流做测试,记录一下~ 采用方案: Docker + EasyDa ...

  6. 【opencv】VideoCapture打不开本地视频文件或者网络IP摄像头

    1.前提:成功打开本地USB摄像头 // 创建VideoCapture对象 VideoCapture vc = new VideoCapture(); // 可以成功打开本地USB摄像头 // 参数可 ...

  7. Android必知必会-获取视频文件的截图、缩略图

    背景 公司最近要求给我负责的APP加上视频录制和发布的功能,我简单的完成了基本的录制和视频压缩功能,后来发现发布接口需要上传视频的截图,网上搜索了一下资料,在这里整理一下. 代码实现 /** * 获取 ...

  8. “本地视频使用flashFXP上传虚拟服务器“的方法

    一.视频转换格式 首先,想要在网页中直接嵌入视频,就得用video标签,而<video>支持的仅有的几种格式中,MP4是兼容性,通用性各方面相对友好的,所以,建议上传之前先转换格式并压缩. ...

  9. .net利用本地播放器播放视频文件代码

    前台点击按钮,执行js事件,跳转到后台代码: function funShowVideo(index) {            var iTop = (window.screen.availHeig ...

随机推荐

  1. MeteoInfoLab脚本示例:subplot

    subplot命令可以自动等间距分配多个坐标系(Axes),命令中有三个参数,前两个定义了行数和列数,第三个指定了当前的坐标系(Axes),绘图命令是作用在当前坐标系中的. 脚本程序: def f(t ...

  2. DFS深度优先搜索算法

    Lake Counting(POJ No.2386) 有一个大小为N*M的园子,雨后积起了水.八连通的积水被认为是在一起的.请求出园子里共有多少个水洼?(八连通是指下图中相对w的*部分) * * * ...

  3. 【原创】xenomai3.1+linux构建linux实时操作系统-基于X86_64和arm

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 目录 一.概要 二.环境准备 1.1 安装内核编译工 ...

  4. Halcon软件介绍与图像基本知识

    1.halcon环境 halcon功能:1.视觉算法(核心)基本 2. 弱语言 3.解释性语言 halcon软件介绍: 1.标题栏 2.菜单栏 3.工具栏 4.工作区 图形窗口(显示图像) 变量窗口( ...

  5. 安装 Linux 系统基础知识概要

    虚拟化软件,建议使用 Vmware Workstation 虚拟硬件配置CPU:2核或更多内存:1G以上,推荐2G硬盘:一块硬盘,200G (虚拟大小)网卡:NAT模式 (桥接在外部网络变化时,无法访 ...

  6. Linux入门到放弃之七《进程管理》

    进程管理 1.查看所有进程,并用全格式显示: 命令:ps -ef 2.用ps命令查看系统当前的进程,并把系统当前的进程保存到文件process中: 命令:ps aux >> process ...

  7. java面试题:多线程交替输出偶数和奇数

    一个面试题:实现两个线程A,B交替输出偶数和奇数 问题:创建两个线程A和B,让他们交替打印0到100的所有整数,其中A线程打印偶数,B线程打印奇数 这个问题配合java的多线程,很多种实现方式 在具体 ...

  8. 【3】TensorFlow光速入门-训练及评估

    本文地址:https://www.cnblogs.com/tujia/p/13862357.html 系列文章: [0]TensorFlow光速入门-序 [1]TensorFlow光速入门-tenso ...

  9. xml在spring中

    平时用的最多的框架莫过Spring,但就算用了怎么久也一直对Spring配置文件的头部那一堆的XML Schema云里雾里的. 今天就来好好整整.俗话说,岁月是把杀猪刀,说不定哪天又忘了,好记性不如烂 ...

  10. java中常见的六种线程池详解

    之前我们介绍了线程池的四种拒绝策略,了解了线程池参数的含义,那么今天我们来聊聊Java 中常见的几种线程池,以及在jdk7 加入的 ForkJoin 新型线程池 首先我们列出Java 中的六种线程池如 ...