4 votes

Comment lire plusieurs clips d'une vidéo l'un après l'autre

J'ai une vidéo, à partir de laquelle je récupère des clips par intervalle de temps, et je veux faire ce qui suit :

  • Faire en sorte que les clips soient lus l'un après l'autre - donc le premier clip est lu, puis une fois qu'il est terminé, le second est lu, et ainsi de suite... Mais actuellement, c'est bien, mais il joue juste la partie entre les intervalles de temps des deux clips, ce que je ne veux pas qu'il fasse.

Comment dois-je m'y prendre ?

J'ai essayé d'utiliser par exemple pause , stop etc... tout simplement tout, mais aucun d'entre eux n'a fonctionné.

Ma version de python : 3.6.0

Et PyQt : 5.6

Fichier du lecteur vidéo (un lien vers repl car il est trop long) :

https://repl.it/repls/SuperBrownSoftware

(il suffit de le copier dans votre IDE)

Voici mon code que vous devriez exécuter :

from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia
from PyQt5.QtWidgets import *
import sys
from pyqtvideo2_copy import *
app = QtWidgets.QApplication(sys.argv)

video = VideoWidget()
w = QtWidgets.QWidget()
w.fr = QtWidgets.QGridLayout(w)
w.bt = QtWidgets.QPushButton()
w.fr.addWidget(w.bt)
w.player_=Player(sys.argv[1:])
w.fr.addWidget(w.player_)
print(w)
video.activateWindow()

def clicked():
    l=[[2000,4000],[10000,15000]]
    for i in l:
        w.player_.setPosition(i[0])
        w.player_.player.pause()
        w.player_.player.play()
        w._end=i[1]
        w.player_.player.positionChanged.connect(on_positionChanged)

def on_positionChanged(position):
    if w.player_.player.state() == QtMultimedia.QMediaPlayer.PlayingState:
        if position > w._end:
            w.player_.player.stop()

def except_hook(cls, exception, traceback):
    sys.__excepthook__(cls, exception, traceback)

w.bt.clicked.connect(clicked)
w.show()
sys.excepthook=except_hook
sys.exit(app.exec_())

Mise à jour :

J'ai maintenant reçu la réponse d'ekhumoro, et j'utilise donc cette configuration de la structure :

class Ui_MainWindow(QMainWindow):
    def setupUi(self, MainWindow):
        ...
    def retranslateUi(self, MainWindow):
        ...
        self.player.positionChanged.connect(self.handlePositionChanged)
        self.player.mediaStatusChanged.connect(self.handleMediaStateChanged)

    ...
    def videoclips(self):
        self.w=QWidget()
        g=QGridLayout(self.w)
        g.setContentsMargins(0,0,0,0)
        d=TableWidget(self.df2,self.clicked)
        g.addWidget(d)
        self.w.show()
    def clicked(self,item):
        self.w.close()
        self.addMedia(ast.literal_eval(item.text()))
    def addMedia(self, clips):
        self._index = -1
        self._clips = clips
    def playNext(self):
        self.player.player.pause()
        self._index += 1
        if 0 <= self._index < len(self._clips):
            self.player.player.setPosition(self._clips[self._index][0])
            self.player.player.play()
    def handlePositionChanged(self, pos):
        if (0 <= self._index < len(self._clips) and
            pos > self._clips[self._index][1] and
            self.player.player.state() == QtMultimedia.QMediaPlayer.PlayingState):
            self.playNext()

    def handleMediaStateChanged(self, state):
        if state == QtMultimedia.QMediaPlayer.LoadedMedia:
            self.playNext()

J'ai copié les fonctions de la réponse d'ekhumoro dans mon code, puis j'ai ajouté deux lignes de : self.player.positionChanged.connect(self.handlePositionChanged) y self.player.mediaStatusChanged.connect(self.handleMediaStateChanged) sur retranslateUi

Mais ça n'a pas semblé marcher, j'ai eu l'impression d'avoir fait une erreur.

Ça me donne une erreur :

AttributeError: 'Ui_MainWindow' object has no attribute '_index'

4voto

ekhumoro Points 23190

Une approche consiste à créer une file d'attente simple, puis à attendre que chaque clip se termine avant de passer à l'élément suivant de la file. Vous trouverez ci-dessous une démo simple montrant comment y parvenir. Nous espérons qu'il sera facile de voir comment l'adapter à votre propre code.

import sys
from PyQt5 import QtCore, QtWidgets, QtMultimedia, QtMultimediaWidgets

class Window(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.video = QtMultimediaWidgets.QVideoWidget()
        self.player = QtMultimedia.QMediaPlayer()
        self.player.setVideoOutput(self.video)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.video)
        self.player.positionChanged.connect(self.handlePositionChanged)
        self.player.mediaStatusChanged.connect(self.handleMediaStateChanged)

    def addMedia(self, path, clips):
        self._index = -1
        self._clips = clips
        self.player.setMedia(
            QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(path)))

    def playNext(self):
        self.player.pause()
        self._index += 1
        if 0 <= self._index < len(self._clips):
            self.player.setPosition(self._clips[self._index][0])
            self.player.play()

    def handlePositionChanged(self, pos):
        if (0 <= self._index < len(self._clips) and
            pos > self._clips[self._index][1] and
            self.player.state() == QtMultimedia.QMediaPlayer.PlayingState):
            self.playNext()

    def handleMediaStateChanged(self, state):
        if state == QtMultimedia.QMediaPlayer.LoadedMedia:
            self.playNext()

app = QtWidgets.QApplication(sys.argv)
window = Window()
window.addMedia(sys.argv[1], [[2000, 4000], [10000, 15000]])
# window.addMedia(sys.argv[1], [[10000, 20000], [40000, 50000]])
window.show()
sys.exit(app.exec_())

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X