How to play multiple clips of a video one after another

雨燕双飞 提交于 2021-02-07 16:42:15

问题


I have a video, from which I am getting some clips by time interval, and I want to do the following:

  • Make the clips play one after another - so first clip plays, then after it is done, then second plays, and so on... But currently, it's good, but it just plays the part in between the time intervals of the two clips, which I don't want it to do.

How would I go about doing that?

I tried using e.g. pause, stop, etc... simply everything, but none of them worked.

My version of python: 3.6.0

And PyQt: 5.6

Video player file (a link to repl since it is too long):

https://repl.it/repls/SuperBrownSoftware

(just copy it into your IDE)

Here is my code that you should run:

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_())

Update:

I now got the answer by ekhumoro, so i am using this setup of the 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()

I copied ekhumoro's answer's functions to my code, then added two lines of: self.player.positionChanged.connect(self.handlePositionChanged) and self.player.mediaStatusChanged.connect(self.handleMediaStateChanged) in retranslateUi

But that didn't seem to work, i felt like i did some mistake.

It's giving me an error:

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

回答1:


One approach is to create a simple queue and then wait for each clip to finish before moving to the next item in the queue. Below is a simple demo showing how to achieve that. Hopefully it should be easy to see how to adapt this to your own 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_())


来源:https://stackoverflow.com/questions/54416396/how-to-play-multiple-clips-of-a-video-one-after-another

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!