I am revisiting the topic of exporting a frame of video to a PNG image file using Python and Gstreamer. In my previous post, I demonstrated how to use the gst-launch command to accomplish this, but I never could get it to work with just Python. Also, my previous pipeline only worked for MPEG and DV video files.
Before we get into the Python part of this post, let me share an updated pipeline that can be used from the command line. This should work with any valid Gstreamer video file, and export the 1st frame to a PNG:
gst-launch gstfilesrc location=/home/MyUser/Videos/MyMovieFile.MPG ! decodebin ! ffmpegcolorspace ! pngenc ! filesink location=/home/MyUser/Videos/MyExportedFrame.pngNow on to the fun part... the Python version of this same pipeline. There are really two approaches to building a Gstreamer pipeline in Python. The 1st approach is to create each element as a separate object, link the elements together, and then change the state of the pipeline to "PLAYING". This can be very difficult to do correctly (based on the complexity of your pipeline), and due to the fact not all elements can be linked together before the pipeline has been prerolled.
The 2nd approach to build a pipeline is much simpler and has many limitations, but it works great for exporting video frames. Please see the 5 lines of Python code below which does the same thing as my pipeline above.
# This example Python script takes any gstreamer movie format, and exports a PNG image of the
# 1st frame. In other words, it takes a screen grab or screen capture of your video file.
# This example uses an MPEG video, but it should work the same with any video format.
# Import the gstreamer library
import gst
# Define your pipeline, just as you would at the command prompt.
# This is much easier than trying to create and link each gstreamer element in Python.
# This is great for pipelines that end with a filesink (i.e. there is no audible or visual output)
pipe = gst.parse_launch("filesrc location=/home/MyUser/Videos/MyMovieFile.MPG ! decodebin ! ffmpegcolorspace ! pngenc ! filesink location=/home/MyUser/Videos/MyExportedFrame.png")
# Get a reference to the pipeline's bus
bus = pipe.get_bus()
# Set the pipeline's state to PLAYING
pipe.set_state(gst.STATE_PLAYING)
# Listen to the pipeline's bus indefinitely until we receive a EOS (end of stream) message.
# This is a super important step, or the pipeline might not work as expected. For example,
# in my example pipeline above, the pngenc will not export an actual image unless you have
# this line of code. It just exports a 0 byte png file. So... don't forget this step.
bus.poll(gst.MESSAGE_EOS, -1)
I hope these examples are useful to you. It's hard to find good Python and Gstreamer examples, and this might be one of the few good examples of this technique on the Internet (as of today). If there are other examples of this, please let me know, because I haven't found a single one. Good luck!





November 16, 2008 2:02 AM
you should also listen for gst.MESSAGE_ERROR on the bus !
Else, if you use a file that produces an error in the pipeline... you'll never see that and your script will be waiting there forever.
Otherwise, you can have a look at the generic thumbnailer we use in PiTiVi (pitivi/thumbnailer.py and pitivi/elements/thumbnailsink.py).
December 8, 2008 3:19 AM
You can also have a look at the code I have written for Advene, which exports the playbin _frame property to png, using a gstreamer pipeline. See snapshot() method in http://svn.gna.org/viewcvs/advene/trunk/lib/advene/player/gstreamer.py?view=markup
January 4, 2009 3:33 PM
The strategy I'm using in pitivi right now is similar to the thumbnailer which edward mentioned. Except it produces a cairo surface instead of a pixbuf, it caches multiple thumbnails by timestamp, and it can draw a sequence of thumbnails into a cairo context when asked to do so. The goal is to separate the fetching/caching of thumbnails from the display code, so that the two can happen asynchronously, and also to make sure that drawing a long strip of thumbnails doesn't slow down updates.