PyQt5 ビデオ再生 -- QVideoWidget にビデオを表示

1. 機能概要
(1) QMediaPlayer は音声ファイルだけでなく、wmv や avi などの動画ファイルも再生できます。

2. 主な機能
(1) setMedia(QMediaContent): メディアリソースの指定;
(2) setPlaylist(): プレイリストの指定;
(3) setVideoOutput(QVideoWidget): ビデオ表示用のインターフェースコンポーネントの指定;
再構成パラメータ:
setVideoOutput(self) 、QVideoWidget)
setVideoOutput(self, QGraphicsVideoItem)
setVideoOutput(self, QAbstractVideoSurface)
(4) setNotifyInterval(1000):情報更新周期1000msを設定します。
(5) setFullScreen(True): フルスクリーンを設定します。

3. 主なクラス
(1) QVideoWidget は QWidget と QMediaBindableInterface を継承したクラスで、QWidget と似たクラ​​スですが、ビデオ画像を表示することができます。
(2) QGraphicsVideoItem は QGraphicsObject および QMediaBindableInterface から継承されたクラスで、Graphics View アーキテクチャのグラフィック項目であり、Graphics View アーキテクチャでビデオ画像を表示するために使用されます。
(3) QAbstractVideoSurface は QObject から直接継承したビデオ表示用の抽象クラスであり、ビデオ画面表示用の標準インターフェースを提供します。 デコードされたビデオ フレーム コンテンツのカスタム表示を実現するには、このクラスからクラスを継承する必要があります。

4. 詳細コード
この例では、QMediaPlayer を使用してビデオ ファイルを再生しQVideoWidget コンポーネントにビデオ画面を表示しますこの例の UI インターフェイスを図に示します。UI インターフェースの設計プロセスについてはあまり紹介しません。
ここに画像の説明を挿入
QVideoWidget を使用して画面を表示するビデオプレーヤー

ここに画像の説明を挿入
MainWindow.ui デザインの効果とレイアウト レベル

: コンポーネント パネルには QVideoWidget クラスはありません。QWidget コンポーネントはプロモーション メソッドによって QVideoWidget クラスに昇格する必要があります。コンポーネントを右クリックして、QWidget から QVideoWidget にプロモートします。
ここに画像の説明を挿入
コンポーネントタイプのプロモーションダイアログ

コンポーネントのプロモーション メソッドは、コンポーネントを既存の Qt クラスまたはカスタム クラスにプロモートできますが、プロモートされたクラスは基本クラスまたは下位レベルのクラスのサブクラスである必要があります。

具体的なコードは次のとおりです。

import sys
from PyQt5.QtWidgets import  QApplication, QMainWindow,QFileDialog
from PyQt5.QtCore import  pyqtSlot,QUrl,QDir, QFileInfo,Qt,QEvent
from PyQt5.QtGui import QIcon,QKeyEvent,QMouseEvent
from PyQt5.QtMultimedia import QMediaContent,QMediaPlayer
from ui_MainWindow import Ui_MainWindow

class QmyMainWindow(QMainWindow):
	def __init__(self, parent=None):
      super().__init__(parent)   #调用父类构造函数,创建窗体
      self.ui=Ui_MainWindow()    #创建UI对象
      self.ui.setupUi(self)      #构造UI界面

      self.player = QMediaPlayer(self)    #创建视频播放器
      self.player.setNotifyInterval(1000) #信息更新周期, ms
      self.player.setVideoOutput(self.ui.videoWidget) #视频显示组件
	
	  self.ui.videoWidget,installEventFilter(self) #事件过滤器
	
	  self.__duration = ""
	  self.__curPos = ""
     
      self.player.stateChanged.connect(self.do_stateChanged)
      self.player.positionChanged.connect(self.do_positionChanged)
      self.player.durationChanged.connect(self.do_durationChanged)

##  ==============自定义功能函数========================

