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

Curso online 👨‍💻

¡Ya lanzamos el curso oficial de Recursos Python en Udemy! Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter en 2024.

Consultoría 💡

Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.

24 comentarios.

  1. Al ejecutar la versión de Qt5, tras salir del programa salía el error de Violación de segmento, lo pude remediar cambiando la última línea por:
    #sys.exit(app.exec_()) # error: Violación de segmento (`core’ generado)
    laapp = app.exec_()
    del app
    sys.exit(laapp)

  2. encontré un error con el código o quizá no lo sea ????
    Al cerrar la ventana donde esta reproduciendo el vídeo, se cierra pero el audio se sigue escuchando.
    Adicionalmente debo decir que pude reproducir varios formatos de vídeo como ser mp4, mpg, avi entre otros ya que tengo instalado k-lite.
    Como se puede corregir este comportamiento y tb quisiera saber como hacer una lista de reproducción y al terminar la lista de reproducción del vídeo se cierre la ventana automáticamente.

    Pd. Muchas gracias por el aporte, Saludos 😀

  3. Muchas gracias por tu aporte Cristo te bendiga.
    bueno lo corrí en mi cpu y me sale un mensaje de error:
    defaultServiceProvider::requestService(): no service found for – «org.qt-project.qt.mediaplayer»
    tengo linux mint 19.1 de 64bit PyQt5 y Python 3 ya busqué en la red y no doy con el problema.

  4. 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!

  5. 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.

    https://mypaste.dev/HAkXnuyc

    Gracias por su respuesta.

  6. 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.

          • Que tal? soy nuevo en esto estoy usando el código para reproducción de vídeo en PyQt5 pero necesito que este se repita indefinidamente al finalizar. Te agradecería mucho si me puedes ayudar Saludos.

  7. 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.

  8. 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 una respuesta