编辑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. 网络io控制器

    网络io控制器 网络io控制器 ZLAN6842,ZLAN6844是8路远程网络IO控制器.含有8路DI.8路DO,8路AI输入.其中DI支持干节点和湿节点,带光耦隔离:DO为继电器输出,具有5A 2 ...

  2. python 不定长参数

    1 #不定长参数 * 元祖 ** 字典 2 def item(a,b,*c,**d): 3 print(a) 4 print(b) 5 print(c) 6 print(d) 7 8 item(11, ...

  3. charles详解

    Charles抓包https:https://www.jianshu.com/p/ec0a38d9a8cf 浅谈charles抓取https原理:https://www.jianshu.com/p/4 ...

  4. docker下安装kafka和kafka-manager

    1.下载镜像 这里使用了wurstmeister/kafka和wurstmeister/zookeeper这两个版本的镜像 docker pull wurstmeister/zookeeper doc ...

  5. 学了那么多 NoSQL 数据库 NoSQL 究竟是啥

    NoSQL 简史 NoSQL 一词最早出现于 1998 年,是 Carlo Strozzi 开发的一个轻量.开源.不提供 SQL 功能的关系数据库. 2009 年,Last.fm 的 Johan Os ...

  6. 文件开启关闭操作c语言模板

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stri ...

  7. concurrenthasmap

    concur'renthashmap java1.7 hashMap在单线程中使用大大提高效率,在多线程的情况下使用hashTable来确保安全.hashTable中使用synchronized关键字 ...

  8. docker是个啥?

    docker 第一问:什么是容器 容器就是在一个隔离的环境中运行的一个进程.注意关键词,隔离和进程.如果进程停止,那么容器就销毁.因为具有隔离的特点,所以每个容器都拥有自己的文件系统:包括IP地址.主 ...

  9. 2020-2021-1 20209306 《linux内核原理与分析》第二周作业

    一.实验一内容及分析 1.实验一内容过程截图 2.实验一完成后收获 可以看到汇编代码中出现了eax.esp.ebp.eax是累加寄存器,esp是堆栈指针寄存器,ebp是基指针寄存器.汇编代码中用到了m ...

  10. 线程池FixedThreadPool

    可重用线程池,只有核心线程,并发无阻塞, public class MainActivity extends AppCompatActivity { @Override protected void ...