【问题标题】:How to play multiple clips of a video one after another如何一个接一个地播放视频的多个片段
【发布时间】:2019-06-22 07:20:27
【问题描述】:

我有一个视频,我从其中按时间间隔获取一些剪辑,我想做以下事情:

  • 让剪辑一个接一个地播放 - 所以第一个剪辑播放,然后在它完成后,然后第二个播放,依此类推...但是目前,这很好,但它只是在时间间隔之间播放这两个剪辑,我不希望它这样做。

我该怎么做呢?

我尝试使用例如pausestop 等等……简直就是一切,但它们都不起作用。

我的python版本:3.6.0

和 PyQt:5.6

视频播放器文件(repl 的链接,因为它太长了):

https://repl.it/repls/SuperBrownSoftware

(只需将其复制到您的 IDE 中)

这是我应该运行的代码:

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

更新:

我现在得到了 ekhumoro 的答案,所以我正在使用这个结构设置:

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

我将 ekhumoro 的答案函数复制到我的代码中,然后添加了两行:self.player.positionChanged.connect(self.handlePositionChanged)self.player.mediaStatusChanged.connect(self.handleMediaStateChanged)retranslateUi

但这似乎不起作用,我觉得我做错了。

它给了我一个错误:

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

【问题讨论】:

    标签: python pyqt pyqt5 qmediaplayer


    【解决方案1】:

    一种方法是创建一个简单的队列,然后等待每个剪辑完成,然后再移动到队列中的下一个项目。下面是一个简单的演示,展示了如何实现这一点。希望它应该很容易看出如何将其适应您自己的代码。

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

    【讨论】:

    • 你知道如何将它嵌入到另一个代码中吗?
    • 我以为我已经尽可能简单了。唯一真正重要的部分是为剪辑参数创建某种队列,然后使用positionChanged 信号获取下一个。我的示例中的所有其他内容只是为了制作一个有效的演示,可以忽略。关键概念是避免使用显式循环结构(就像您在问题中所说的那样),并使用信号等待当前剪辑完成,然后再从队列中获取下一个剪辑。如果你不能让它工作,那么你的代码的其他部分一定有问题。
    • 感谢您的回复,所以我只需将您的addMediaplayNexthandlePositionChangedhandleMediaStateChanged 函数复制到我的整个代码中,同时添加这两行:self.player.positionChanged.connect(self.handlePositionChanged)@ 987654328@
    • 不,你显然不能直接复制粘贴代码。这不是你要求的。你问如何去做,这就是我的回答。您不需要媒体状态更改部分。你只需要一个函数来初始化队列(比如addMedia);开始下一个剪辑的函数(如playNext);以及处理位置变化信号的函数(如handlePositionChange)。我认为如果您仔细阅读它们,很容易看出我的函数是如何工作的,因此也应该很容易看到如何在您自己的代码中使用类似的东西。
    • 给了你赏金。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    相关资源
    最近更新 更多