Cutting a video file

Kaito Kumashiro kumashiro.kaito at gmail.com
Mon Jul 2 04:22:16 PDT 2012


Hello

I'm trying to cut out a fragment from video file (audio + video in AVI
container). For that, I wrote a Python script where I create pipeline
like this:

------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------
demux_elements = []
video_elements = []
audio_elements = []
remux_elements = []

pipeline = gst.Pipeline()

demux_elements.append(gst.element_factory_make("filesrc", "src"))
demux_elements.append(gst.element_factory_make("queue", "squeue"))
demux_elements.append(gst.element_factory_make("avidemux", "demuxer"))

video_elements.append(gst.element_factory_make("queue", "vqueue"))
video_elements.append(gst.element_factory_make("ffdec_msmpeg4v2", "vdecoder"))
#video_elements.append(gst.element_factory_make("ffmpegcolorspace",
"vcspace"))  # I don't think this is needed
video_elements.append(gst.element_factory_make("ffenc_msmpeg4v2", "vencoder"))
video_elements.append(gst.element_factory_make("queue", "vequeue"))

audio_elements.append(gst.element_factory_make("queue", "aqueue"))
audio_elements.append(gst.element_factory_make("mp3parse", "aparser"))
audio_elements.append(gst.element_factory_make("ffdec_mp3", "adecoder"))
audio_elements.append(gst.element_factory_make("audioconvert", "aconverter"))
audio_elements.append(gst.element_factory_make("audioresample", "aresampler"))
audio_elements.append(gst.element_factory_make("lamemp3enc", "aencoder"))
audio_elements.append(gst.element_factory_make("queue", "aequeue"))

remux_elements.append(gst.element_factory_make("avimux", "remuxer"))
remux_elements.append(gst.element_factory_make("filesink", "dst"))

pipeline.add_many(*demux_elements)
pipeline.add_many(*video_elements)
pipeline.add_many(*audio_elements)
pipeline.add_many(*remux_elements)

pipeline.get_by_name("demuxer").connect("pad-added", dec_pad_added_cb, pipeline)
pipeline.get_by_name("aequeue").get_pad("src").link(pipeline.get_by_name("remuxer").get_pad("audio_00"))
pipeline.get_by_name("vequeue").get_pad("src").link(pipeline.get_by_name("remuxer").get_pad("video_00"))
pipeline.get_by_name("vencoder").set_property("mb-decision", 1)
pipeline.get_by_name("vencoder").set_property("bitrate", 1200000)
pipeline.get_by_name("aencoder").set_property("bitrate", 48)

gst.element_link_many(*demux_elements)
gst.element_link_many(*video_elements)
gst.element_link_many(*audio_elements)
gst.element_link_many(*remux_elements)

bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message::error", error_cb, pipeline)
bus.connect("message::eos", eos_cb, pipeline)
bus.connect("message::state-changed", state_changed_cb, pipeline)
bus.connect("message::segment-done", segment_done_cb, pipeline)
------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------

Now, I have two problems with it.

1. When I cut a fragment using pipeline above (setting seek event
etc.), video stream lags behind audio when I play it in mplayer, Totem
or VLC. It starts synchronized, but over time this async grows and
after 1 minute of playback audio is couple of seconds ahead of video.
All plugins used are part of the same pipeline, so I don't know where
that synchronization problem comes from. When I build a pipeline like
this:

------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------
pipeline = gst.Pipeline()

src = gst.element_factory_make("filesrc", "src")
pipeline.add(src)
squeue = gst.element_factory_make("queue", "squeue")
pipeline.add(squeue)
demuxer = gst.element_factory_make("avidemux", "demuxer")
demuxer.connect("pad-added", dec_pad_added_cb, pipeline)
pipeline.add(demuxer)
gst.element_link_many(src, squeue, demuxer)

vqueue = gst.element_factory_make("queue", "vqueue")
pipeline.add(vqueue)

aqueue = gst.element_factory_make("queue", "aqueue")
pipeline.add(aqueue)

remuxer = gst.element_factory_make("avimux", "remuxer")
pipeline.add(remuxer)
dst = gst.element_factory_make("filesink", "dst")
pipeline.add(dst)
gst.element_link_many(remuxer, dst)

pipeline.get_by_name("aqueue").get_pad("src").link(pipeline.get_by_name("remuxer").get_pad("audio_00"))
pipeline.get_by_name("vqueue").get_pad("src").link(pipeline.get_by_name("remuxer").get_pad("video_00"))

bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect("message::error", error_cb, pipeline)
bus.connect("message::eos", eos_cb, pipeline)
bus.connect("message::state-changed", state_changed_cb, pipeline)
bus.connect("message::segment-done", segment_done_cb, pipeline)
------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------8<------

(in short: there are no decoders and encoders; demuxer is linked with
muxer) audio and video in resulting AVI file is synchronized, but I
can't cut out a fragment of video, because after sending seek event to
the pipeline it rolls to the start position, but plays to the end of
input file, not to the end position given in an event. Even when
SEEK_FLAG_SEGMENT is set, "segment-done" message is not posted on a
bus.

How can I get rid of this async when recoding or how can I cut a part
of material without recoding?


2. Ye Ol Problem. Before seeking to start position, few frames from
the start are sent during PREROLL. How can I avoid this? I tried
blocking muxer pads and using valve plugin, but that only messes up
the output (huge async or video playing at 20+ speed while audio plays
normally). I also tried to use gnonlin, but it doesn't seem to work at
all. Pipeline (or composition) links without problems, but it hangs
after changing the state to STATE_PLAYING or STATE_PAUSED (according
to debug, pipeline stops after opening output file for writing).


Python 2.7.2
gstreamer 0.10.35
gnonlin 0.10.17


Thank you for helping me out with this
Regards

-- 
熊城


More information about the gstreamer-devel mailing list