Guide to set up DeepStream pyds and run an RTSP pipeline in Python with Smart Video Record.
Note: NVIDIA Smart Recording isn’t in official Python bindings and is supported only in C++. NVIDIA Smart Video Record isn’t in the official Python bindings and is supported only in C++. This guide includes the minimal tweaks to enable Smart Video Recording from Python, and we’ve added a complete example script that shows how to trigger start/stop, handle the sr-done callback, and save clips to disk. We’d love your help making this repo a one-stop place for DeepStream wheels with Smart-Record—if you’ve built a working wheel for your setup, please open a Pull Request so others can use it too!
Depeding of the version you are trying to install
Ubuntu 22.04 · Python 3.10 · DeepStream 7.1
Python 3.10 is required (3.8 will not work).
Ubuntu 24.04 · Python 3.12 · DeepStream 8.0
Python 3.12 is required (3.8 will not work).
- Prerequisites
- Clone in the Correct Location
- Initialize Submodules
- Build & Install gst-python
- Edit C++ files
- Additional required fixes
- Edit CMakeLists.txt
- Compiling the bindings
- Verify
- Troubleshooting
- Credits / Acknowledgements
Download and install DeepStream SDK (and dependencies) from:
After installation, you should have a path like:
/opt/nvidia/deepstream/deepstream-X.XNOTICE THAT X.X IS YOUR DEEPSTREAM VERSION, please edit according your version (e.g 7.1,8.0)
Install development packages required to build the bindings and gst-python:
sudo apt update
sudo apt install -y \
python3 python3-pip python3-dev python3.10-dev \
python3-gi python3-gst-1.0 python-gi-dev \
git meson ninja-build cmake g++ build-essential \
libglib2.0-dev libglib2.0-dev-bin libgstreamer1.0-dev \
libtool m4 autoconf automake \
libgirepository1.0-dev libcairo2-devInstall the PyPA build backend (used to create the wheel):
python3 -m pip install --upgrade pip
python3 -m pip install buildDeepStream expects the Python apps under sources/. NOTICE THAT X.X IS YOUR DEEPSTREAM VERSION, please edit according your version (e.g 7.1,8.0)
export DS_ROOT=/opt/nvidia/deepstream/deepstream-X.X
sudo mkdir -p "$DS_ROOT/sources"
sudo chown -R "$USER":"$USER" "$DS_ROOT/sources"
cd "$DS_ROOT/sources"
git clone https://github.com/NVIDIA-AI-IOT/deepstream_python_appsYou should now have:
/opt/nvidia/deepstream/deepstream-X.X/sources/deepstream_python_appsPull the gst-python and pybind11 submodules:
cd "$DS_ROOT/sources/deepstream_python_apps"
git submodule update --init
python3 bindings/3rdparty/git-partial-submodule/git-partial-submodule.py restore-sparseBuild and install gst-python so GStreamer’s Python bindings match your build:
cd "$DS_ROOT/sources/deepstream_python_apps/bindings/3rdparty/gstreamer/subprojects/gst-python/"
meson setup build
cd build
ninja
sudo ninja installMake the following source additions to enable Smart Recording–related types and helpers. This files are already ready to use in the folder bindings, so you can just replace the files.
Apply the following changes to bindings/src/bindfunctions.cpp:
diff --git a/bindings/src/bindfunctions.cpp b/bindings/src/bindfunctions.cpp
index eade8d5..7a4b459 100644
--- a/bindings/src/bindfunctions.cpp
+++ b/bindings/src/bindfunctions.cpp
@@ -586,7 +586,7 @@ namespace pydeepstream {
std::function<utils::RELEASEFUNC_SIG> const &func) {
utils::set_freefunc(meta, func);
},
- py::call_guard<py::gil_scoped_release>(),
+ py::call_guard<py::gil_scoped_release>(),
"meta"_a,
"func"_a,
pydsdoc::methodsDoc::user_releasefunc);
@@ -601,10 +601,9 @@ namespace pydeepstream {
// Required for backward compatibility
m.def("unset_callback_funcs",
[]() {
- utils::release_all_func();
- },
- py::call_guard<py::gil_scoped_release>()
- );
+ utils::release_all_func();
+ },
+ py::call_guard<py::gil_scoped_release>());
m.def("alloc_char_buffer",
[](size_t size) {
@@ -650,6 +649,14 @@ namespace pydeepstream {
py::return_value_policy::reference,
pydsdoc::methodsDoc::get_ptr);
+ m.def("get_native_ptr",
+ [](size_t ptr) {
+ return (gpointer) ptr;
+ },
+ "ptr"_a,
+ py::return_value_policy::reference,
+ pydsdoc::methodsDoc::get_ptr);
+
m.def("strdup",
[](size_t ptr) -> size_t {
char *str = (char *) ptr;Apply the following changes to bindings/src/utils.cpp
diff --git a/bindings/src/utils.cpp b/bindings/src/utils.cpp
index 9f97794..009314a 100644
--- a/bindings/src/utils.cpp
+++ b/bindings/src/utils.cpp
@@ -28,6 +28,7 @@
#include "nvdsmeta_schema.h"
#include "utils.hpp"
#include "nvds_obj_encode.h"
+#include "gst-nvdssr.h"
#include "bind_string_property_definitions.h"
#include "../../docstrings/utilsdoc.h"
@@ -103,6 +104,48 @@ namespace pydeepstream {
},
py::return_value_policy::reference,
pydsdoc::utilsdoc::NvDsObjEncUsrArgsDoc::cast);
+
+ py::enum_<NvDsSRContainerType>(m, "NvDsSRContainerType")
+ .value("NVDSSR_CONTAINER_MP4", NVDSSR_CONTAINER_MP4)
+ .value("NVDSSR_CONTAINER_MKV", NVDSSR_CONTAINER_MKV)
+ .export_values();
+
+ py::class_<NvDsSRRecordingInfo>(m, "NvDsSRRecordingInfo")
+ .def(py::init<>())
+ .def_property("filename", STRING_FREE_EXISTING(NvDsSRRecordingInfo, filename))
+ .def_property("dirpath", STRING_FREE_EXISTING(NvDsSRRecordingInfo, dirpath))
+ .def_readwrite("duration", &NvDsSRRecordingInfo::duration)
+ .def_readwrite("containerType", &NvDsSRRecordingInfo::containerType)
+ .def_readwrite("width", &NvDsSRRecordingInfo::width)
+ .def_readwrite("height", &NvDsSRRecordingInfo::height)
+ .def_readwrite("containsVideo", &NvDsSRRecordingInfo::containsVideo)
+ .def_readwrite("channels", &NvDsSRRecordingInfo::channels)
+ .def_readwrite("samplingRate", &NvDsSRRecordingInfo::samplingRate)
+ .def_readwrite("containsAudio", &NvDsSRRecordingInfo::containsAudio)
+ .def("cast", [](size_t data) {
+ return (NvDsSRRecordingInfo *) data;
+ },
+ py::return_value_policy::reference)
+ .def("cast", [](void* data) {
+ return (NvDsSRRecordingInfo *) data;
+ },
+ py::return_value_policy::reference);
+ struct SRUserContext {
+ int sessionid;
+ char name[32];
+ };
+ py::class_<SRUserContext>(m, "SRUserContext")
+ .def(py::init<>())
+ .def_readwrite("sessionid", &SRUserContext::sessionid)
+ .def_property("name", STRING_CHAR_ARRAY(SRUserContext, name))
+ .def("cast", [](size_t data) {
+ return (SRUserContext *) data;
+ },
+ py::return_value_policy::reference)
+ .def("cast", [](void* data) {
+ return (SRUserContext *) data;
+ },
+ py::return_value_policy::reference);
}
}Keep all of the above inside
namespace pydeepstream { ... }.
Some builds fail around the STRING_CHAR_ARRAY helper used for fixed-size char[] fields.
File: bindings/src/utils.hpp -- macro for fixed-size char[]
Replace the existing macro with:
#ifndef STRING_CHAR_ARRAY
#define STRING_CHAR_ARRAY(Type, member) \
[](Type &self) -> std::string { \
return std::string(self.member); \
}, \
[](Type &self, const std::string &v) { \
std::snprintf(self.member, sizeof(self.member), "%s", v.c_str()); \
self.member[sizeof(self.member) - 1] = '\0'; \
}
#endif#include <cstdio> // for std::snprintfUpdate the build system to target the version you need e.g. CMake 3.10, Python 3.10, and (optionally) a versioned DeepStream path.
e.g Require CMake 3.10 (was 3.12)
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)e.g Default Python version: 3.10 (was 3.12)
check_variable_set(PYTHON_MAJOR_VERSION 3)
check_variable_set(PYTHON_MINOR_VERSION 10)e.g Allowed Python minor version: 10 (was 12)
set(PYTHON_MINVERS_ALLOWED 10)
check_variable_allowed(PYTHON_MINOR_VERSION PYTHON_MINVERS_ALLOWED)Versioned DeepStream path (replace X.X, e.g., 7.1)
check_variable_set(DS_PATH "/opt/nvidia/deepstream/deepstream-X.X")(Optional generic form)
check_variable_set(DS_VERSION "7.1")
check_variable_set(DS_PATH "/opt/nvidia/deepstream/deepstream-${DS_VERSION}")Output: a Python wheel under
bindings/dist/that you can install withpip.
cd "$DS_ROOT/sources/deepstream_python_apps/bindings"
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
python3 -m build
cd dist
python3 -m pip install --force-reinstall *.whlcd "$DS_ROOT/sources/deepstream_python_apps/bindings"
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
python3 -m build
cd dist
python3 -m pip install --force-reinstall *.whlcd "$DS_ROOT/sources/deepstream_python_apps/bindings"
export CMAKE_ARGS="-DIS_SBSA=on"
export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
python3 -m build
cd dist
python3 -m pip install --force-reinstall *.whlpython3 - <<'PY'
import gi
gi.require_version("Gst","1.0")
from gi.repository import Gst
Gst.init(None)
import pyds
print("Gst OK, pyds OK")
# new alias should exist
assert hasattr(pyds, "get_native_ptr")
print("get_native_ptr OK")
PY- Python version mismatch:
python3 --versionmust be 3.10.x. Usepython3.10explicitly if needed. - Missing Ninja: Ensure
ninja-buildis installed. - DeepStream path: If you changed
DS_PATH, confirm headers/libs exist under that folder. - GStreamer/GLib headers: Install
libgstreamer1.0-devandlibglib2.0-dev. - Clean rebuild:
cd "$DS_ROOT/sources/deepstream_python_apps/bindings" git clean -fdX build dist *.egg-info export CMAKE_BUILD_PARALLEL_LEVEL=$(nproc) python3 -m build cd dist && python3 -m pip install --force-reinstall *.whl
We’d love your help making this repo a one-stop place for DeepStream wheels.
If you’ve successfully built a wheel that works on your setup, please open a Pull Request and add it so others can use it too!
- Wheel file (
.whl) built for a specific stack (DeepStream/JetPack/Ubuntu), architecture, and Python version. - Checksums: a
SHA256SUMS.txtin the same folder as the wheel, and (if possible) update the rootSHA256SUMS.txt. - (Optional) Constraints file if special pins are needed (e.g.,
numpy==1.26.0).
wheels/<package>/<version>/
└── DS-<DS_MAJOR.MINOR>_JP<JP_MAJOR.MINOR>_UBU<UBUNTU_MAJOR.MINOR>/
└── <arch>/
└── cp<PYMAJMIN>/
├── <original-wheel-name>.whl
└── SHA256SUMS.txtNotes
archislinux_x86_64(PC) oraarch64(Jetson).cp312= Python 3.12;cp310= Python 3.10, etc.- Keep the original wheel filename intact.
- DeepStream version (e.g.,
DS 8.0orDS 7.1) - JetPack & Ubuntu (e.g.,
JP 6.1 / Ubuntu 22.04) - Python version (e.g.,
3.12) - Architecture (
x86_64oraarch64) - Any special constraints (e.g.,
numpy==1.26.0)
- Wheel placed in the correct folder structure.
- Short compatibility section in the PR description.
Thanks for sharing your builds—your contribution helps the whole community install reliably without rebuilding! 🙌
This repository’s Smart Video Record support for DeepStream Python bindings is heavily inspired by the patch and example shared by @fanzh on the NVIDIA Developer Forums:
- DeepStream SDK FAQ – “[Use nvurisrcbin plugin to do smart record in Python]”
https://forums.developer.nvidia.com/t/deepstream-sdk-faq/80236/41
The C++/Python changes to enable Smart Record (NvDsSRRecordingInfo, SRUserContext,
get_native_ptr, and the nvurisrcbin usage pattern) are adapted from that post.