简体   繁体   English

在gstreamer中串联视频文件(在python中)

[英]Concatenating video files in gstreamer (in python)

I am trying to take a series of video segment files (in .flv format, all with identical audio/video encodings), and concatenate them to a new file (in .mp4 format). 我正在尝试获取一系列视频片段文件(.flv格式,所有音频/视频编码都相同),并将它们连接到一个新文件(.mp4格式)。 My encoding pipeline works just fine for normal single-segment files, but once I add the second segment, I am having no end of difficulty getting this to work correctly. 我的编码管道适用于普通的单段文件,但是一旦添加了第二段,我就可以毫不费力地使它正常工作。

With my current implementation, I have a message handler for EOS messages as such: 在当前的实现中,我有一个用于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)

This shows the duration of the last segment, and attempts to set the offset of the next segment to being the end of the previous segment. 这显示了最后一个片段的持续时间,并尝试将下一个片段的偏移量设置为上一个片段的结尾。 This does transcode OK, but it is always seeking back to the beginning of the output file and overwriting the previous contents. 确实可以对代码进行转码,但是它始终会返回到输出文件的开头并覆盖先前的内容。 Obviously this is not giving the output I want! 显然,这没有给出我想要的输出!

Is there something I missed here? 我在这里错过了什么吗? I've tried with this as a pad probe, but then it won't let me stop and restart the pipeline from its own thread, and crashes miserably (telling me to do it in a message handler, which is what I have now). 我已经尝试将其用作填充探针,但是它不会让我停止并从其自己的线程重新启动管道,并且崩溃极了(告诉我在消息处理程序中进行此操作,这就是我现在所拥有的) 。

filesink is always overwriting the existing file. filesink始终会覆盖现有文件。 What you really want here is to append the new segment to the existing MP4 file (and also you don't want to just append another MP4 file to the end of an existing one). 您真正想要的是将新段附加到现有的MP4文件中(而且您也不想仅将另一个MP4文件附加到现有文件的末尾)。

What you will have to do for this is that you have to catch the EOS event (not message) on the srcpad right in front of the muxer via a pad probe. 为此,您将必须通过填充探针在多路复用器前面的srcpad上捕获EOS 事件 (不是消息)。 From the pad probe callback you would then unlink that srcpad and the muxer's sinkpad. 然后,从pad探针回调中,取消该srcpad和复用器的接收板的链接。 Then you would dynamically link in a new input and link it to the muxer, while setting the pad offset as you already do. 然后,您将动态链接一个新的输入并将其链接到多路复用器,同时像已经设置的那样设置打击垫的偏移量。 Don't ever change the state of the pipeline, and for the very last segment you would let the EOS event go through and wait for the EOS message (not event!) to be posted on the bus. 永远不要更改管道的状态,在最后一段中,您将让EOS事件通过并等待EOS消息(不是事件!)在总线上发布。 Only then shut down the pipeline. 只有这样才能关闭管道。

Now the tricky part with all of this is that you probably also want to clean up the old segments. 现在,所有这些棘手的部分是,您可能还希望清理旧的段。 You can't do that from the pad probe callback as EOS is sent from the streaming thread. 由于EOS是从流线程发送的,因此您无法从pad探针回调中执行此操作。 What you would need to do here is that (after unlinking from the pad probe callback!) you would remove the elements related to the old segment from the pipeline from another thread, set their state to GST_STATE_NULL and then unref them. 您需要做的是(从pad probe回调取消链接之后!)您将从另一个线程的管道中删除与旧段相关的元素,将它们的状态设置为GST_STATE_NULL,然后取消引用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM