16 Nov

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.png
Now 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!