zoukankan      html  css  js  c++  java
  • Pyqt 音视频播放器

    在寻找如何使用Pyqt做一个播放器时首先找到的是openCV2

    openCV2 貌似太强大了,各种关于图像处理的事情它都能完成,如 读取摄像头、图像识别、人脸识别、  图像灰度处理 、 播放视频等,强大的让你想不到!

    openCV2 播放视频也很简单:

     1 #coding=utf-8
     2 
     3 import cv2.cv as cv
     4 filename = "cn.avi"
     5 win_name = "video player"
     6 capture = cv.CaptureFromFile(filename)
     7 cv.NamedWindow(win_name, cv.CV_WINDOW_AUTOSIZE)
     8 
     9 # 定义一个无限循环
    10 while 1:
    11 
    12        # 每次从视频数据流框架中抓取一帧图片
    13     image = cv.QueryFrame(capture)
    14 
    15     # 将图片显示在特定窗口上
    16     cv.ShowImage(win_name, image)
    17 
    18     # 当安县Esc键时退出循环
    19     c = cv.WaitKey(33)
    20     if c == 27:
    21         break
    22 
    23 # 退出循环后销毁显示窗口
    24 cv.DestroyWindow(win_name)

    效果:

    在这里也提供以些openCV的信息

    下载地址:http://opencv.org/downloads.html      我使用的版本(V2.4.10) time:2015-02-10

    下载完成后解压文件,找到opencv目录下的build-->python->cv2.pyd, 复制cv2.pyd到python的安装目录,此时运行脚本会报错,因为还要安装numpy,下载地址:https://pypi.python.org/pypi/numpy/1.9.1

    再次运行不报错了但播放不了视频文件,为什么呢? 因为缺少解码器下载video codec解码器,http://www.xvidmovies.com/codec/ 

    现在运行就OK了!

    关于更多的openCV信息参考:

     http://docs.opencv.org/trunk/doc/py_tutorials/py_gui/py_video_display/py_video_display.html#display-video

    http://blog.sina.com.cn/s/blog_5562b0440102uw7g.html

    -------------------------------------------------------------------------------

    言归正传, 我们这里要讲的是如何用Pyqt 做一个音视频播放器。

    使用openCV2播放视频,但openCV2只提供图像处理,没有音频处理,所以即使Pyqt集成openCV2也只能播放视频而没有声音。

    现在我们使用Phonon 来完成这个功能。 话说 Phonon不属于QT, 是QT集成了Phonon

    下面我们来讲讲用Phonon实现的过程。

    在上一篇我转载过一篇关于Phonon的文章http://www.cnblogs.com/dcb3688/p/4283222.html

    里面介绍了Phonon的结构、安装  、使用以及详细的例子,今天我们就在做一个例子

    第一步:创建UI

    老方法,先创建UI文件

    video.ui  XML代码:

      1 <?xml version="1.0" encoding="UTF-8"?>
      2 <ui version="4.0">
      3  <class>videofrom</class>
      4  <widget class="QWidget" name="videofrom">
      5   <property name="geometry">
      6    <rect>
      7     <x>0</x>
      8     <y>0</y>
      9     <width>880</width>
     10     <height>572</height>
     11    </rect>
     12   </property>
     13   <property name="windowTitle">
     14    <string>Form</string>
     15   </property>
     16   <widget class="QWidget" name="verticalLayoutWidget_2">
     17    <property name="geometry">
     18     <rect>
     19      <x>10</x>
     20      <y>10</y>
     21      <width>861</width>
     22      <height>551</height>
     23     </rect>
     24    </property>
     25    <layout class="QVBoxLayout" name="verticalLayout_main" stretch="2">
     26     <item>
     27      <layout class="QVBoxLayout" name="verticalLayout" stretch="8,1,1">
     28       <item>
     29        <layout class="QVBoxLayout" name="verticalLayout_player" stretch="">
     30         <property name="spacing">
     31          <number>6</number>
     32         </property>
     33        </layout>
     34       </item>
     35       <item>
     36        <widget class="Phonon::SeekSlider" name="seekSlider"/>
     37       </item>
     38       <item>
     39        <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0,2,0,5,0,2">
     40         <item>
     41          <widget class="QPushButton" name="BtnOpen">
     42           <property name="contextMenuPolicy">
     43            <enum>Qt::CustomContextMenu</enum>
     44           </property>
     45           <property name="toolTip">
     46            <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;选择文件,右键选择音频or 视频&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
     47           </property>
     48           <property name="text">
     49            <string>选择文件</string>
     50           </property>
     51          </widget>
     52         </item>
     53         <item>
     54          <widget class="Line" name="line">
     55           <property name="orientation">
     56            <enum>Qt::Vertical</enum>
     57           </property>
     58          </widget>
     59         </item>
     60         <item>
     61          <layout class="QHBoxLayout" name="horizontalLayout_btn"/>
     62         </item>
     63         <item>
     64          <widget class="Line" name="line_2">
     65           <property name="orientation">
     66            <enum>Qt::Vertical</enum>
     67           </property>
     68          </widget>
     69         </item>
     70         <item>
     71          <widget class="Phonon::VolumeSlider" name="volumeSlider"/>
     72         </item>
     73         <item>
     74          <widget class="Line" name="line_3">
     75           <property name="orientation">
     76            <enum>Qt::Vertical</enum>
     77           </property>
     78          </widget>
     79         </item>
     80         <item>
     81          <widget class="QLCDNumber" name="lcdNumber"/>
     82         </item>
     83        </layout>
     84       </item>
     85      </layout>
     86     </item>
     87    </layout>
     88   </widget>
     89  </widget>
     90  <customwidgets>
     91   <customwidget>
     92    <class>Phonon::SeekSlider</class>
     93    <extends>QWidget</extends>
     94    <header location="global">phonon/seekslider.h</header>
     95   </customwidget>
     96   <customwidget>
     97    <class>Phonon::VolumeSlider</class>
     98    <extends>QWidget</extends>
     99    <header location="global">phonon/volumeslider.h</header>
    100   </customwidget>
    101  </customwidgets>
    102  <resources/>
    103  <connections/>
    104 </ui>

    转换为py文件

    video.py :

      1 # -*- coding: utf-8 -*-
      2 
      3 # Form implementation generated from reading ui file 'video.ui'
      4 #
      5 # Created: Thu Feb 12 17:25:10 2015
      6 #      by: PyQt4 UI code generator 4.10.3
      7 #
      8 # WARNING! All changes made in this file will be lost!
      9 
     10 from PyQt4 import QtCore, QtGui
     11 
     12 try:
     13     _fromUtf8 = QtCore.QString.fromUtf8
     14 except AttributeError:
     15     def _fromUtf8(s):
     16         return s
     17 
     18 try:
     19     _encoding = QtGui.QApplication.UnicodeUTF8
     20     def _translate(context, text, disambig):
     21         return QtGui.QApplication.translate(context, text, disambig, _encoding)
     22 except AttributeError:
     23     def _translate(context, text, disambig):
     24         return QtGui.QApplication.translate(context, text, disambig)
     25 
     26 class Ui_videofrom(object):
     27     def setupUi(self, videofrom):
     28         videofrom.setObjectName(_fromUtf8("videofrom"))
     29         videofrom.resize(880, 572)
     30         self.verticalLayoutWidget_2 = QtGui.QWidget(videofrom)
     31         self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 10, 861, 551))
     32         self.verticalLayoutWidget_2.setObjectName(_fromUtf8("verticalLayoutWidget_2"))
     33         self.verticalLayout_main = QtGui.QVBoxLayout(self.verticalLayoutWidget_2)
     34         self.verticalLayout_main.setMargin(0)
     35         self.verticalLayout_main.setObjectName(_fromUtf8("verticalLayout_main"))
     36         self.verticalLayout = QtGui.QVBoxLayout()
     37         self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
     38         self.verticalLayout_player = QtGui.QVBoxLayout()
     39         self.verticalLayout_player.setObjectName(_fromUtf8("verticalLayout_player"))
     40         self.verticalLayout.addLayout(self.verticalLayout_player)
     41         self.seekSlider = phonon.Phonon.SeekSlider(self.verticalLayoutWidget_2)
     42         self.seekSlider.setObjectName(_fromUtf8("seekSlider"))
     43         self.verticalLayout.addWidget(self.seekSlider)
     44         self.horizontalLayout = QtGui.QHBoxLayout()
     45         self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
     46         self.BtnOpen = QtGui.QPushButton(self.verticalLayoutWidget_2)
     47         self.BtnOpen.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
     48         self.BtnOpen.setObjectName(_fromUtf8("BtnOpen"))
     49         self.horizontalLayout.addWidget(self.BtnOpen)
     50         self.line = QtGui.QFrame(self.verticalLayoutWidget_2)
     51         self.line.setFrameShape(QtGui.QFrame.VLine)
     52         self.line.setFrameShadow(QtGui.QFrame.Sunken)
     53         self.line.setObjectName(_fromUtf8("line"))
     54         self.horizontalLayout.addWidget(self.line)
     55         self.horizontalLayout_btn = QtGui.QHBoxLayout()
     56         self.horizontalLayout_btn.setObjectName(_fromUtf8("horizontalLayout_btn"))
     57         self.horizontalLayout.addLayout(self.horizontalLayout_btn)
     58         self.line_2 = QtGui.QFrame(self.verticalLayoutWidget_2)
     59         self.line_2.setFrameShape(QtGui.QFrame.VLine)
     60         self.line_2.setFrameShadow(QtGui.QFrame.Sunken)
     61         self.line_2.setObjectName(_fromUtf8("line_2"))
     62         self.horizontalLayout.addWidget(self.line_2)
     63         self.volumeSlider = phonon.Phonon.VolumeSlider(self.verticalLayoutWidget_2)
     64         self.volumeSlider.setObjectName(_fromUtf8("volumeSlider"))
     65         self.horizontalLayout.addWidget(self.volumeSlider)
     66         self.line_3 = QtGui.QFrame(self.verticalLayoutWidget_2)
     67         self.line_3.setFrameShape(QtGui.QFrame.VLine)
     68         self.line_3.setFrameShadow(QtGui.QFrame.Sunken)
     69         self.line_3.setObjectName(_fromUtf8("line_3"))
     70         self.horizontalLayout.addWidget(self.line_3)
     71         self.lcdNumber = QtGui.QLCDNumber(self.verticalLayoutWidget_2)
     72         self.lcdNumber.setObjectName(_fromUtf8("lcdNumber"))
     73         self.horizontalLayout.addWidget(self.lcdNumber)
     74         self.horizontalLayout.setStretch(0, 1)
     75         self.horizontalLayout.setStretch(2, 2)
     76         self.horizontalLayout.setStretch(4, 5)
     77         self.horizontalLayout.setStretch(6, 2)
     78         self.verticalLayout.addLayout(self.horizontalLayout)
     79         self.verticalLayout.setStretch(0, 8)
     80         self.verticalLayout.setStretch(1, 1)
     81         self.verticalLayout.setStretch(2, 1)
     82         self.verticalLayout_main.addLayout(self.verticalLayout)
     83         self.verticalLayout_main.setStretch(0, 2)
     84 
     85         self.retranslateUi(videofrom)
     86         QtCore.QMetaObject.connectSlotsByName(videofrom)
     87 
     88     def retranslateUi(self, videofrom):
     89         videofrom.setWindowTitle(_translate("videofrom", "Form", None))
     90         self.BtnOpen.setToolTip(_translate("videofrom", "<html><head/><body><p>选择文件,右键选择音频or 视频</p></body></html>", None))
     91         self.BtnOpen.setText(_translate("videofrom", "选择文件", None))
     92 
     93 from PyQt4 import phonon
     94 
     95 if __name__ == "__main__":
     96     import sys
     97     app = QtGui.QApplication(sys.argv)
     98     videofrom = QtGui.QWidget()
     99     ui = Ui_videofrom()
    100     ui.setupUi(videofrom)
    101     videofrom.show()
    102     sys.exit(app.exec_())

    运行效果:

    看起来很乱的布局是吧,在这理因为的是layout里面的setStretch 方法,该方法可以按照百分比的比例来显示控件的坐标,空的地方我们预留了一个 QToolBar 和  VideoWidget。

    为什么是VideoWidget 而不是VideoPlayer 呢? 因为VideoPlayer 提供的方法太少。只有播放 暂停 停止等,而VideoWidget 提供了更多的方法和功能。

    在Qt designer中我一直在找Phonon的VideoWidget 控件一直找不到,只有一个VideoPlayer, 所以只能在逻辑页面 addWidget了。

    第二步: 编写逻辑页面

    细节不讲了,直接贴出代码:

      1 # -*- coding: utf-8 -*-
      2 
      3 
      4 
      5 from PyQt4 import QtCore, QtGui
      6 from PyQt4 import phonon
      7 from video import Ui_videofrom
      8 import sys
      9 import icoqrc
     10 
     11 class mainvideo(QtGui.QWidget):
     12     def __init__(self):
     13         super(mainvideo, self).__init__()
     14         self.UI=Ui_videofrom()
     15         self.UI.setupUi(self)
     16         self.setWindowTitle(u'Pyqt 音视频播放器')
     17         self.setWindowIcon(QtGui.QIcon(':flash.ico'))
     18         self.mediaObject = phonon.Phonon.MediaObject(self)
     19         self.mediaObject.stateChanged.connect(self.stateChanged)  # 对象改变时
     20         self.mediaObject.tick.connect(self.tick)  # 链接到时间
     21         self.setupUi()
     22         self.connect(self.UI.BtnOpen, QtCore.SIGNAL('customContextMenuRequested (const QPoint&)'), self.openright)
     23         self.connect(self.UI.BtnOpen, QtCore.SIGNAL('clicked()'), self.alert)
     24 
     25         self.UI.videoPlayer =phonon.Phonon.VideoWidget(self)
     26         self.UI.verticalLayout_player.addWidget(self.UI.videoPlayer)
     27 
     28 
     29     def setupUi(self):
     30         self.playAction = QtGui.QAction(self.style().standardIcon(QtGui.QStyle.SP_MediaPlay), "Play",self, shortcut="Ctrl+P", enabled=False, triggered=self.mediaObject.play)
     31         self.pauseAction = QtGui.QAction(self.style().standardIcon(QtGui.QStyle.SP_MediaPause), "Pause", self, shortcut="Ctrl+A", enabled=False, triggered=self.mediaObject.pause)
     32         self.stopAction = QtGui.QAction(self.style().standardIcon(QtGui.QStyle.SP_MediaStop), "Stop",  self, shortcut="Ctrl+S", enabled=False,triggered=self.mediaObject.stop)
     33         # 添加工具条  包含 播放, 暂停, 重新开始
     34         bar = QtGui.QToolBar()
     35         bar.addAction(self.playAction)
     36         bar.addAction(self.pauseAction)
     37         bar.addAction(self.stopAction)
     38         self.UI.horizontalLayout_btn.addWidget(bar)
     39         #  显示LED时间
     40         palette = QtGui.QPalette()
     41         palette.setBrush(QtGui.QPalette.Light, QtCore.Qt.darkGray)
     42         self.timeLcd = self.UI.lcdNumber
     43         self.timeLcd.setPalette(palette)
     44         self.timeLcd.display('00:00')
     45         self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)  # PyQT禁止窗口最大化按钮:
     46         self.setFixedSize(self.width(), self.height())   # PyQT禁止调整窗口大小:
     47 
     48 
     49 
     50 
     51 
     52     # button 右键菜单
     53     def openright(self):
     54         popMenu = QtGui.QMenu()
     55         popMenu.addAction(QtGui.QAction(QtGui.QIcon(':chrome.ico'), u'音频文件', self,  enabled=True, triggered=self.openaudio))
     56         popMenu.addAction(QtGui.QAction(QtGui.QIcon(':myfavicon.ico'), u'视频文件', self,  enabled=True, triggered=self.openvideo))
     57         popMenu.exec_(QtGui.QCursor.pos())
     58 
     59 
     60     # 选择打开音频
     61     def openaudio(self):
     62         file = self.addFiles('audio')
     63         self.mediaObject.setCurrentSource(phonon.Phonon.MediaSource(file))
     64         # 初始化音频的输出按钮
     65         self.audioOutput = phonon.Phonon.AudioOutput(phonon.Phonon.VideoCategory, self)
     66         phonon.Phonon.createPath(self.mediaObject, self.audioOutput)
     67         # 连接到音量
     68         self.UI.volumeSlider.setAudioOutput(self.audioOutput)
     69         self.UI.seekSlider.setMediaObject(self.mediaObject)
     70         self.mediaObject.play()
     71         
     72 
     73     # 选择打开视频文件
     74     def openvideo(self):
     75         file = self.addFiles('video')
     76         self.mediaObject.setCurrentSource(phonon.Phonon.MediaSource(file))   # 加载当前的源文件
     77         phonon.Phonon.createPath(self.mediaObject, self.UI.videoPlayer)
     78         # 初始化视频输出
     79         self.UI.videoPlayer.setAspectRatio(phonon.Phonon.VideoWidget.AspectRatioAuto)
     80         # 初始化音频的输出按钮
     81         self.audioOutput  =phonon.Phonon.AudioOutput(phonon.Phonon.VideoCategory, self)
     82         phonon.Phonon.createPath(self.mediaObject, self.audioOutput)
     83         # 连接到音量按钮
     84         self.UI.volumeSlider.setAudioOutput(self.audioOutput)
     85         self.UI.seekSlider.setMediaObject(self.mediaObject)
     86         self.mediaObject.play()
     87 
     88 
     89 
     90     def alert(self):
     91         QtGui.QMessageBox.question(self, (u'提示'),(u'请右键选择打开文件!'),QtGui.QMessageBox.Ok)
     92         
     93     # 选择文件
     94     def addFiles(self,filetype='all'):
     95         if filetype=='audio':
     96             tips=u'选择音频文件'
     97             expand = 'Image Files(*.mp3 *.wav)'
     98         elif filetype=='video':
     99             tips = u'选择视频文件'
    100             expand = 'Image Files(*.mp4 *.avi)'
    101         else:
    102             tips =u'请选择播放文件'
    103             expand = 'Image Files(*.mp3 *.wav *.mp4 *.avi)'
    104         # getOpenFileName  只能选择一个    getOpenFileNames  可多个选择
    105         files = QtGui.QFileDialog.getOpenFileName(self, tips,QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.MusicLocation), expand)    # QStringList getOpenFileNames (QWidget parent = None, QString caption = QString(), QString directory = QString(), QString filter = QString(), Options options = 0)
    106         
    107         if not files:
    108             return ''
    109         
    110         return files
    111     # 改变状态
    112     def stateChanged(self, newState):
    113 
    114         if newState == phonon.Phonon.ErrorState:
    115             if self.mediaObject.errorType() == phonon.Phonon.FatalError:
    116                 QtGui.QMessageBox.warning(self, "Fatal Error",
    117                         self.mediaObject.errorString())
    118             else:
    119                 QtGui.QMessageBox.warning(self, "Error",
    120                         self.mediaObject.errorString())
    121 
    122         elif newState == phonon.Phonon.PlayingState:
    123             self.playAction.setEnabled(False)
    124             self.pauseAction.setEnabled(True)
    125             self.stopAction.setEnabled(True)
    126 
    127         elif newState == phonon.Phonon.StoppedState:
    128             self.stopAction.setEnabled(False)
    129             self.playAction.setEnabled(True)
    130             self.pauseAction.setEnabled(False)
    131             self.timeLcd.display("00:00")
    132 
    133 
    134         elif newState == phonon.Phonon.PausedState:
    135             self.pauseAction.setEnabled(False)
    136             self.stopAction.setEnabled(True)
    137             self.playAction.setEnabled(True)
    138     # 时间显示
    139     def tick(self, time):
    140         displayTime = QtCore.QTime(0, (time / 60000) % 60, (time / 1000) % 60)
    141         self.timeLcd.display(displayTime.toString('mm:ss'))
    142 
    143 
    144 
    145     def keyPressEvent(self, event):
    146          if event.key() ==QtCore.Qt.Key_Escape:
    147              self.close()
    148 
    149 
    150 if __name__ == '__main__':
    151     app=QtGui.QApplication(sys.argv)
    152     mainapp = mainvideo()
    153     app.setQuitOnLastWindowClosed(True)
    154     mainapp.show()
    155     sys.exit(app.exec_())

    第三步: 运行和排除问题

    按理来说,应该是先排除问题再运行。

    在完成这个Pyqt的播放器中过程中遇到了N多问题

    一个大问题是:没有声音和视频画面, 问题google后很简单: 没有解码器! 下载视频解码器喽!

    好!现在我们运行看效果:

     

  • 相关阅读:
    java中如何制作可双击执行的程序--jar打包工具的使用
    GUI菜单——菜单条、菜单、子条目之间关系
    设计模式——单例模式(饿汉式、懒汉式)
    深入理解利用new创建对象的执行过程以Person p=new Person("张三",20);为例
    构造代码块、构造函数、this执行顺序
    OpenGL 动画的制作
    UE4制作插件的插件神器pluginCreator
    3dmax中cs骨骼教程
    如何解决 应用程序无法启动 因为应用程序的并行配置不正确 问题
    如何自学游戏引擎的开发
  • 原文地址:https://www.cnblogs.com/dcb3688/p/4290315.html
Copyright © 2011-2022 走看看