Reproductor de video simple con PyQt 4 y 5



Simple código de fuente de un reproductor de video en PyQt utilizando los módulos multimedia Phonon (en PyQt 4) y QtMultimedia (PyQt 5). La librería gráfica se encarga mayoritariamente de todo: control de volumen, tiempo de reproducción, pantalla completa (presionando dos veces en la pantalla). Código totalmente comentado para facilitar su comprensión. La versión de PyQt 4 corre en Python 2 y 3; la de PyQt 5 solo en Python 3.

Fuente

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       videoplayer.py
#
#       Copyright 2016 Recursos Python - www.recursospython.com
#
#


import sys

from PyQt4.QtCore import QEvent
from PyQt4.QtGui import (QApplication, QHBoxLayout, QMainWindow,
                         QWidget, QPushButton, QVBoxLayout)
from PyQt4.phonon import Phonon


# Ruta del archivo.
VIDEO_PATH = "video.wmv"


class MainWindow(QMainWindow):
    
    def __init__(self):
        QMainWindow.__init__(self)
        
        # Controles principales para organizar la ventana.
        self.widget = QWidget(self)
        self.layout = QVBoxLayout()
        self.bottom_layout = QHBoxLayout()
        
        # Control de reproducción de video de Qt.
        self.video_player = Phonon.VideoPlayer(
            Phonon.VideoCategory, self)
        
        # Botones de reproducción y pausa.
        self.play_button = QPushButton("Pausa", self)
        self.stop_button = QPushButton("Detener", self)
        
        # Deslizadores para el volumen y transición del video.
        self.seek_slider = Phonon.SeekSlider(self)
        self.volume_slider = Phonon.VolumeSlider(self)
        
        # Acomodar controles en la pantalla.
        self.layout.addWidget(self.video_player)
        self.layout.addLayout(self.bottom_layout)
        self.bottom_layout.addWidget(self.play_button)
        self.bottom_layout.addWidget(self.stop_button)
        self.bottom_layout.addWidget(self.volume_slider)
        self.layout.addWidget(self.seek_slider)
        
        # Conectar los eventos con sus correspondientes funciones.
        self.play_button.clicked.connect(self.play_clicked)
        self.stop_button.clicked.connect(self.stop_clicked)
        self.video_player.mediaObject().stateChanged.connect(
            self.state_changed)
        
        # Se utiliza installEventFilter() para capturar eventos
        # del mouse en el control de video que utiliza internamente
        # la clase Phonon.VideoPlayer.
        self.video_player.videoWidget().installEventFilter(self)
        
        # Personalizar la ventana.
        self.setWindowTitle("Reproductor de video")
        self.resize(800, 600)
        self.layout.setMargin(0)
        self.bottom_layout.setMargin(0)
        self.widget.setLayout(self.layout)
        self.setCentralWidget(self.widget)
        
        # Reproducir el archivo.
        self.video_player.play(Phonon.MediaSource(VIDEO_PATH))
        
        # Conectar el control de volumen y transición de video
        # con las clases correspondientes.
        self.seek_slider.setMediaObject(self.video_player.mediaObject())
        self.volume_slider.setAudioOutput(
            self.video_player.audioOutput())
    
    def play_clicked(self):
        """
        Comenzar o resumir la reproducción.
        """
        if (self.video_player.mediaObject().state() in
            (Phonon.PausedState, Phonon.StoppedState)):
            self.video_player.play()
        else:
            self.video_player.pause()
    
    def stop_clicked(self):
        """
        Detener la reproducción.
        """
        self.video_player.stop()
    
    def state_changed(self, newstate, oldstate):
        """
        Actualizar el texto de los botones de reproducción y pausa.
        """
        states = {
            Phonon.PausedState: "Resumir",
            Phonon.PlayingState: "Pausa",
            Phonon.StoppedState: "Reproducir"
        }
        self.play_button.setText(states[newstate])
        self.stop_button.setEnabled(newstate != Phonon.StoppedState)
    
    def eventFilter(self, obj, event):
        """
        Establecer o remover pantalla completa al obtener
        el evento MouseButtonDblClick.
        """
        if event.type() == QEvent.MouseButtonDblClick:
            obj.setFullScreen(not obj.isFullScreen())
        return False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#       videoplayer.py
#
#       Copyright 2016 Recursos Python - www.recursospython.com
#
#


import sys
from functools import partial

from PyQt5.QtCore import QEvent, QUrl, Qt
from PyQt5.QtWidgets import (QApplication, QHBoxLayout, QMainWindow,
                             QWidget, QPushButton, QSlider,
                             QVBoxLayout)
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer
from PyQt5.QtMultimediaWidgets import QVideoWidget


# Ruta del archivo.
VIDEO_PATH = "video.avi"


