我正在尝试拍摄一系列视频片段文件(采用.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探测器,但随后它不会让我停止并从其自己的线程重新启动管道,并且惨遭崩溃(告诉我在消息处理程序中执行此操作,这是什么我现在有。)
答案 0 :(得分:4)
filesink始终覆盖现有文件。你真正想要的是将新段附加到现有的MP4文件中(并且你也不想只是将另一个MP4文件附加到现有文件的末尾)。
您需要做的就是必须通过pad探测器在多路复用器前面的srcpad上捕获EOS 事件(而不是消息)。从pad探测器回调中,您将取消链接srcpad和muxer的sinkpad。然后,您将动态链接新输入并将其链接到多路复用器,同时设置焊盘偏移量。不要改变管道的状态,对于最后一段,您将让EOS事件通过并等待EOS消息(不是事件!)在总线上发布。然后才关闭管道。
现在所有这一切的棘手部分是你可能还想清理旧的细分市场。由于从流线程发送EOS,因此无法从pad探测回调中执行此操作。你需要做的是(在从pad探测器回调取消链接之后!)你将从另一个线程中删除与管道相关的元素,将它们的状态设置为GST_STATE_NULL然后取消它们。