How to install Gstreamer Python Bindings
3 min. read |
Development for Gstreamer could be quite challenging at the beginning. But there is a lifeboard, – Gstreamer Python Bindings. With Python it is much easier to understand basic Gstreamer concepts and at the same time to speed up applications development.
Requirements
- Ubuntu 18
- Python 3.6
Guide
Personal experience
Gstreamer is written on pure C. I worked with C/C++ for almost 5 years. But at first it was still quite difficult to use it and prototype video analytics applications within short deadlines. And almost all logic for such applications often is written in Python using OpenCV, Tensorflow. But with Gstreamer Bindings for Python it was much easier to build applications using advantages of Gstreamer’s flexibility and Python’s simplicity. Now I could hide any image processing in Gstreamer pipeline and for analytics pipeline just use decoded RGB buffer.
Dockerfile
Checkout Dockerfile to build Docker Image for Ubuntu 18 and Gstreamer Python Binding.
docker build -t gstreamer:python /path/to/Dockerfile
xhost +local: # To enable UI
sudo docker run --name gstreamer-python -it -e DISPLAY=$DISPLAY -v /tmp/.X11-unix/:/tmp/.X11-unix gstreamer:python
Manual
First, Install Gstreamer on Ubuntu
In addition we need to install dev package for gstreamer
sudo apt-get install gstreamer-1.0
sudo apt-get install gstreamer1.0-dev
Then, install Python specific packages.
sudo apt-get install python3.6 python3.6-dev python-dev python3-dev
sudo apt-get install python3-pip python-dev
sudo apt-get install python3.6-venv
Also install additional packages required to build Gstreamer from sources
sudo apt-get install git autoconf automake libtool
Let’s install packages for Python GObject, GObject Introspection required to make Gstreamer friends with Python.
sudo apt-get install python3-gi python-gst-1.0
sudo apt-get install libgirepository1.0-dev
sudo apt-get install libcairo2-dev gir1.2-gstreamer-1.0
Now system is ready to build gst-python package from repository.
Building gst-python from sources
First, create a test virtual environment to check installation
python3 -m venv venv
source venv/bin/activate
pip install --upgrade wheel pip setuptools
After all, install pip-requirements. Detailed requirements for Python GObject installation
pip install pycairo
pip install PyGObject
Checkout Python GObject API References. This resource is going to be main source of Gstreamer API for Python.
Gst-Python API Check
Now check that essential imports are working in python
python -c "import gi; gi.require_version('Gst', '1.0'); \
gi.require_version('GstApp', '1.0'); \
gi.require_version('GstVideo', '1.0'); \
gi.require_version('GstBase', '1.0')"
Gst-Python Plugin Check
Download gst-plugin-check.py and execute next command
python gstreamer_empty_plugin_test_case.py
If while running previous commands you got any mistakes, then proceed with next steps.
Let’s build gst-python from sources. This allows to use the latest gstreamer python bindings and align it with pre-installed gstreamer version.
git clone https://github.com/GStreamer/gst-python.git
cd gst-python
export PYTHON=/usr/bin/python3
git checkout 1.14.5
./autogen.sh --disable-gtk-doc --noconfigure
./configure --with-libpython-dir=/usr/lib/x86_64-linux-gnu --prefix venv
make
make install
Hacks
- Set PYTHON variable to change python executable location
export PYTHON=/usr/bin/python3
- Gstreamer Version Check
GSTREAMER_VERSION=$(gst-launch-1.0 --version | grep version | tr -s ' ' '\n' | tail -1)
git checkout $GSTREAMER_VERSION
- Get libpython-dir (location of libpython*m.so)
LIBPYTHON=$($PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var("LDLIBRARY"))')
LIBPYTHONPATH=$(dirname $(ldconfig -p | grep -w $LIBPYTHON | head -1 | tr ' ' '\n' | grep /))
- Get Prefix for current environment (Python Library Path)
PREFIX=$(dirname $(dirname $(which python)))
Common Issues
Element factory metadata for plugin has no valid long-name field
For example, during execution gst-plugin-check.py :
python gstreamer_empty_plugin_test_case.py
You can get the following error message
GStreamer-WARNING **: 11:02:19.587: Element factory metadata for 'plugin_name' has no valid long-name field
ImportError: Plugin plugin_name not registered
Solution. While gst-python installation the following files should be copied to PYTHON_PACKAGES_DIR/gi/overrides. Because existing files installed by pygobject could be outdated.
Gst.py
GstPbutils.py
_gi_gst.la
_gi_gst.cpython-35m-x86_64-linux-gnu.so
Note: PYTHON_PACKAGES_DIR is usually path to site-packages or dist-packages
Usually, all the files are being copied during make install execution.
But in case if you want to move files into another location you can use the following procedure.
1. Define GI_OVERRIDES_PATH:
GI_OVERRIDES_PATH=$($PYTHON -c 'import gi; import os; print(os.path.join(os.path.dirname(gi.__file__), "overrides"))')
# echo $GI_OVERRIDES_PATH
# > /usr/lib/python3/dist-packages/gi/overrides
2. Define GST_GI_OVERRIDES_PATH. Path to files generated by make inside gst-python folder
GST_GI_OVERRIDES_PATH=/path/to/gst-python/gi/overrides
# echo $GST_GI_OVERRIDES_PATH
# > /home/gst-python/gi/overrides
3. Now, copy required files from GST_GI_OVERRIDES_PATH to GI_OVERRIDES_PATH
cp $GST_GI_OVERRIDES_PATH/Gst*.py $GI_OVERRIDES_PATH
cp $GST_GI_OVERRIDES_PATH/_gi_gst.* $GI_OVERRIDES_PATH
This should fix previous error.
Note: The only time I needed this is when I was installing gst-python with prefix /usr. Because in that case all files are being install into ../site-packages folder, but python uses ../dist-packages. In that case manual files transfer helps.
But in general, I suggest you to use venv. In such a case python uses ../site-packages folder
Notes
- All previous guide tested in docker container
- With gstreamer-python you can easily install Gstreamer Python Bindings (Make sure all packages are already installed). Also check installation console output
pip install git+https://github.com/jackersson/gstreamer-python.git@{tag_name}#egg=gstreamer-python
- Complete gst-python installation script
Repeat Gst–Python API Check.
Hope everything works as expected. Finally, in case of any errors, mistakes or problems leave comments down here. I’d be happy to find out solution with you 😉
Thanks for the tutorial. The “gstreamer_empty_plugin_test_case.py” did not work under Python3.6 It works under Python2.7.
In Python3 env, the error shows “ImportError: Plugin gstplugin_py not registered”
Hey Yu You,
Can you provide full installation steps, so we can find the problem?
******
Because, the complete guide was tested in docker container (Ubuntu 18, Python 3.6). Check also gst-python installation script. And console output after installation
Best regards,
I followed exactly and tested both Docker env (your Dockerfile) under Ubuntu 18 and my local host (OSX). Both envs are Python 3.6 and GStreamer versions 1.14.5 and 1.16.2.
Within the conaine, I ran “bash build-gst-python.sh” and everything built and installed. For example, it says:
Python Executable: /usr/bin/python3
Python Library Path: /usr/lib/x86_64-linux-gnu
Current Python Path /usr
Gstreamer Version: 1.14.5
When I run “pytho3 gstreamer_empty_plugin_test_case.py” and exception happended:
(python3:6761): GStreamer-WARNING **: 08:48:59.055: Element factory metadata for ‘gstplugin_py’ has no valid long-name field
Traceback (most recent call last):
File “gstreamer_empty_plugin_test_case.py”, line 121, in
register(GstPluginPy)
File “gstreamer_empty_plugin_test_case.py”, line 117, in register
raise ImportError(“Plugin {} not registered”.format(name))
ImportError: Plugin gstplugin_py not registered
Hi,
Updated a post with the guide how to avoid such a problem (check Common Issues section). I also had such a problem a lot)
But, in general, I suggest to install gst-python to venv (instead of /usr).
Hope this helps 😉
what the hell is up with these code blocks, i love how the toolbar blocks the first line of code whenever the cursor hovers over
Hi,
Totally agree 😉 Fixed it. Thanks for notice)
Are this tutorial only for Ubuntu 18, what should I change for Ubuntu 16.04?
It works on Ubuntu 16.04 with Python 2.7 but with python 3.5 no, it has some errors ?
Hi Anas,
This should work for both Ubuntu 18/16. In previous comments there is a similar question (author: Yu You). The solution is described in Common Issues Section. I suggest you to install bindings into local environment (ex.: venv). Otherwise, you’ll need to copy built files in manual way 😉
Good luck 😉
Thank you for you quick response,
I have tried to put the python executable path to the same python inside the environment ~/.virtualenvs/cv/bin/python
It gave me this error:
checking for headers required to compile python extensions… not found
configure: error: could not find Python headers
But if I put /usr/bin/python3 it works. why it is not working in virtual enviroment
Yes, I have a similar problem. For example, in gst-python installation script I use /usr/bin/python3, and not the ../venv/bin/python.
It is due to the fact that ./configure script is looking for Python.h location via python-config utility. For example:
/usr/bin/python3-config --includes
But in venv there is no: python-config, and no Python.h in venv/includes.
And the main effect of gst-python installation is to update specific *.py files and put *.so into lib/ folder. So, it is ok to use global /usr/bin/python3.
Thanks a lot, I have tried it and every thing is working fine now
According to your instructions, there is an error in executing the command, how to solve it:
./configure –with-libpython-dir=/usr/lib/x86_64-linux-gnu
………………….
checking for PYGOBJECT… configure: error: Package requirements (pygobject-3.0 >= 3.8) were not met:
No package ‘pygobject-3.0’ found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables PYGOBJECT_CFLAGS
and PYGOBJECT_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
Hi Guo,
Thanks for mentioning that 😉
In general I get this error only when I forget to install pygobject with:
pip install pygobject
So, if this package is already properly installed then everything should work like a charm.
gst-launch-1.0 videotestsrc ! videoconvert ! gstvideocrop left=10 top=20 bottom=10 right=20 ! videoconvert ! xvimagesink
Setting pipeline to PAUSED …
Pipeline is PREROLLING …
Pipeline is PREROLLED …
Setting pipeline to PLAYING …
New clock: GstSystemClock
This is OK.
gst-launch-1.0 videotestsrc ! gaussian_blur kernel=9 sigmaX = 5.0 sigmaY=5.0 ! videoconvert ! autovideosink
Setting pipeline to PAUSED …
Pipeline is PREROLLING …
ERROR: from element /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0: Internal data stream error.
Additional debug info:
gstbasesrc.c(3055): gst_base_src_loop (): /GstPipeline:pipeline0/GstVideoTestSrc:videotestsrc0:
streaming stopped, reason not-negotiated (-4)
ERROR: pipeline doesn’t want to preroll.
Setting pipeline to NULL …
Freeing pipeline …
But this gave a error.
Hi Guo,
This is probably due to autovideosink element, because both pipelines with gstvideocrop and gaussian_blur are the same. In fact both pipelines work just fine on my PC and in docker container provided in the post.
Also checkout that gstvideocrop’s caps same as gaussian_blur’s caps (use gst-inspect-1.0 for each element).
So, what you can do:
1. Try append videoconvert before gaussian_blur to force pipeline to convert caps to same format.
gst-launch-1.0 videotestsrc ! videoconvert ! gaussian_blur kernel=9 sigmaX = 5.0 sigmaY=5.0 ! videoconvert ! autovideosink
2. Try use another sink (fakesink, gtksin, xvimagesink, …) instead of autovideosink.
3. Debug pipeline (add -v flag) to check what causes the problem, and what sink is picked by autovideosink:
gst-launch-1.0 videotestsrc ! gaussian_blur kernel=9 sigmaX = 5.0 sigmaY=5.0 ! videoconvert ! autovideosink -v
Hope this helps.
Keep me updated on problem progress 😉
Hello taras.lishchenko, first of all i would like to say thanks for this great tutorial ??
I’m newbie in gstreamer, so i tried your example code in gstreamer-python repo. I’ve tried gst_capture.py and its running well. But, when i change string pipeline using uridecodebin, i’ve got error like this,
Traceback (most recent call last):
File “/home/stezar/miniconda3/envs/gpu/lib/python3.6/site-packages/gstreamer/gst_tools.py”, line 627, in _on_buffer
self._queue.put(self._extract_buffer(sample))
File “/home/stezar/miniconda3/envs/gpu/lib/python3.6/site-packages/gstreamer/gst_tools.py”, line 604, in _extract_buffer
c = get_num_channels(video_format)
File “/home/stezar/miniconda3/envs/gpu/lib/python3.6/site-packages/gstreamer/utils.py”, line 27, in get_num_channels
return _CHANNELS[fmt]
KeyError:
——————————————————-
this is my pipeline string:
uridecodebin uri=rtspt://freja.hiof.no:1935/rtplive/definst/hessdalen03.stream ! nvvideoconvert ! video/x-raw, format=NV12, width=1024, height=576 ! videoconvert ! appsink emit-signals=True sync=false
is there anything wrong?
Thank you for your help
Hey,
Thanks for noticing this 😉
I’ve updated the code in repository, now it supports any formats (before that is was only RGB{x}/Gray images).
Also I’ve added example run_appsink. This is more flexible example, so you can have access to format conversion and add any format you want. You can launch your pipeline with:
python3 examples/run_appsink.py -p "uridecodebin uri=rtspt://freja.hiof.no:1935/rtplive/definst/hessdalen03.stream ! nvvideoconvert ! video/x-raw,format=NV12,width=1024,height=576 ! videoconvert ! appsink emit-signals=True sync=false"
Also maybe RGB-based formats is better to use for appsink for image processing tasks. As NV12 a bit hard to interpret with numpy
Hope this helps 😉
Best regards,
Thanks,
When the buffer converted to numpy array, Is there a disadvantage for this solution? Is it possible to directly modify the buffer without converting to numpy array? with converting buffer to array this use two memory used or used only once because of pointer if buffers?
No,
Gst.Buffer -> np.ndarray is very fast operation (12.3 us for 2560x3840x3, CPU i7-7700HQ,2.80GHz). So the memory is shared. You can also verify this by modifying the resulted np.ndarray and see the result in output window 😉
In Python I think np.ndarray is the best solution to work with Gst.Buffer memory 😉
Thank you for your help, very appreciate it! 🙂
Is it possible to run without with statement for GstContext and GstPipeline? Because i wanna implement RTSP Server like this (https://github.com/madams1337/python-opencv-gstreamer-examples/blob/master/gst_rtsp_server.py). I little bit confused how to merge your script into that script.
Thanks.
Hi Stezar,
Yes, you can easily launch pipelines without any GstContext, GstPipeline. Checkout “How to launch gstreamer pipeline in Python” (there are simple code samples).
Also, there is a sample with launching rtsp server using GstContext/GstPipeline (but code is still under development).
Best regards,
Thanks taras.lishchenko. i’ll try
Recently i’ve found that my gst-python didn’t built properly. I’ve stcuk in this step
—————————————
checking for GST… yes
checking for PYGOBJECT… configure: error: Package requirements (pygobject-3.0 >= 3.8) were not met:
No package ‘pygobject-3.0’ found
———————————
i’ve already install pycairo and PyGObject from pip, but it fails when ./configure.
Thanks
Check out this comment (similar problem with pygobject-3.0)
Hello.
Thanks for the great post
I did all the steps mentioned above on venv, when I run the test, give me error
ImportError: cannot import name ‘_gi_gst’ from ‘gi.overrides’ (/../lib/python3.8/site-packages/gi/overrides/__init__.py)
In the manual copy step I only found
Gst.py
GstPbutils.py and I changed their directories.
please help