##  ==============event处理函数==========================
   def closeEvent(self,event):  #窗体关闭时
   # 窗口关闭时不能自动停止播放,需手动停止
      if (self.player.state() == QMediaPlayer.PlayingState):
         self.player.stop()

   def eventFilter(self, watched, event):     ##事件过滤器
      if (watched != self.ui.videoWidget):
         return super().eventFilter(watched, event)

      #鼠标左键按下时,暂停或继续播放
      if event.type() == QEvent.MouseButtonPress:
         if event.button() == Qt.LeftButton:
            if self.player.state() == QMediaPlayer.PlayingState:
               self.player.pause()
            else:
               self.player.play()

      #全屏状态时,按ESC键退出全屏
      if event.type() == QEvent.KeyPress:
         if event.key() == Qt.Key_Escape:
            if self.ui.videoWidget.isFullScreen():
               self.ui.videoWidget.setFullScreen(False)
        
      return super().eventFilter(watched,event)

##  ==========由connectSlotsByName()自动连接的槽函数============        
   @pyqtSlot()    ##打开文件
   def on_btnOpen_clicked(self):
      curPath = QDir.currentPath()  #获取系统当前目录
      title = "选择视频文件" 
      filt = "视频文件(*.wmv *.avi);;所有文件(*.*)"
      fileName, flt = QFileDialog.getOpenFileName(self, title, curPath, filt)
      if (fileName == ""):
         return

      fileInfo = QFileInfo(fileName)
      baseName = fileInfo.fileName()
      self.ui.LabCurMedia.setText(baseName)

      curPath = fileInfo.absolutePath()
      QDir.setCurrent(curPath)   #重设当前目录
 
      media = QMediaContent(QUrl.fromLocalFile(fileName))
      self.player.setMedia(media)   #设置播放文件
      self.player.play()

   @pyqtSlot()    ##播放
   def on_btnPlay_clicked(self):
      self.player.play()

   @pyqtSlot()    ##暂停
   def on_btnPause_clicked(self):
      self.player.pause()

   @pyqtSlot()    ##停止
   def on_btnStop_clicked(self):
      self.player.stop()

   @pyqtSlot()    ##全屏
   def on_btnFullScreen_clicked(self):
      self.ui.videoWidget.setFullScreen(True)

   @pyqtSlot()    ##静音按钮
   def on_btnSound_clicked(self):
      mute=self.player.isMuted()
      self.player.setMuted(not mute)
      if mute:
         self.ui.btnSound.setIcon(QIcon(":/icons/images/volumn.bmp"))
      else:
         self.ui.btnSound.setIcon(QIcon(":/icons/images/mute.bmp"))
         
   @pyqtSlot(int)  ##音量调节
   def on_sliderVolumn_valueChanged(self,value):
      self.player.setVolume(value)

   @pyqtSlot(int)  ##播放进度调节
   def on_sliderPosition_valueChanged(self,value):
      self.player.setPosition(value)

##  =============自定义槽函数===============================        
   def do_stateChanged(self, state):    ##状态变化
      isPlaying = (state == QMediaPlayer.PlayingState)
      
      self.ui.btnPlay.setEnabled(not isPlaying)
      self.ui.btnPause.setEnabled(isPlaying)
      self.ui.btnStop.setEnabled(isPlaying)

   def do_durationChanged(self,duration):    ##文件长度变化
      self.ui.sliderPosition.setMaximum(duration)
	  
	  #先把ms化为s,再转换为min
      secs = duration / 1000   #秒
      mins = secs / 60         #分钟
      secs = secs % 60       #余数秒
      self.__duration = "%d:%d"%(mins, secs)
      self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

   def do_positionChanged(self, position): ##当前播放位置变化
      if (self.ui.sliderPosition.isSliderDown()):
         return  #如果正在拖动滑条,退出

      self.ui.sliderPosition.setSliderPosition(position)
      secs = position/1000   #秒
      mins = secs/60         #分钟
      secs = secs % 60       #余数秒
      self.__curPos = "%d:%d"%(mins, secs)
      self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

イベントフィルター EventFilter を使用して、ビデオ表示コンポーネント videoWidget にマウスとキー操作の機能を提供し、画面上でマウスの左ボタンをクリックし、フルスクリーン状態で Esc キーを押すと、再生を一時停止または継続することができます。全画面状態を終了します。

おすすめ

転載: blog.csdn.net/qq_35412059/article/details/129451553