GStreamer和GNonLin的视频转场无法使用
我一直在尝试用gstreamer和gnonlin在Python中把两个视频合并在一起,并在它们之间加一个短暂的过渡效果(像smpte那样)。不过,我一直搞不定gnloperation/smpte过渡效果。
目标
下面是一个程序。我希望它能播放第一个文件的前4秒,在第2秒的时候开始进行一个持续2秒的smpte过渡到另一个文件。(也就是说,第二个文件会在整个播放过程中从第2秒开始播放,但会在这2秒的过渡中逐渐显现出来),在过渡结束后,第二个文件的2秒内容应该单独播放。
这个想法是基于另一个gstreamer/gnonlin的Python脚本。我在gstreamer-devel邮件列表上问过这个问题(还有再次问过),现在在这里尝试。
问题
过渡效果没有完成。过渡大约持续了0.5秒,然后视频1播放了大约1.5秒,接着视频2才开始播放。我尝试改变控制器的结束位置(例如设置为controller.set("position", 0.5 * gst.SECOND, 0.0)
),这样过渡在0.5秒内完成,但一旦过渡结束,视频1又会播放一小段时间,然后视频2才开始播放。
我想也许视频过渡限制在0.5秒,所以我把gnloperation改成0.5秒,但同样的问题依然存在,只不过过渡效果只播放了大约0.3秒,视频1在过渡过程中又播放了一小段时间,然后视频2才开始播放。
脚本
#! /usr/bin/python
import gst, gobject
gobject.threads_init()
comp = gst.element_factory_make("gnlcomposition", "composition")
gsrc1 = gst.element_factory_make("gnlfilesource")
gsrc1.props.location = "file:///home/rory/helmetcam/dingle-tom/vshort01.mov"
gsrc1.props.start = 0
gsrc1.props.duration = 4 * gst.SECOND
gsrc1.props.media_start = 0
gsrc1.props.media_duration = 4 * gst.SECOND
gsrc1.props.priority = 3
comp.add(gsrc1)
gsrc2 = gst.element_factory_make("gnlfilesource")
gsrc2.props.location = "file:///home/rory/helmetcam/dingle-tom/vshort02.mov"
gsrc2.props.start = 2 * gst.SECOND
gsrc2.props.duration = 6 * gst.SECOND
gsrc2.props.media_start = 0
gsrc2.props.media_duration = 2 * gst.SECOND
gsrc2.props.priority = 2
comp.add(gsrc2)
bin = gst.Bin()
alpha1 = gst.element_factory_make("alpha")
queue = gst.element_factory_make("queue")
smpte = gst.element_factory_make("smptealpha")
smpte.props.type = 21
mixer = gst.element_factory_make("videomixer")
bin.add(alpha1, queue, smpte, mixer)
alpha1.link(mixer)
queue.link(smpte)
smpte.link(mixer)
controller = gst.Controller(smpte, "position")
controller.set_interpolation_mode("position", gst.INTERPOLATE_LINEAR)
controller.set("position", 0, 1.0)
controller.set("position", 2.0 * gst.SECOND, 0.0)
bin.add_pad(gst.GhostPad("sink1", alpha1.get_pad("sink")))
bin.add_pad(gst.GhostPad("sink2", queue.get_pad("sink")))
bin.add_pad(gst.GhostPad("src", mixer.get_pad("src")))
op = gst.element_factory_make("gnloperation")
op.add(bin)
op.props.start = 2 * gst.SECOND
op.props.duration = 2 * gst.SECOND
op.props.media_start = 0
op.props.media_duration = 2 * gst.SECOND
op.props.priority = 1
comp.add(op)
# create the backend
color= gst.element_factory_make("ffmpegcolorspace")
enc = gst.element_factory_make("theoraenc")
mux = gst.element_factory_make("oggmux")
sink = gst.element_factory_make("filesink")
sink.props.location = "./transitions-between-two.ogv"
pipeline = gst.Pipeline()
pipeline.add(comp, color, enc, mux, sink)
color.link(enc)
enc.link(mux)
mux.link(sink)
def on_pad(comp, pad, elements):
convpad = elements.get_compatible_pad(pad, pad.get_caps())
pad.link(convpad)
comp.connect("pad-added", on_pad, color)
# now run the pipeline
loop = gobject.MainLoop(is_running=True)
bus = pipeline.get_bus()
bus.add_signal_watch()
def on_message(bus, message, loop):
if message.type == gst.MESSAGE_EOS:
loop.quit()
elif message.type == gst.MESSAGE_ERROR:
print message
loop.quit()
bus.connect("message", on_message, loop)
pipeline.set_state(gst.STATE_PLAYING)
loop.run()
pipeline.set_state(gst.STATE_NULL)
1 个回答
2
看起来问题出在你第二个源文件的属性上。
而不是:
gsrc2.props.start = 2 * gst.SECOND
gsrc2.props.duration = 6 * gst.SECOND
gsrc2.props.media_start = 0
gsrc2.props.media_duration = 2 * gst.SECOND
gsrc2.props.priority = 2
试试:
gsrc2.props.start = 2 * gst.SECOND
gsrc2.props.duration = 4 * gst.SECOND
gsrc2.props.media_start = 0
gsrc2.props.media_duration = 4 * gst.SECOND
gsrc2.props.priority = 2
对我来说,这似乎是按预期工作的。