pyQT 视频播放器(三) 实现视频截图、获取每一帧数据
pyQT 视频播放器(三) 实现视频截图、获取每一帧数据
- 背景
- 方法调研
- 详细代码说明
- 最终效果
- 总结:
- 参考资料
背景
在 “PyQt5 实现视频播放器(二) ,详细版本 ,适合新手入门“
中已经想写的介绍了如何使用pyQT 自带的一些控件,实现简单的视频播放功能(例如播放、暂停、进度条跳转、声音控制、全屏播放等),通过评论区的交流,发现大家除了这些简单功能外,还有一个比较强烈的需求就是视频截图,所以下面就来实现一下视频截图功能
方法调研
在方法调研的前分享一下自己在遇到一个新问题的时候的“搜索方法”,希望能够起到抛砖引玉的作用。(有了正确的搜索方式,对于开发能少走弯路,提高效率)
- 问题定义:这一步也容易也难,特别是工作之后会有更加深刻的体验,简单来说就是如何将你的需求/问题与实际程序实现逻辑进行对应,比如说想实现视频进度条展示,那么对应到具体的pyqt的开发中可能就是,如何使用qt的slider来展示qmediaplayer 播放的媒体进度。这就要求你能对需求/问题进行分解、对使用的程序逻辑/程序组件功能有充分的了解。有点啰嗦了,回归正题,问题定义为:
“qt实现视频截图”、如何获取qt视频播放中的每一帧数据、“qt mediaplayer 截图 ”,
会用英文更好: get frame data using QMediaPlayer - 搜索: pyQT作为QT的一个python版本接口使用方式,整体的资料虽然不如QT的多,但是QT的使用方式都能够在pyQT上使用,因此我在搜索的时候基本上都是不区分pyqt和QT的,比如这次搜索的时候就是查询qt 如何获取,参考的代码也都是QT的源码,改成python的时候只需要注意import 的位置、以及c++写法到python写法的切换即可。
- 筛选:搜索到的方案比较多,大致可以归纳为如下几种:
(1)使用“截屏”的方式来完成截图,我稍微尝试了一下发现对于qmediaplayer输出的widget无法截取到画面图像,另外即使截取到了也只是UI界面上大小原始原始图像的大小,因此放弃这个方案
(2)qt + ffmpeg或qt + vlc或qt+ opencv 等进行视频解码播放,功能强大,能够比较方便的进行功能较复杂的图像处理需求,例如使用opencv可以对图像进行复杂的操作(识别、检测、画框)
(3)QMediaPlayer + QAbstractVideoSurface,比较方便,转换的是QImage,可以获取每一帧数据。
方案筛选上,由于我们只需要完成截图功能,而且之前用的就是Qmediaplayer,选方案二,能够最快速的实现这个功能。
详细代码说明
采用 QMediaPlayer + QAbstractVideoSurface 这个方案重点需要了解一下QAbstractVideoSurface 这个类,结合查询到的资料以及Assistant中的说明:QAbstractVideoSurface class is a base class for video presentation surfaces.
其中 [pure virtual] 的有两个函数:
(1)supportedPixelFormats() # 支持的视频解码后的数据格式
(2)present(const QVideoFrame &frame) # 获取视频解码的数据frame,进行展示
因此我们只需要新写一个类,继承这个抽象的QAbstractVideoSurface 类,然后重写里面的这个两个纯虚函方法,就能从present 输入的Frame中获取每一帧的数据。
如下:
from PyQt5.QtMultimedia import QAbstractVideoSurface, QVideoFrame, QAbstractVideoBuffer
from PyQt5.QtCore import pyqtSignal, QDateTime
from PyQt5.QtGui import QImage
class myVideoSurface(QAbstractVideoSurface):FinishGrab = pyqtSignal() # 截图完成信号def __init__(self, parent=None):super(QAbstractVideoSurface, self).__init__(parent)def supportedPixelFormats(self, type=None):support_format = [QVideoFrame.Format_ARGB32,QVideoFrame.Format_ARGB32_Premultiplied,QVideoFrame.Format_ARGB8565_Premultiplied,QVideoFrame.Format_AYUV444,QVideoFrame.Format_AYUV444_Premultiplied,QVideoFrame.Format_BGR24,QVideoFrame.Format_BGR32,QVideoFrame.Format_BGR555,QVideoFrame.Format_BGR565,QVideoFrame.Format_BGRA32,QVideoFrame.Format_BGRA32_Premultiplied,QVideoFrame.Format_BGRA5658_Premultiplied,QVideoFrame.Format_CameraRaw,QVideoFrame.Format_IMC1,QVideoFrame.Format_IMC2,QVideoFrame.Format_IMC3,QVideoFrame.Format_IMC4,QVideoFrame.Format_Jpeg,QVideoFrame.Format_NV12,QVideoFrame.Format_NV21,QVideoFrame.Format_RGB24,QVideoFrame.Format_RGB32,QVideoFrame.Format_RGB555,QVideoFrame.Format_RGB565,QVideoFrame.Format_User,QVideoFrame.Format_UYVY,QVideoFrame.Format_Y16,QVideoFrame.Format_Y8 ,QVideoFrame.Format_YUV420P,QVideoFrame.Format_YUV444,QVideoFrame.Format_YUYV,QVideoFrame.Format_YV12,]return support_formatdef present(self, frame: 'QVideoFrame'):print("width:{},heigth:{},format:{},start_time:{},endtime{}".format(frame.width(), frame.height(), frame.pixelFormat(), frame.startTime(), frame.endTime()))if frame.isValid():frame.map(QAbstractVideoBuffer.ReadOnly)img = QImage(frame.bits(), frame.width(), frame.height(),QVideoFrame.imageFormatFromPixelFormat(frame .pixelFormat()))grab_jpg = './'+QDateTime.currentDateTime().toString("yyyy-MM-dd hh-mm-ss-zzz")+'.jpg'save_state = img.save(grab_jpg)print("截图状态:"+str(save_state))frame.unmap()self.FinishGrab.emit()return Trueelse:return False
其中 supportedPixelFormats 中的支持的格式只要后面present中能够支持即可,由于我们并不是真的展示,在present中只是转成了QImage,然后完成截图。在这里有两种方案:
(1)使用present中每一帧数据进行展示(这里已经转成QImage图像数据了,接着想怎么画图都可以,然后图像展示就可以),这个方案的话就是图像转换比较耗时,可能会影响到播放的流畅度,如果不是每一帧图像都需要处理的话,不建议用这种方式
(2)播放然后采用“PyQt5 实现视频播放器(二) ,详细版本 ,适合新手入门“
中介绍的widget进行播放,只有需要截图的将player的输出切换到videosurface进行截图,截完图在切换回去,这种方式播放就是在截图的时候由于切换了player的输出因此会导致截图的时候视频界面会就“黑“一下(此时没有输出),
这里考虑到截图功能不是每一帧都需要截(由界面上得按钮触发),因此采用了方案(2)
最终效果
首先在原先 “PyQt5 实现视频播放器(二) ,详细版本 ,适合新手入门“中的界面基础上增加了一个截图按钮:
在视频播放的时候,点击截图按钮,会自动截取当前时刻的图片,由于只是demo(抛砖引玉的作用),因此图片会保存到demo所在的当前目录下面(保存的代码在present函数中):
某张具体的截图如下:(获取到720x480的原始尺寸大小)
总结:
(1)基本完成视频截图的功能,如果需要复杂的功能可以在这个上面继续扩展(例如截图的列表展示、截图的帧号等)
(2)截图的时候已经能够获取每一帧的数据,那么对应的“画框”、图像检测、分类等等都可以在这个上面进行扩展
(3)完整的演示demo 已经打包上传到csdn上:
[https://download.csdn.net/download/u012552296/84553765](demo中有视频和解码器,可以完整运行完整个demo,windows10 环境验证正常)(https://download.csdn.net/download/u012552296/84553765)
[https://download.csdn.net/download/u012552296/16184221] (https://download.csdn.net/download/u012552296/16184221)
参考资料
如果你想加载一篇你写过的.md文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。
[1]How to save a frame using QMediaPlayer?
https://stackoverflow.com/questions/37724602/how-to-save-a-frame-using-qmediaplayer
[1]原来Qt从视频中获取每一帧数据如此简单: https://blog.csdn.net/jxbinwd/article/details/81034339
pyQT 视频播放器(三) 实现视频截图、获取每一帧数据相关推荐
- Qt从视频中获取每一帧数据
参考了以下文章:https://blog.csdn.net/jxbinwd/article/details/81034339 我按照上面文章的描述写程序,解析出来的图像保存成图片.保存的图片有很多乱码 ...
- Android FFmpeg视频播放器三 音频封装格式解码播放
Android FFmpeg视频播放器一解封装 Android Android FFmpeg视频播放器二 视频封装格式解码播放 视频解封装之后就会得到音频流和视频流,解封状得到的数据是AVPackag ...
- 安卓开发本地视频播放器——扫描本地视频文件显示在gridview上,然后点击播放。
本文将引导大家做一个本地视频播放器,希望能帮到有需要的朋友. 直接上代码: 下面这是获取扫描视频的代码. package com.mediaplayer.utils;import java.util. ...
- android电商评论,三步教你获取电商评论数据
现在的电商平台的商品琳琅满目,咱们足不出户就可以淘到性价比很好的尖货.但是东西多了大家不免要比较一番,这个时候看看商品粉丝的评论就尤其重要. 接下来一步步给大家介绍怎样获取评论的数据来供我们分析,以天 ...
- H.264裸流文件中获取每一帧数据
测试解码器性能时,最常用的无非是向解码器中推送码流. 之前封装了一个avc的解码器,想做一个测试,读取H.264裸流文件将码流定期定时推送到解码器. 测试其实很简单: 1.了解H.264裸流文件的构成 ...
- android videoview截屏,如何进行网络视频截图/获取视频的缩略图
小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题.本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下一个问题,如下图所示,如果要获取直播中节 ...
- C++ Qt高仿QQ影音视频播放器 (三)
本篇介绍中间视频播放控件的实现. 主要涉及到3个控件:打开文件按钮.右侧打开文件列表按钮.播放时间进度条按钮.播放效果如下: 正常播放时,时间进度条只有在鼠标悬浮到视频区域时才显示. 打开 ...
- vue 视频截图获取第一帧或者某一帧
id:传入的video容器id,imgType:截图文件的类型. const screenshot = (id, imgType)=>{const video = document.getEle ...
- android 暂停函数,Android万能视频播放器06-添加视频暂停、播放和Seek功能
1.Seek函数: avformat_seek_file(pFormatCtx, -1, INT64_MIN, relsecds, INT64_MAX, 0); relsecds单位: int64_t ...
最新文章
- 用户操作拦截并作日志记录--自定义注解+AOP拦截
- 年结 利润分配-未分配利润年结
- KDD2021 放榜,6 篇论文带你了解阿里妈妈AI技术
- 用9种办法解决 JS 闭包经典面试题之 for 循环取 i
- SQLi LABS Less-22
- php array_diff 用法
- window版GitHub使用
- matlab位图矢量化,matlab图形矢量化解决方案
- SpringBoot整合定时任务(在线Cron表达式生成器)
- 西门子G120变频器常用参数(自己总结的)
- 怎么利用企业微信营销 企业微信如何营销 企业微信如何维护好友 企业微信如何开通
- 让你嘿嘿嘿!最新windows7升级win10方法!
- 百度paddlepaddle入门讲解第一周内容
- 铝电解电容器在电路设计时的使用注意事项
- matlab 实验七 低层绘图操作,matlab实验内容答案
- 【Web动画】CSS3 3D 行星运转 浏览器渲染原理
- python骚操作!WiFi密码还能这样获取?用户扫一扫连接,无需输入密码
- 全球与中国车载称重系统市场现状及未来发展趋势
- C++围棋小游戏1.2.2
- 教你一招,能解决90%的机房问题