How to launch Gstreamer pipeline in Python

5 min. read |

Common use of Gstreamer is through command line. In the next post we are going to launch Gstreamer pipeline from Python. This could be helpful for those who have already working pipeline and want to debug/extend it with own code.

Requirements

Code

What you’ll learn?

Go through next simple steps and learn how to launch Gstreamer pipeline within Python script in two common ways:

  • with Gst.parse_launch
  • with Gst.ElementFactory

Guide

Setup gst-python-tutorials

git clone https://github.com/jackersson/gst-python-tutorials.git
cd gst-python-tutorials

python3 -m venv venv
source venv/bin/activate

pip install --upgrade wheel pip setuptools
pip install --upgrade --requirement requirements.txt

Basics

Import

At first import Gstreamer into Python script. Common libraries to import are GstGObject, GstApp, GstVideo, etc. To explore all of them use Python GObject API reference.

import gi 
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GObject

Note: If you do not specify gi.require_version you’ll get warning message:

Gst was imported without specifying a version first. \
Use gi.require_version('Gst', '1.0') before \
import to ensure that the right version gets loaded

Init Gstreamer

Gst.init(sys.argv)

This call initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins.

Note: if you do not call Gst.init you’ll get next error:

gi.overrides.Gst.NotInitialized: Please call \
Gst.init(argv) before using GStreamer

Define Pipeline

Gstreamer Pipeline is simple container of ordered elements through which data flows in specific direction, from Src to Sink

For simplicity we’ll use “hello world” pipeline. Check it in your terminal.

gst-launch-1.0 videotestsrc num-buffers=50 ! autovideosink

Following pipeline generates 50 buffers of next video pattern. Hope you got similar window.

videotestsrc Gstreamer plugin

Let’s init this pipeline in python.

Init Pipeline in Python

Note: Gstreamer Pipeline in Python: Gst.Pipeline

With Gst.parse_launch

This method is fast and useful when you don’t want to handle connections between plugins manually and just want to launch some existing pipeline. Creating pipeline with Gst.parse_launch is very simple and flexible solution.

# Gst.Pipeline
pipeline = Gst.parse_launch("videotestsrc num-buffers=50 ! autovideosink")

With Gst.ElementFactory

Next approach is for those who wants to handle all elements, properties, connections. This approach requires more advanced Gstreamer knowledge.

Gst.ElementFactory is suitable when you exactly know the pipeline and don’t change it to often.

# create pipeline object 
pipeline = Gst.Pipeline() 

# create Gst.Element by plugin name 
src = Gst.ElementFactory.make("videotestsrc") 

# as Gst.Element inherit from GObject 
# we can use GObject methods to set property of element
src.set_property("num-buffers", 50) 

# create Gst.Element by plugin name 
sink = Gst.ElementFactory.make("gtksink") 

# as Gst.Pipeline is container of Gst.Elements 
# add src, sink to Gst.Pipeline 
pipeline.add(src, sink) 

# link src with sink 
# Note: elements should be elements of same Gst.Pipeline 
src.link(sink)

Start Pipeline

To start pipeline just set pipeline’s state to Gst.State.PLAYING (list of pipeline’s states)

pipeline.set_state(Gst.State.PLAYING)

To reset pipeline set NULL state:

pipeline.set_state(Gst.State.NULL)

Run GObject.MainLoop

Start GObject.MainLoop for pipeline to enable: receive signals, events, states or handle messages from Gst.Bus.

# Init GObject loop to handle Gstreamer Bus Events 
loop = GObject.MainLoop() 
try: 
    loop.run()
except: 
    loop.quit()

Handle messages with Gst.Bus

Pipeline’s Bus allows handle messages in main thread. All errors, tags, meta info could be handled by Gst.Bus

# https://lazka.github.io/pgi-docs/Gst-1.0/classes/Bus.html
bus = pipeline.get_bus()

# allow bus to emit messages to main thread bus.add_signal_watch()

# Add handler to specific signal # https://lazka.github.io/pgi-docs/GObject-2.0/classes/Object.html#GObject.Object.connect
bus.connect("message", on_message, None)

Note: Every object in Gst module is GObject itself, so a lot of capabilities from GObject are accessible. For example, in Gst.Bus with GObject’s connect you can add message handler, like this (those are basic message types that you should handle in any Gstreamer Pipeline):

def on_message(bus: Gst.Bus, message: Gst.Message, loop: GObject.MainLoop):
    mtype = message.type 
    """
        Gstreamer Message Types and how to parse
  https://lazka.github.io/pgi-docs/Gst-1.0/flags.html#Gst.MessageType 
    """ 
    if mtype == Gst.MessageType.EOS: 
        # Handle End of Stream 
        print("End of stream") 
        loop.quit()
    elif mtype == Gst.MessageType.ERROR: 
        # Handle Errors 
        err, debug = message.parse_error() 
        print(err, debug) 
        loop.quit()
    elif mtype == Gst.MessageType.WARNING: 
        # Handle warnings 
        err, debug = message.parse_warning() 
        print(err, debug) 
return True

Run Examples

python launch_pipeline/pipeline_with_factory.py
How to launch Gstreamer Pipeline in Python

Note: Look at videotestsrc patterns and try them. In previous example I changed pattern with next line of code:

src.set_property("pattern", "snow")

With pipeline_with_factory.py you can pass any pipeline

python launch_pipeline/pipeline_with_parse_launch.py \
-p "videotestsrc num-buffers=100 pattern=1 ! autovideosink"

Conclusion

Hope everything works as expected 🙂 . In case of any troubles – leave comments.

Add a Comment

Your email address will not be published. Required fields are marked *