编辑UI

编辑UI如下图所示:

新建视频播放类Display

定义如下初始化函数

  1. def __init__(self, ui, mainWnd):
  2. self.ui = ui
  3. self.mainWnd = mainWnd
  4. # 默认视频源为相机
  5. self.ui.radioButtonCam.setChecked(True)
  6. self.isCamera = True
  7. # 信号槽设置
  8. ui.Open.clicked.connect(self.Open)
  9. ui.Close.clicked.connect(self.Close)
  10. ui.radioButtonCam.clicked.connect(self.radioButtonCam)
  11. ui.radioButtonFile.clicked.connect(self.radioButtonFile)
  12. # 创建一个关闭事件并设为未触发
  13. self.stopEvent = threading.Event()
  14. self.stopEvent.clear()

打开相机

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

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

关闭相机

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

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

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

显示视频画面

注意:

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

完整源代码

文件VideoDisplay.py


  1. import cv2
  2. import threading
  3. from PyQt5.QtCore import QFile
  4. from PyQt5.QtWidgets import QFileDialog, QMessageBox
  5. from PyQt5.QtGui import QImage, QPixmap
  6. class Display:
  7. def __init__(self, ui, mainWnd):
  8. self.ui = ui
  9. self.mainWnd = mainWnd
  10. # 默认视频源为相机
  11. self.ui.radioButtonCam.setChecked(True)
  12. self.isCamera = True
  13. # 信号槽设置
  14. ui.Open.clicked.connect(self.Open)
  15. ui.Close.clicked.connect(self.Close)
  16. ui.radioButtonCam.clicked.connect(self.radioButtonCam)
  17. ui.radioButtonFile.clicked.connect(self.radioButtonFile)
  18. # 创建一个关闭事件并设为未触发
  19. self.stopEvent = threading.Event()
  20. self.stopEvent.clear()
  21. def radioButtonCam(self):
  22. self.isCamera = True
  23. def radioButtonFile(self):
  24. self.isCamera = False
  25. def Open(self):
  26. if not self.isCamera:
  27. self.fileName, self.fileType = QFileDialog.getOpenFileName(self.mainWnd, 'Choose file', '', '*.mp4')
  28. self.cap = cv2.VideoCapture(self.fileName)
  29. self.frameRate = self.cap.get(cv2.CAP_PROP_FPS)
  30. else:
  31. # 下面两种rtsp格式都是支持的
  32. # cap = cv2.VideoCapture("rtsp://admin:Supcon1304@172.20.1.126/main/Channels/1")
  33. self.cap = cv2.VideoCapture("rtsp://admin:Supcon1304@172.20.1.126:554/h264/ch1/main/av_stream")
  34. # 创建视频显示线程
  35. th = threading.Thread(target=self.Display)
  36. th.start()
  37. def Close(self):
  38. # 关闭事件设为触发,关闭视频播放
  39. self.stopEvent.set()
  40. def Display(self):
  41. self.ui.Open.setEnabled(False)
  42. self.ui.Close.setEnabled(True)
  43. while self.cap.isOpened():
  44. success, frame = self.cap.read()
  45. # RGB转BGR
  46. frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
  47. img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
  48. self.ui.DispalyLabel.setPixmap(QPixmap.fromImage(img))
  49. if self.isCamera:
  50. cv2.waitKey(1)
  51. else:
  52. cv2.waitKey(int(1000 / self.frameRate))
  53. # 判断关闭事件是否已触发
  54. if True == self.stopEvent.is_set():
  55. # 关闭事件置为未触发,清空显示label
  56. self.stopEvent.clear()
  57. self.ui.DispalyLabel.clear()
  58. self.ui.Close.setEnabled(False)
  59. self.ui.Open.setEnabled(True)
  60. break

文件main.py


  1. import sys
  2. import DisplayUI
  3. from PyQt5.QtWidgets import QApplication, QMainWindow
  4. from VideoDisplay import Display
  5. if __name__ == '__main__':
  6. app = QApplication(sys.argv)
  7. mainWnd = QMainWindow()
  8. ui = DisplayUI.Ui_MainWindow()
  9. # 可以理解成将创建的 ui 绑定到新建的 mainWnd 上
  10. ui.setupUi(mainWnd)
  11. display = Display(ui, mainWnd)
  12. mainWnd.show()
  13. 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. 【二分】CF Round #587 (Div. 3)E2 Numerical Sequence (hard version)

    题目大意 有一个无限长的数字序列,其组成为1 1 2 1 2 3 1.......1 2 ... n...,即重复的1~1,1~2....1~n,给你一个\(k\),求第\(k(k<=10^{1 ...

  2. jenkins:配置密钥时报错的解决:Failed to add SSH key. Message invalid privatekey(Jenkins 2.257)

    一,报错的现象: 1,提示信息: jenkins.plugins.publish_over.BapPublisherException: Failed to add SSH key. Message ...

  3. centos8平台使用journalctl管理systemd-journald日志

    一,systemd-journald的作用 1,什么是systemd-journald? systemd-journald 是 systemd 自带的日志系统,是一个收集并存储各类日志数据的系统服务. ...

  4. python爬取知乎评论

    点击评论,出现异步加载的请求 import json import requests from lxml import etree from time import sleep url = " ...

  5. 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   普通的linux 和 普通的windows.    ...

  6. 【应用服务 App Service】当使用EntityFrameWorkCore访问Sql Server数据库时,在Azure App Service会出现Cannot create a DbSet for ** because this type is not included in the model for the context的错误

    问题情形 使用EF Core访问数据库,在本地运行正常,发布到App Service后,偶尔出现了Cannot create a DbSet for ** because this type is n ...

  7. MSF权限维持

    MSF权限维持 环境搭建 目标机:win7 ip:192.168.224.133 攻击机:kali linux ip:192.168.224.129 首先使用web_delivery模块的regsvr ...

  8. ELK6环境搭建

    (一)什么是ELK Stack ELK 到底是什么呢? "ELK"是三个开源项目的首字母缩写,这三个项目分别是:Elasticsearch.Logstash 和 Kibana. E ...

  9. 联赛模拟测试22 D. 简单计算

    题目描述 分析 \(\sum_{i=0}^p[(p|qi)?0:1]=\sum_{i=0}^p[(p/gcd(p,q)|qi/gcd(p,q))?0:1]=\sum_{i=0}^p[(p/gcd(p, ...

  10. dbvis 导出表结构 xls

    1.dbvis 可以导出多种格式的文件,如SQL.XLS.TXT.HTML.JSON.CSV及XML. 需求场景(本场景是实际场景引申的场景,此处导出xls): 最近,遇到一个需求需要将表的结构数据导 ...