一、引言

在写《第15.39节、splitDockWidget和tabifyDockWidget嵌套布局QDockWidget的PyQt人机对话案例:笨笨机器人》的,为了说明setDockNestingEnabled的作用,使用了2个动画,当时是使用录屏软件录屏录的MP4文件,但将其转gif时遇到了困难,网上各种下载的工具都是在gif文件中加了各种LOGO图形,在线的转码操作很困难,转得慢,好不容易转完之后发现下载不下来,实在不想用了。作为一个Pythonic的人,马上想到的是“人生苦短,我用Python”,网上一查,结果发现好多大神有跟老猿一样的情况,并且还真有工具,一个是基于MoviePy 的,一个是基于OpenCV的,都还比较好使用,但MoviePy更好用,于是马上动手安装了一个。

二、MoviePy简介

MoviePy能处理的视频是ffmpeg格式的,老猿理解支持的文件类型至少包括:*.mp4 *.wmv *.rm *.avi *.flv *.webm *.wav *rmvb 。

MoviePy有很多与视频相关的功能,包括剪辑、合成、分离音视频等,在此老猿只用了其中的视频转gif的功能,老猿暂时没准备去深入研究,在此也不多介绍,大家可以参考《MoviePy - 中文文档(一个专业的python视频编辑库)教程》的介绍以及英文版官方文档https://zulko.github.io/moviepy/中文版文档:http://moviepy.cn/。在此就说明如下几点:

  1. 安装:pip安装时,请将站点指向国内的镜像站点,否则下载很慢或者下载不下来,老猿使用清华的镜像,指令是:

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple moviepy

    注意moviepy全小写,安装时会自动安装相关依赖包,这点与上面文章介绍的有出入。

  2. 模块导入:moviepy是一个包,由于只使用视频转gif,相关功能在editor模块内,因此导入使用指令:

    import moviepy.editor as mpe

  3. 视频文件装载方法:

    VideoFileClip(videoFile)

    这个方法就是构造一个VideoFileClip对象,这个对象就是视频的内容,可以通过该对象对视频进行剪辑等操作

  4. 截取视频方法:

    subclip(start,end)

    参数start和end是视频起止位置,如果是整数单位是秒,也可以是其他时间设置方法,如:2分12.5秒,表示方法可以是(2,12.5)、(0,2,12.5)或者 (00:02:12.5)。

    返回值还是一个VideoFileClip对象。

  5. 输出视频到gif文件的方法:

    write_gif(gifFileName,fps=fps)

    write_gif有很多参数,除了第一个参数是文件名外,其他参数都是关键字参数(不明白关键字参数的请参考《第5章函数进阶 第5.1节 Python函数的位置参数、关键字参数精讲》),在此老猿仅使用了fps参数,其他参数就不展开说了。fps参数是指生成GIF是每秒抽取的帧数,这个数字越大,同样视频生成的gif文件就越大,所以需要有所取舍。

    6、关闭视频缓存方法:close方法用于关闭视频缓存。

示例代码:
		import moviepy.editor as mpe
cache = mpe.VideoFileClip(r"c:\temp\操作录屏.mp4").subclip(0,15)
cache.write_gif(r"c:\temp\操作录屏.gif",fps=2)

三、构建MP4视频转gif工具

3.1、设计操作界面

工具的操作界面提供了选择视频文件、输出gif文件、设置输出视频段的起止时间以及转换GIF的fps,另外老猿发现moviepy的输出都是打印输出,因此将所有相关输出信息(包括自编代码输出和moviepy模块的输出)重定向到了信息输出历史窗proccessInf中,同时将最近输出的信息显示在“最近输出信息”后面的名为currentInf的label上。输入信息设置完成后,点击转换按钮即将对应视频输出到gif文件中。整体ui设计界面如下:

3.2、实现转换按钮点击的槽方法

为了确保转换不被异常操作干扰,开始转换后整个主窗口设置为disable,转换完成后恢复enable。

    def convert(self):
self.setEnabled(False)
self.proccessInf.clear()
self.convertByMoviepy(self.videoFile.text(),self.gifFile.text())
self.setEnabled(True)

3.3、实现方法convertByMoviepy

方法convertByMoviepy就是取界面相关设置调用moviepy对应方法完成文件转换,为了确保转换顺利,对相关参数进行了校验,如起止位置和fps必须是整数,如果终止位置不为0则必须大于起始位置。最后就是执行视频文件加载和转换,代码可以参考上面moviepy简介部分。

3.4、重定向输出信息到信息输出历史窗proccessInf

信息输出历史窗proccessInf为一个QTextBrowser对象,要将所有print输出信息到该历史窗,需要完成如下工作:

  1. 在构造方法中备份标准输出sys.stdout
  2. 构建承接输出信息的对象赋值给sys.stdout

    承接输出对象必须是一个类似文件io的对象,Python判断对象是否支持文件IO,是个典型的鸭子类型处理方式,就是看对象是否实现了读写方法,由于标准输出无需读只需写,因此只要实现了write方法即可。

    在本工具的实现方法内,老猿将标准输出指向了主窗口,因此在主窗口中实现了write方法,在write方法中将输出信息追加显示到proccessInf中、将最新信息显示到“最近输出信息”后的currentInf标签上。

    但在此需要注意,输出到proccessInf中的信息在程序输出过程中不会即时显示,导致给人的感觉是没有输出一样,为了确保输出信息即时显示在proccessInf窗口中,需要主动调用应用的processEvents方法。

    同时为了确保信息可对比跟踪,将重定向的信息使用备份的标准输出进行了输出
