在gstreamer中连接视频文件(在python中)

时间:2014-10-27 17:41:47

标签: python video concatenation gstreamer

我正在尝试拍摄一系列视频片段文件(采用.flv格式,所有文件都采用相同的音频/视频编码),并将它们连接到一个新文件(采用.mp4格式)。我的编码管道对于普通的单段文件工作得很好,但是一旦我添加了第二段,我就没有困难让它正常工作。

使用我当前的实现,我有一个EOS消息的消息处理程序:

    def on_eos(self, bus, msg):
        remain = len(self.metadata['localSegments'])
        logger.warning("Hit EOS Probe: %d segments left" % remain)
        if remain == 0:
            self.abort = True
            self.mainloop.quit()
            return

        duration = self.pipeline.query_duration(Gst.Format(Gst.Format.TIME))[1]
        self.offset += duration
        logger.info("Duration: %s, new offset: %s" % (Gst.TIME_ARGS(duration),
                                                      Gst.TIME_ARGS(self.offset)))
        self.pipeline.set_state(Gst.State.READY)
        self.localInFile = self.metadata['localSegments'].pop(0)
        logger.info("Starting new file: %s" % self.localInFile)
        self.elem_src.set_property('location', self.localInFile)
        self.elem_src_src.set_offset(self.offset)
        self.pipeline.set_state(Gst.State.PLAYING)

这显示最后一个段的持续时间,并尝试将下一个段的偏移量设置为前一个段的末尾。这确实转码好,但它总是寻找输出文件的开头并覆盖以前的内容。显然这不是我想要的输出!

我在这里错过了什么吗?我已尝试将其作为pad探测器,但随后它不会让我停止并从其自己的线程重新启动管道,并且惨遭崩溃(告诉我在消息处理程序中执行此操作,这是什么我现在有。)

1 个答案:

答案 0 :(得分:4)

filesink始终覆盖现有文件。你真正想要的是将新段附加到现有的MP4文件中(并且你也不想只是将另一个MP4文件附加到现有文件的末尾)。

您需要做的就是必须通过pad探测器在多路复用器前面的srcpad上捕获EOS 事件(而不是消息)。从pad探测器回调中,您将取消链接srcpad和muxer的sinkpad。然后,您将动态链接新输入并将其链接到多路复用器,同时设置焊盘偏移量。不要改变管道的状态,对于最后一段,您将让EOS事件通过并等待EOS消息(不是事件!)在总线上发布。然后才关闭管道。

现在所有这一切的棘手部分是你可能还想清理旧的细分市场。由于从流线程发送EOS,因此无法从pad探测回调中执行此操作。你需要做的是(在从pad探测器回调取消链接之后!)你将从另一个线程中删除与管道相关的元素,将它们的状态设置为GST_STATE_NULL然后取消它们。