Updating the Pipeline#
The loitering detection pipeline is a DL Streamer Pipeline Server pipeline: a GStreamer
gst-launch-style string plus a small REST-overridable parameters schema, both defined in one
JSON file. This guide covers where it lives, what each stage does, and how to change it safely.
Note
This page is about editing the pipeline definition itself (config.json - adding/removing
GStreamer elements, changing what is hardcoded vs REST-overridable). To use the pipeline as-is
add a zone, add a new stream, pick a different model, read the published MQTT data - see Customize the Application instead; nothing there requires editing this file.
Where it lives#
File:
loitering-detection/src/dlstreamer-pipeline-server/config.jsonZone definitions:
loitering-detection/src/dlstreamer-pipeline-server/zones/*.json
Both are bind-mounted into the dlstreamer-pipeline-server container (see
compose-without-scenescape.yml), so editing them on the host and recreating that one container
is enough - no image rebuild:
docker compose up -d --force-recreate dlstreamer-pipeline-server
config.json is only read at container start, so this restart is required even for a small
pipeline-string edit; it also drops every currently-running stream (CLI and Console UI alike).
Structure of config.json#
{
"config": {
"pipelines": [
{
"name": "object_tracking_gpu",
"source": "gstreamer",
"pipeline": "{auto_source} name=source ! ... ! appsink name=destination",
"parameters": {
"type": "object",
"properties": {
"detection-properties": { "element": { "name": "detection", "format": "element-properties" } }
}
}
}
]
}
}
One object per device variant - this app defines
object_tracking_cpu,object_tracking_gpu,object_tracking_npu, selected by whicheverdevicethe caller (Console UI orsample_start.sh) asked for.pipelineis the actual GStreamer pipeline, written exactly like agst-launch-1.0command line.{auto_source}is substituted by the Pipeline Server for whateversource.type/source.urithe REST request supplies (a file or RTSP URL here).parameters.propertiesdeclares which elements can have properties overridden per REST request, by name. Each entry maps a request-time key (e.g."detection-properties") to a pipeline elementname=...and its GObject property, letting one static pipeline definition serve many different models/zones/devices without editing the file per request.
The pipeline stage-by-stage#
{auto_source} ! <decode> ! gvadetect ! gvatrack ! gvaanalytics ! loitering_watermark ! gvametaconvert ! appsink
Stage |
Purpose |
|---|---|
|
Decode the source video; GPU/NPU decode into |
|
Runs the detection model on the full frame |
|
Assigns/keeps a stable id per object across frames. |
|
Matches each tracked object against the active zone(s) (polygons from the zone file, or a custom rectangle - see below), computes dwell time, and draws the zone outline(s). This is the only zone-awareness in the pipeline - it decides what counts toward the loiter table, not what gets boxed. |
|
Burns zone/dwell-time text onto the video itself, toggled by the Console UI’s “Show dwell-time overlay” checkbox ( |
|
Serialises detections + zone/dwell info into the JSON published to MQTT, including empty-frame results. |
|
Hands frames+metadata to the Pipeline Server, which fans them out to the configured destinations (MQTT for metadata, WebRTC for video). |
What overrides what, per request#
Both the Console UI (console-addon/console/api_pipelines.py, function _launch) and the CLI
sample (sample_start.sh) call POST /pipelines/{name}/{version} with a parameters object
matching config.json’s schema:
Request key |
Element it targets |
What it sets |
|---|---|---|
|
|
|
|
|
|
|
|
|
There is no live-update path: changing any of these (switching model, device, or zone)
always stops the current pipeline instance and starts a brand new one with the new parameters -
confirmed in dlstreamer-pipeline-server’s own logs, where a zone/model change shows as a
Pipeline <old-id> Ended / Aborted line immediately followed by a new
Creating Instance of Pipeline user_defined_pipelines/<name> with a different instance id.
Adding or changing a stage#
Edit the
pipelinestring for the device variant(s) you want to change - keep the three variants (CPU/GPU/NPU) consistent unless the change is genuinely device-specific.If the new/changed element needs to be overridable per request, add it to every pipeline’s
parameters.propertieswith a uniqueelement.namematching aname=...you gave it in thepipelinestring.For a new
gvapythonstage, drop the.pyfile underconfigs/(already bind-mounted) and reference it withmodule=/home/pipeline-server/configs/<file>.py class=<ClassName>.Recreate the container (see above) and verify with:
docker logs dlstreamer-pipeline-server --tail 50
A malformed pipeline string fails loudly here at container start, before any stream is ever requested.