class MainWindow(QMainWindow):
    
    def __init__(self):
        super().__init__()
        
        # Controles principales para organizar la ventana.
        self.widget = QWidget(self)
        self.layout = QVBoxLayout()
        self.bottom_layout = QHBoxLayout()
        
        # Control de reproducción de video de Qt.
        self.video_widget = QVideoWidget(self)
        self.media_player = QMediaPlayer()
        self.media_player.setMedia(
            QMediaContent(QUrl.fromLocalFile(VIDEO_PATH)))
        self.media_player.setVideoOutput(self.video_widget)
        
        # Botones de reproducción y pausa.
        self.play_button = QPushButton("Pausa", self)
        self.stop_button = QPushButton("Detener", self)
        
        # Deslizadores para el volumen y transición del video.
        self.seek_slider = QSlider(Qt.Horizontal)
        self.volume_slider = QSlider(Qt.Horizontal)
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(self.media_player.volume())
        self.seek_slider.sliderMoved.connect(self.media_player.setPosition)
        self.volume_slider.sliderMoved.connect(self.media_player.setVolume)
        self.media_player.positionChanged.connect(self.seek_slider.setValue)
        self.media_player.durationChanged.connect(
            partial(self.seek_slider.setRange, 0))
        
        # Acomodar controles en la pantalla.
        self.layout.addWidget(self.video_widget)
        self.layout.addLayout(self.bottom_layout)
        self.bottom_layout.addWidget(self.play_button)
        self.bottom_layout.addWidget(self.stop_button)
        self.bottom_layout.addWidget(self.volume_slider)
        self.layout.addWidget(self.seek_slider)
        
        # Conectar los eventos con sus correspondientes funciones.
        self.play_button.clicked.connect(self.play_clicked)
        self.stop_button.clicked.connect(self.stop_clicked)
        self.media_player.stateChanged.connect(self.state_changed)
        
        # Se utiliza installEventFilter() para capturar eventos
        # del mouse en el control de video.
        self.video_widget.installEventFilter(self)
        
        # Personalizar la ventana.
        self.setWindowTitle("Reproductor de video")
        self.resize(800, 600)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.bottom_layout.setContentsMargins(0, 0, 0, 0)
        self.widget.setLayout(self.layout)
        self.setCentralWidget(self.widget)
        
        # Reproducir el video.
        self.media_player.play()
    
    def play_clicked(self):
        """
        Comenzar o resumir la reproducción.
        """
        if (self.media_player.state() in
            (QMediaPlayer.PausedState, QMediaPlayer.StoppedState)):
            self.media_player.play()
        else:
            self.media_player.pause()
    
    def stop_clicked(self):
        """
        Detener la reproducción.
        """
        self.media_player.stop()
    
    def state_changed(self, newstate):
        """
        Actualizar el texto de los botones de reproducción y pausa.
        """
        states = {
            QMediaPlayer.PausedState: "Resumir",
            QMediaPlayer.PlayingState: "Pausa",
            QMediaPlayer.StoppedState: "Reproducir"
        }
        self.play_button.setText(states[newstate])
        self.stop_button.setEnabled(newstate != QMediaPlayer.StoppedState)
    
    def eventFilter(self, obj, event):
        """
        Establecer o remover pantalla completa al obtener
        el evento MouseButtonDblClick.
        """
        if event.type() == QEvent.MouseButtonDblClick:
            obj.setFullScreen(not obj.isFullScreen())
        return False


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Vista previa

preview



19 comentarios.

  1. Hola, muchas gracias por el tutorial!

    Queria saber como puedo tener el tiempo en pantalla, tanto el totaltime como currentime, y tabmein queria saber como hacer un evento al finalizar el video, por lo que lei es algo asi como finished pero no logre hacer mucho porque la documentacion la encontre para c++.

    Muchas gracias de antemano!

  2. Hola, soy nuevo en Python, quiero hacer una publicidad con vídeo (sin sonido) como las que hay en las calles de pantalla grande, yo lo voy hacer en una tv XD, y quiero que los vídeos se reproduzcan uno tras otros. He hecho este código, pero me sale error y solo se reproduce uno. El código de esta pagina me da un error que dice : from PyQt4.QtCore import QEvent
    ImportError: DLL load failed: %1 no es una aplicación Win32 válida.
    Por eso hice este código.

    http://pastebin.com/axJdeFxe

    Gracias por su respuesta.

  3. Hola soy nuevo en este lenguaje Python y al correr el código me marca un error “from PyQt4.QtCore import QEvent” al parecer es por la librería PyQt4 pero ya la instale y aun así me sigue marcando error. Espero puedan ayudarme.

    ¡Gracias!

    • Recursos Python says:

      Hola, ¿qué versión de Python estás usando y qué sistema operativo? Podés intentar hacer import PyQt4 en la consola interactiva de Python para ver si marca algún error.

      Saludos.

          • hola la verdad esque soy nuevo usando python una preguntota ya instale pyqt4 tengo que instalar multimedia Phonon para que ya no me de el error en line from PyQt4.QtCore import QEvent muchas garcias por respodery estar atento espero puedas atender mi duda gracis

          • Recursos Python says:

            Si sigues obteniendo un error al importar QEvent entonces probablemente no tengas instalado PyQt 4. Phonon se incluye por defecto en la instalación de PyQt 4. Si estás usando PyQt 5 ya actualicé el artículo con un nuevo código para que corra en esa versión.

            Si sigues teniendo problemas te invito a registrarte en el foro y crear un tema allí así podemos ver las cosas con más detalle.

            Saludos.

  4. Hola que buen trabajo. No lo he probado pero de ante mano gracias.

    Me surge una pregunta, si el video se encuentra en otra ubicación agregaría la ubicacion entre las comillas de la linea 67?

    Como podría reproducir varios videos, uno tras otro??

    Gracias nuevamente.

    • Recursos Python says:

      Hola Cristian.

      Efectivamente, podés especificar cualquier archivo de video tal como comentás.

      Para reproducir varios videos consecutivos, podrías hacer uso de la señal finished que provee el reproductor de vídeo, que es invocada cuando termina la reproducción del video, conectándola (self.video_player.finished.connect(...)) a alguna función que se encargue de seleccionar el próximo archivo y reproducirlo. Si necesitás ayuda con el código te invito a que crees un tema en el foro para que podamos verlo.

      Un saludo.

  5. Excelente tutorial.
    Por que no usas la función super es un poco mas ordenado no? saludos 🙂

    def __init__(self):
    QMainWindow.__init__(self)

    def __init__(self):
    super(QMainWindow, self).__init__()

Deja un comentario