基于PyQt5开发一个视频转GIF的小应用

 pyqt5是一套Python绑定Digia QT5应用的框架。它可用于Python 2和3

01

什么是pyqt5

pyqt5是一套Python绑定Digia QT5应用的框架。它可用于Python 2和3。本教程使用Python 3。Qt库是最强大的GUI库之一。pyqt5的官方网站http://www.riverbankcomputing.co.uk/news。

pyqt5做为Python的一个模块,它有620多个类和6000个函数和方法。这是一个跨平台的工具包,它可以运行在所有主要的操作系统,包括UNIX,Windows,Mac OS。pyqt5是双重许可。开发者可以在GPL和商业许可之间进行选择。

pyqt5的类别分为几个模块,包括以下:

QtCore:包含了核心的非GUI功能。此模块用于处理时间、文件和目录、各种数据类型、流、URL、MIME类型、线程或进程。

QtGui:包含类窗口系统集成、事件处理、二维图形、基本成像、字体和文本。
qtwidgets:模块包含创造经典桌面风格的用户界面提供了一套UI元素的类。
QtMultimedia:包含的类来处理多媒体内容和API来访问相机和收音机的功能。
Qtbluetooth:模块包含类的扫描设备和连接并与他们互动。描述模块包含了网络编程的类。这些类便于TCP和IP和UDP客户端和服务器的编码,使网络编程更容易和更便携。
Qtpositioning:包含类的利用各种可能的来源,确定位置,包括卫星、Wi-Fi、或一个文本文件。
Enginio:模块实现了客户端库访问Qt云服务托管的应用程序运行时。
Qtwebsockets:模块包含实现WebSocket协议类。
QtWebKit:包含一个基于Webkit2图书馆Web浏览器实现类。
Qtwebkitwidgets:包含的类的基础webkit1用于qtwidgets应用Web浏览器的实现。
QtXml:包含与XML文件的类。这个模块为SAX和DOM API提供了实现。
QtSvg:模块提供了显示SVG文件内容的类。可伸缩矢量图形(SVG)是一种描述二维图形和图形应用的语言。
QtSql:模块提供操作数据库的类。
QtTest:使pyqt5应用程序的单元测试

02


pyqt5环境搭建

1、安装pyqt5

我使用的Anaconda3,直接在Anaconda3 Prompt输入pip install pyqt5,我这边之前已经安装过,有如下提示表示安装成功

2、将QtDesigner和PyUIC链接到PyCharm的外部工具库

QtDesigner与PyCharm的链接见下图所示:点击PyCharm的File->Settings->Tools->External tools打开外部工具界面,点‘+'号进入添加外部工具界面。在‘Name'处输入工具名称,这个名称可以随便取,只要自己清楚就行,我这里写的是Qt designer。然后,找到安装的designer.exe所在的路径(一般在python安装目录下的Library\bin文件夹里),将其路径复制到‘Programs'处,注意要包含designer.exe的文件名。在Working directory处设置变量$ProjectFileDir$,就是自己的工作路径,qtdesigner生成的ui文件会默认保存在该路径。‘Arguments'不用设置,确认即可

基于PyQt5开发一个视频转GIF的小应用_第1张图片

接下来,按同样的方法添加pyuic,pyuic用于将qtdesigner生成的.ui文件转换成python可以识别的.py文件。其设置过程如下图所示,Programs处输入python.exe所在的路径和文件名,Arguments处输入:

-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py

Working directory处输入:$FileDir$

基于PyQt5开发一个视频转GIF的小应用_第2张图片

设置完成后就可以在PyCharm的Tools->External Tools菜单下看到我们新添加的工具了。

基于PyQt5开发一个视频转GIF的小应用_第3张图片

QtDesigner打开后会自动弹出新建窗口的对话框,如果没有弹出的话可以单击File->New来打开该对话框。如下图所示,选择Main Windows,然后单击Create来创建一个主窗口。

基于PyQt5开发一个视频转GIF的小应用_第4张图片

QtDesigner打开后的界面如下图所示,我用红框标出了四个常用的区域,左上角的区域显示了我们界面窗口所有使用的控件列表和对应的名称;左下角区域是所有可用的控件库;中间是工作区,我们可以将控件从控件库拖拽到工作区来组合我们的程序界面;右侧区域为控件属性设置区,在我们单击选中某一个控件后,它的属性就会在这里显示出来,我们也可以在这里对控件的属性进行修改。

在左下角的控件菜单中找到Tool Button,用鼠标左键将其拖到中间区域,然后单击File->Save as,将当前界面保存到我们刚创建的PyQtTest项目文件夹下,文件名设为QtTest.ui。

