Open Menu
GStreamer Python Bindings for Windows
developer

GStreamer Python Bindings for Windows

User Name

Escrito por:

Andoni Morales

29 de Noviembre de 2023

GStreamer is an incredibly powerful and flexible open-source multimedia framework that enables developers to create almost any kind of multimedia application, including media players, non-linear video editors, streaming services, or video conferencing systems. However, developing GStreamer applications can be challenging since the framework has an extensive API with a steep learning curve, which, combined with its C API, can act as an entry barrier for new developers.

The GStreamer Python bindings offer a very convenient way to write GStreamer applications and plugins, both for newcomers taking their first steps in the frameworks and for experienced developers needing to prototype a plugin or a multimedia application quickly. They provide complete access to the API in an idiomatic way, allowing anyone familiar with Python to start leveraging all the power of GStreamer immediately. The bindings are based on PyGObject with an additional layer of overrides to make them more idiomatic.

Even though the Python bindings have existed for a long time, they aren't packaged in the official Windows installers and need to be built manually, involving several steps. Thanks to work done by Fluendo, it's now possible to build the Python bindings with meson and subprojects as part of the regular GStreamer monorepo build, simplifying this process a lot.

In this blog post, we will explain the work done to achieve this milestone and a guide on building and using the bindings.

Building GObject Introspection as a meson subproject

The first part of getting the bindings building with meson was adding support to build GObject Introspection as a meson subproject. The main problem is that the GLib introspection data (the .gir's and .typelib's for GLib, GObject, etc...) is built by GObject Introspection instead of done by GLib and GObject Introspection depends on GLib, creating a circular dependency between them. This means GObject Introspection needs to retrieve some information from the GLib subproject, such as the location of the source files and headers for example.

Another problem is that GObject Introspection can't use meson's gnome.generate_dir since this meson module requires the 'gobject-introspection-1.0' dependency that is provided by GObject Introspection itself, which is a chicken-egg problem. This means all of the gir's need to be built with custom commands (in this MR we solved the problem for when GObject Introspection is a subproject dependency, but it wouldn’t work when it's a pkg-config dependency)

Fixing everything required several MRs on both GLib and GObject Introspection:

Some work is planned to break that circular dependency and improve the current situation.

Adding introspection support in GStreamer

The second part involved enabling introspection to build in GStreamer with meson using subprojects. The work done here consisted of adding GObject Introspection as a subproject, ensuring the introspection, and enabling the python and introspection options in the Windows CI jobs. All this work is upstream, and it was merged in the gi: support gi generation with subprojects MR

GStreamer Python Bindings on Windows

All the work described in the previous steps makes it now possible to build the GStreamer Python bindings using the monorepo and subprojects. In this section, we will explain how to set up the build environment, build the bindings, and use our freshly built bindings.

Building the bindings

Building the GStreamer bindings is now a straightforward process compiling from the main branch.

The first step is to check out the GStreamer sources

    git clone https://gitlab.freedesktop.org/gstreamer/gstreamer.git
    cd gstreamer


GObject Introspection requires pkg-config, which GStreamer provides through a subproject. Due to a limitation in Meson, we still need to instruct g-ir-scanner on how to find it with the PKG_CONFIG environment variable. This is only required if you don't have pkg-config available in your PATH.

    $env:PKG_CONFIG="${pwd}\subprojects\win-pkgconfig\pkg-config.exe"


Let's now configure the project with introspection enabled and set the installation path to c:\gstreamer-python:

    meson setup build -Dintrospection=enabled --prefix c:/gstreamer-python


If everything is correct, you should gobject-introspection and gst-python reporting YES in the subprojects summary:

    gobject-introspection      : YES 4 warnings (from gst-python => pygobject)
    gst-python                 : YES 1 warning


Let's finally build and install everything:

    meson compile -C .\build
    meson install -C .\build


To verify everything was built and installed correctly, you can check the following files were installed:

    C:/gstreamer-python\lib\girepository-1.0\Gst-1.0.typelib
    C:/gstreamer-python\lib\site-packages\gi\module.py
    C:/gstreamer-python\lib\site-packages\gi\overrides\Gst.py


Let's wrap it up:

    git clone https://gitlab.freedesktop.org/gstreamer/gstreamer.git
    cd gstreamer
    $env:PKG_CONFIG="${pwd}\subprojects\win-pkgconfig\pkg-config.exe"
    meson setup build --prefix c:/gstreamer-python
    meson compile -C .\build
    meson install -C .\build

Using the bindings

To use the bindings in our applications, we will need to let our application know where GI's Python module and GStreamer are installed. We will show how to do it with this sample application that prints the GStreamer version:

    import gi
    gi.require_version('Gst', '1.0')
    from gi.repository import Gst
    Gst.init(sys.argv)
    print(Gst.version_string())


We will see different errors if we try to launch this application without configuring it correctly. Let's solve them one by one in the next sections.

Unable to find the GI module from the GStreamer installation

The first issue is that Python is unable to locate the PyGObject's GI module:

    ModuleNotFoundError: No module named 'gi'


We need to let Python know where our freshly built module adding the site-packages directory to the sys.path

    import sys
    sys.path.append('C:/gstreamer-python/Lib/site-packages')


This can also be done with an environment variable:

    env:PYTHONPATH="C:/gstreamer-python/Lib/site-packages"

 

Unable to load GI's C extension

The next issue we will see is that we are unable to load our module because it can't load GI's C extension:

    ImportError: DLL load failed while importing _gi: 
    The specified module could not be found.


This happens because GI's module C extension links to GLib and GObject Introspection, among other libraries, and Python cannot find them. Starting with Python 3.8, DLL's search paths must be added with os.add_dll_directory since PATH is no longer used to resolve dependencies for imported extension modules.

    os.add_dll_directory('C:/gstreamer-python/bin')

 

Unable to initialize GStreamer

The next issue when trying to import the GStreamer module is that it's unable to locate the GStreamer shared library: 'gstreamer-1.0-0.dll'

    Failed to load shared library 'gstreamer-1.0-0.dll' referenced by the typelib: 'gstreamer-1.0-0.dll': 
    The specified module could not be found.


To fix it, we also need to add our binaries directory to PATH so that shared libraries can be resolved by the dynamic linker:

    os.environ['PATH'] = 'C:/gstreamer-python/bin'

This can also be done with an environment variable in PowerShell:

    env:PATH="C:/gstreamer-python/bin;$env:PATH"

 

Application

After initializing our application correctly, everything should be working correctly. Let's wrap it up:

    import os
    import sys
    from pathlib import Path

    gst_install_dir = Path('c:/gstreamer-python')
    gst_bin_dir = gst_install_dir / 'bin'
    sys.path.append(str(gst_install_dir / 'Lib' / 'site-packages'))
    os.environ['PATH'] = str(gst_bin_dir)
    os.add_dll_directory(gst_bin_dir)

    import gi
    gi.require_version('Gst', '1.0')
    from gi.repository import Gst
    Gst.init(sys.argv)
    print(Gst.version_string())


Next steps

We are working on building the Python bindings with cerbero and shipping them as part of the official installers. Most of the comments from this MR have been resolved, and we hope to have it merged for the next stable release. Stay tuned for our next update!

Da el salto con tus experiencias multimedia

Navega a través de nuestra lista de códecs de audio y video. Entiende por qué ofrecemos servicios de alta calidad para industrias de todos los tamaños.

¡Contacta con un experto!
Grid
Decor