重定向参考代码如下:
class mainWin(QtWidgets.QWidget,ui_mainWin.Ui_mainWin):
def __init__(self):
super().__init__()
self.setupUi(self)
self.stdoutbak = sys.stdout
self.stderrbak = sys.stderr
sys.stdout = self def write(self,info):
self.proccessInf.insertPlainText(info)
if len(str):self.currentInf.setText(str)
QtWidgets.qApp.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents|QtCore.QEventLoop.ExcludeSocketNotifiers)
self.stdoutbak.write(info)

3.5、运行界面截图及动图



广告

老猿关于PyQt的付费专栏《使用PyQt开发图形界面Python应用》只需要9.9元,该部分与第十五章的内容基本对应,但同样内容在付费专栏上总体来说更详细、案例更多。本节内容对应付费专栏的《第三十三章、PyQt+moviepy实现的MP4视频转gif工具》。如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

老猿Python,跟老猿学Python!

第15.40节、PyQt(Python+Qt)实战:moviepy实现MP4视频转gif动图的工具的更多相关文章

  1. 第15.25节 PyQt(Python+Qt)入门学习:Model/View开发实战--使用QTableView展示Excel文件内容

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 在前面的订阅专栏<第十九章.Model/View开发:QTableView的功能及属 ...

  2. 第15.38节 PyQt(Python+Qt)入门学习:containers容器类部件QDockWidget停靠窗功能详解

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 QDockWidget类提供了一个可以停靠在QMainWin ...

  3. 第15.37节 PyQt(Python+Qt)入门学习:containers容器类部件QMdiArea多文档界面部件详解及编程开发案例

    专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.引言 老猿在前期学习PyQt相关知识时,对每个组件的属性及方法都研 ...

  4. 第15.28节 PyQt(Python+Qt)入门学习:Model/View架构中的便利类QTableWidget详解

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.引言 表格部件为应用程序提供标准的表格显示工具,在表格内可以管理基于行和列的数据项,表格中的最大 ...

  5. 第15.18节 PyQt(Python+Qt)入门学习:Model/View架构中视图Item Views父类详解

    老猿Python博文目录 老猿Python博客地址 一.概述 在PyQt图形界面中,支持采用Model/View架构实现数据和界面逻辑分离,其中Model用于处理数据存储,View用于界面数据展现,当 ...

  6. 第15.13节 PyQt(Python+Qt)入门学习:Qt Designer的Spacers部件详解

    一. 引言 在Designer的部件栏中,有两种类型的Spacers部件,下图中上面布局中为一个水平间隔部件(按钮1和按钮2之间的部件),下面布局中为一个垂直间隔部件(按钮3和4之间),如图: 这两种 ...

  7. 第15.33节 PyQt(Python+Qt)入门学习:containers容器类部件QTabWidget选项窗部件简介

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...

  8. 第15.31节 PyQt(Python+Qt)入门学习:containers容器类部件GroupBox分组框简介

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 容器部件就是可以在部件内放置其他部件的部件,在Qt Designer中可以使用的容器部件有 ...

  9. 第15.29节 PyQt(Python+Qt)入门学习:containers容器类部件QScrollArea滚动区域详解

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 Scroll Area提供了一个呈现在其他部件上的可滚动区域视图,滚动区域用于显示框架内的 ...

随机推荐

  1. 【SpringBoot】07.SpringBoot文件上传

    SpringBoot文件上传 1.编写html文件在classpath下的static中 <!DOCTYPE html> <html> <head> <met ...

  2. 分布式文档存储数据库之MongoDB副本集

    前文我们聊到了mongodb的索引的相关作用和介绍以及索引的管理,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13950287.html:今天我们来聊下mon ...

  3. Java 实现输入公历日期输出农历日期、生肖、天干地支、节日、节气等信息

    最近的工作中客户要求前台页面展示日历,日历内容包括:农历年月日日.公历年月日.生肖.天干地支.农历节日.公历节日.24节气等信息,之前在网上查找资料关于Java实现方面的文章不少,但是大多数针对节气. ...

  4. JS如何判断表单中用户选择哪个哪个选项?

    JS如何判断表单中用户选择哪个哪个选项? HTML代码: <form name="form1" onsubmit="return foo();"> ...

  5. 牛客网-C++-2020.9.2

    1. for循环语句能够被改写成(D)语句 A. 复合 B. if C. switch D. while 解析: for循环可以写成while控制循环的次数,同时也可以被改写成do while语句 2 ...

  6. orphan sockets

    orphan sockets 介绍一下什么是 orphan sockets,简单来说就是该 socket 不与任何一个文件描述符相关联.例如,当应用调用 close() 关闭一个链接时,此时该 soc ...

  7. 45. 跳跃游戏 II

    给定一个非负整数数组,你最初位于数组的第一个位置. 数组中的每个元素代表你在该位置可以跳跃的最大长度. 你的目标是使用最少的跳跃次数到达数组的最后一个位置. 示例: 输入: [2,3,1,1,4]输出 ...

  8. innodb为什么需要doublewrite(转)

    InnoDB的page size默认是16KB,而操作系统的一个block size是4KB,磁盘io block则更小.那么InnoDB的page刷到磁盘上要写4个操作系统block,在极端情况下( ...

  9. Android 架构组件-Lifecycle、LiveData、ViewModel

    Lifecycle Lifecycle组件包括LifecycleOwner.LifecleObserver,能方便监听Activity或者Fragment的生命周期. 步骤: 1.实现Lifecycl ...

  10. 运维和shell

    什么是运维 术语名词 IDC--(Internet Data Center)互联网数据中心,主要服务包括整机租用.服务器托管.机柜租用.机房租用.专线接入和网络管理服务等.广义上的IDC业务,实际上就 ...