保存完成后,回到PyCharm中,可以看到我们的PyQtTest项目下多了一个QtTest.ui文件。鼠标右键单击该文件调出右键菜单,单击External tools->PyUIC,程序会调用pyuic,将ui文件转换为py文件,执行完成后就会在该项目中生成一个QtTest.py文件了。

打开QTest.py文件会发现,里面只有一个Ui_MainWindow类,没有主程序,我们需要自己编写一个主程序来调用Ui_MainWindow类。

由于QTest.py是通过pyuic自动生成的,当我们在qtdesigner中对程序界面进行修改,并重新生成QtTest.py时,里面原来的内容会被全部覆盖掉,因此我们尽量不要在QTest.py中添加自己的代码,而是新建一个py文件来调用QTest.py中的类,将自己的代码都放在新创建的文件中。

基于PyQt5开发一个视频转GIF的小应用_第5张图片

接下来右键单击PyQtTest项目,选择New->Python File新建一个Python文件,文件名设为'QtestUi.py',打开该文件输入如下代码,然后运行QtestUi.py。

from QTest import Ui_MainWindow
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow




class CamShow(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(CamShow, self).__init__(parent)
        self.setupUi(self)




if __name__ == '__main__':
    app = QApplication(sys.argv)
    ui = CamShow()
    ui.show()
    sys.exit(app.exec_())

基于PyQt5开发一个视频转GIF的小应用_第6张图片

03


利用pyqt5开发一个MP4转GIF的小工具

1、按照上述步骤,利用QtDesigner生成如下的界面:

基于PyQt5开发一个视频转GIF的小应用_第7张图片

2、UI初始化如下

class GifConversioGUI(QMainWindow):


    def __init__(self):
        super().__init__()
        self.icon = "icon.png"
        self.title = "Vedio2GIF"
        self.prompt = QLabel(
            '请选择你需要转换的视频')
        self.prompt.setAlignment(Qt.AlignCenter)


        self.convertButton = QPushButton("开始转换")
        self.convertButton.setEnabled(False)
        self.convertButton.clicked.connect(self.convert)


        self.clip = ''


        # Create new action
        self.openAction = QAction(self.style().standardIcon(
            QStyle.SP_DialogOpenButton), '&Open', self)
        self.openAction.setShortcut('Ctrl+O')
        self.openAction.setStatusTip('Open movie')
        self.openAction.triggered.connect(self.openFile)


        # Create exit action
        self.exitAction = QAction(self.style().standardIcon(
            QStyle.SP_DialogCancelButton), '&Exit', self)
        self.exitAction.setShortcut('Ctrl+Q')
        self.exitAction.setStatusTip('Exit application')
        self.exitAction.triggered.connect(self.close)


        # Create about action
        self.aboutAction = QAction(self.style().standardIcon(
            QStyle.SP_FileDialogInfoView), '&About', self)
        self.aboutAction.triggered.connect(self.about)


        # Create menu bar and add action
        self.fileMenu = QMenu("&File", self)
        self.fileMenu.addAction(self.openAction)
        self.fileMenu.addSeparator()
        self.fileMenu.addAction(self.exitAction)


        self.aboutMenu = QMenu("&About", self)
        self.aboutMenu.addAction(self.aboutAction)


        self.menuBar().addMenu(self.fileMenu)
        self.menuBar().addMenu(self.aboutMenu)


        self.setWindowIcon(QIcon(self.icon))
        self.setWindowTitle(self.title)






        # 创建5个单行文本框
        self.LineEditfps = QLineEdit()
        self.LineEditStartime = QLineEdit()
        self.LineEditEndtime = QLineEdit()
        self.LineEditWidth = QLineEdit()
        self.LineEditHeight = QLineEdit()




        # 设置提示输入文本
        self.LineEditfps.setPlaceholderText("请填写转换的gif的fps")
        self.LineEditStartime.setPlaceholderText("请填写需要截取视频的开始时间,单位为秒")
        self.LineEditEndtime.setPlaceholderText("请填写需要截取视频的结束时间,单位为秒")
        self.LineEditWidth.setPlaceholderText("请填写需要转换gif图片的宽度,单位为像素")
        self.LineEditHeight.setPlaceholderText("请填写需要转换gif图片的高度,单位为像素")




        # 设置显示效果
        self.LineEditfps.setEchoMode(QLineEdit.Normal)
        self.LineEditStartime.setEchoMode(QLineEdit.Normal)
        self.LineEditEndtime.setEchoMode(QLineEdit.Normal)
        self.LineEditWidth.setEchoMode(QLineEdit.Normal)
        self.LineEditHeight.setEchoMode(QLineEdit.Normal)


        wid = QWidget(self)
        self.setCentralWidget(wid)


        controlLayout = QVBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(self.LineEditfps)
        controlLayout.addWidget(self.LineEditStartime)
        controlLayout.addWidget(self.LineEditEndtime)
        controlLayout.addWidget(self.LineEditWidth)
        controlLayout.addWidget(self.LineEditHeight)
        controlLayout.addWidget(self.prompt)
        controlLayout.addWidget(self.convertButton)


        layout = QVBoxLayout()
        layout.addLayout(controlLayout)


        wid.setLayout(layout)
        self.resize(800, 600)

3、open文件的槽函数

    @pyqtSlot()
    def openFile(self):
        """Gets video file path from file dialogue, updates GUI accordingly"""


        # Open file dialogue for video selection
        options = QFileDialog.Options()
        fileName, _ = QFileDialog.getOpenFileName(
            self, 'Select a Video to Convert', '', 'Videos (*mov *mp4 *.gif)', options=options)


        # Update GUI if video selected
        if fileName != '':
            self.clip = fileName
            self.convertButton.setEnabled(True)
            video_type = fileName.split('/')[-1].split('.')[-1]
            video_title = fileName.split('/')[-1].split('.')[-2]
            self.prompt.setText(
                f"确定将 {video_title}.{video_type} 转换成 {video_title}.gif吗?请在选择视频后填写上述的参数")


4、转换button的槽函数:

主要是获取LineEdit输入的值,然后显示转换后的gif

    @pyqtSlot()
    def convert(self):


        QApplication.setOverrideCursor(Qt.WaitCursor)
        fps=(self.LineEditfps.text())
        start_time = (self.LineEditStartime.text())
        stop_time = (self.LineEditEndtime.text())
        width = (self.LineEditWidth.text())
        height = (self.LineEditHeight.text())


        makeGif(self.clip, '.gif',fps,start_time,stop_time,width,height)


        outputPath = os.path.splitext(os.path.abspath(self.clip))[0] + ".gif"
        self.gif = QMovie(outputPath)
        self.prompt.setMovie(self.gif)
        self.gif.start()
        QApplication.restoreOverrideCursor()


        self.convertButton.setEnabled(False)

5、具体的转换实现:

利用python库moviepy,来进行gif的转换。

def makeGif(clip, targetFormat,fps,start_time,stop_time,width,height):


    inputPath = os.path.abspath(clip)
    outputPath = os.path.splitext(inputPath)[0] + targetFormat




    fps = int(fps)
    start_time = int(start_time)
    stop_time = int(stop_time)
    width = int(width)
    height = int(height)


    content = mpy.VideoFileClip(inputPath)
    c1 = content.subclip((0,start_time),(0,stop_time)).resize((width,height))
    c1.write_gif(outputPath, fps=fps)

基本上上述5个步骤就可以实现这样一个简单的功能,但是这个仅仅是个demo,至少对于LineEditor的输入还得进行空值和数据类型的判断。有兴趣的小伙伴可以自行完善,设计完成后,验证效果如下:

基于PyQt5开发一个视频转GIF的小应用_第8张图片

04


利用pyinstaller打包整个应用

首先还是安装pyinstaller

pip install pyinstaller

然后在pycharm terminal输入打包命令

pyinstaller -F -w PyVideoToGifConverter.py 

PyInstaller部分参数的含义

-F 表示生成单个可执行文件
-w 表示去掉控制台窗口,这在GUI界面时非常有用。不过如果是命令行程序的话那就把这个选项删除吧!
-i 表示可执行文件的图标

PyInstaller注意点

1、有一些代码需要调用一些图片和资源文件的,这是不会自动导入的,
   需要你自己手动复制进去才行。不然exe文件运行时命令窗口会报错找不到这个文件。

2、当你使用错误的参数去打包或者打包到一半中断,等等此类运行到一半没了的情况。
   会导致你原来的py文件变成一个0KB的空文件。里面的代码会全部消失!!!
   所以以后需要有个良好的习惯,就是复制一份代码出来,用这个副本进行打包。
   并且参数出错,或者打错了导致失败时,检查下副本文件的py文件是否还存在再继续重新打包,
   不然打出来的就是空的文件,自然一直闪退,因为压根没内容。

3、写代码的时候应当有个良好的习惯,用什么函数导什么函数,不要上来import整个库,
   最后你会发现你一个100KB的代码打包出来有500MB,全是库

pyqt5的整个开发流程基本完成,相关代码如果大家有兴趣可以私信我。

听说关注公众号的都是大牛

基于PyQt5开发一个视频转GIF的小应用_第9张图片

你可能感兴趣的:(python,java,编程语言,web,软件测试)