nvidia/skills

deepstream-sop

Use this skill when building, deploying, evaluating, debugging, or measuring latency for the DeepStream SOP Inference Microservice — a GPU-accelerated FastAPI service that detects whether operators perform assembly-line steps in order via event boundary detection (GEBD) plus VLM classification. Trigger even if the user does not name it: verify operator step sequence, detect missing or out-of-order SOP steps, score factory/work-cell video for procedure compliance, run VLM-based SOP checking on i…

First seen Jul 1, 2026

Installation

$ npx skills add nvidia/skills --skill deepstream-sop

Also in this package

Other skills from nvidia/skills · top by installs.

npx skills add nvidia/skills

Browse all from nvidia/skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 3.2K
License LICENSE-APACHE
Default branch main
Open issues 5
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version1.0.0
LicenseCC-BY-4.0 AND Apache-2.0
More metadata
author
Wind Yuan <[email protected]>
tags
["deepstream","sop","vlm","triton","gpu"]
languages
["python"]
frameworks
["deepstream","triton","fastapi"]
domain
video-analytics

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 19,633 B
  • docs SUMMARY.md 981 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 669 installs

SKILL.md

DeepStream SOP Inference Microservice Skill

This skill guides AI coding assistants in building, extending, and debugging the NVIDIA DeepStream SOP (Standard Operating Procedure) Inference Microservice — a GPU-accelerated pipeline for temporal action detection and VLM-based SOP compliance monitoring on industrial video feeds.

Reference repository: https://github.com/NVIDIA/sop-monitoring-blueprints/tree/main/microservices/sop-inference-bp Local reference code: sop-inference-bp/ directory (from a local clone of the repository)


Models

Model-agnostic at both inference stages — swap via env var (and Triton dir for GEBD).

Stage Role Model class Default Swap via
Stage 1 (CV) Per-frame boundary scoring → chunk segmentation Generic Event Boundary Detection (GEBD) DDM (MCG-NJU/DDM) via Triton Python backend Replace tritonmodelrepo/<model>/ + DDMMODELPATH (§ 5)
Stage 3 (VLM) Per-chunk action classification Vision-language model via vLLM Cosmos Reason 1 7B (Reason 2 also supported) Set VLLMMODELPATH to a different HF ID or local path

"GEBD" = swappable Stage-1 slot; "DDM" = the default architecture (terms used interchangeably).

Chunking is selectable per request (§ 2): default ddm-net uses GEBD; uniform produces fixed-length chunks and bypasses Stage-1 GEBD (§ 3, § 6). DDM temporal window is configurable via FRAMESPERSIDE / SEQUENCE_BATCH (§ 4, § 5), with optional TensorRT (§ 5).


Architecture Overview

Runs in a Docker container (nvds-action-sop) alongside a Kafka container. Full diagram: [references/soparchitecture.svg](references/soparchitecture.svg).

Data flow through the 4-stage SOPVideoProcessor pipeline (per-request):

Input Sources                    Docker Container: nvds-action-sop
─────────────                    ──────────────────────────────────────────────────
Video Files ──┐                  FastAPI Server (port 8300)
RTSP Streams ─┤── base64/       ├─ /v1/chat/completions → SOPProcessManager
Basler Camera ┘   file/rtsp/       │
                  camera           │ ModelInitializer: VLM first, then DDM dummy pipeline
                                   │ 4 Thread Pools: cv(32), clip(32), vlm(64), vlm_req(64)
                                   │
                                   ▼ SOPVideoProcessor (per-request)
                                   ┌────────────────────────────────────────────────┐
                                   │ Stage 1: DeepStream Pipeline (GPU)             │
                                   │   Source → nvstreammux → tee1                  │
                                   │    ├─[inference] queue1 → nvdspreprocess       │
                                   │    │  → nvinferserver (Triton CAPI + DDM)      │
                                   │    │  → InferOutputTensorParser → score_queue  │
                                   │    ├─[frames]  queue3 → nvvideoconvert         │
                                   │    │  → capsfilter → appsink                   │
                                   │    │  → DecodedFrameRetriever → frame_queue    │
                                   │    └─[RTSP out] queue → convert → H.264 enc    │  (optional, § 18)
                                   │       → rtppay → udpsink → RTSPServer (§ 18)   │  opt-in only
                                   │              │ boundary scores                 │
                                   │              ▼                                 │
                                   │ Stage 2: Clip Post-Process                     │
                                   │   Boundary detection → chunk segmentation      │
                                   │              │ video frames + timestamps        │
                                   │              ▼                                 │
                                   │ Stage 3: VLM Inference                         │
                                   │   Embedded vLLM (Cosmos Reason 1/2)            │
                                   │   Frame sampling at VLM_FPS → classification   │
                                   │              │ action labels                    │
                                   │              ▼                                 │
                                   │ Stage 4: SOP Checker                           │
                                   │   Sequence validation → missing/misordered     │
                                   │              │ chunk results                    │
                                   │              ▼                                 │
                                   │         final_queue                            │
                                   └────────────────────────────────────────────────┘
                                          │
Output                                    ▼
──────                             ┌─────────────────┐
SSE Stream (chat.completion.chunk) │ Kafka Messages   │
Non-streaming (chat.completion)    │ (JSON/Protobuf)  │
Prometheus metrics (/v1/metrics)   └────────┬────────┘
                                            ▼
                                   Docker Container: kafka
                                   (apache/kafka:3.7.0)

Section Index

Each section is a standalone file in references/ — load only what your task needs.

§ File Responsibility
1 [skill01fastapiendpoints.md](references/skill01fastapiendpoints.md) FastAPI endpoints, server init, Prometheus metrics
2 [skill02pydanticschemas.md](references/skill02pydanticschemas.md) Request/response Pydantic models (api_types.py)
3 [skill03deepstreampipeline.md](references/skill03deepstreampipeline.md) DeepStream pyservicemaker pipeline, tensor parser, dummy pipeline
4 [skill04configtemplates.md](references/skill04configtemplates.md) nvdspreprocess / nvinferserver config templates + rendering
5 [skill05tritonddmmodel.md](references/skill05tritonddmmodel.md) Triton model repo, config.pbtxt, model.py, ddm_net.py
5b [skill05bcustompostprocess.md](references/skill05bcustompostprocess.md) C++ postprocess plugin, Makefile, IOptions API
6 [skill06sopprocessmanager.md](references/skill06sopprocessmanager.md) SOPProcessManager, SOPVideoProcessor, VLLMInference, Kafka
6b [skill06bsopchecker.md](references/skill06bsopchecker.md) SOP sequence and checker compliance: MissingNumberDetector, SopCheckerCache, SopCheckerRequest/Response
7 [skill07ssestreaming.md](references/skill07ssestreaming.md) SSE generator, stream response formatting, dummy test mode
8 [skill08baslercamera.md](references/skill08baslercamera.md) Basler camera support, Pylon SDK, emulation, formats
9 [skill09dockerbuilddeploy.md](references/skill09dockerbuilddeploy.md) Docker build, deploy, .env configuration
10 [skill10testsuite.md](references/skill10testsuite.md) Test suite coverage, assertions, running tests
11 [skill11envvariables.md](references/skill11envvariables.md) All environment variables reference
12 [skill12evaluationworkflow.md](references/skill12evaluationworkflow.md) End-to-end eval workflow: static checks, build, launch, tests, API/camera/Kafka checks, report
13 [skill13verificationcurl.md](references/skill13verificationcurl.md) Verification steps and curl examples
14 [skill14implementationchecklist.md](references/skill14implementationchecklist.md) Implementation checklist: file copy list, generated files, Docker prereqs, verification
15 [skill15latencymeasurement.md](references/skill15latencymeasurement.md) TTFC and C2C latency measurement for file input via SSE streaming
16 [skill16messageschema.md](references/skill16messageschema.md) Kafka message schema selection (JSON default vs NvProtoSchema) and extending messages with custom data
17 [skill17cameralatencymeasurement.md](references/skill17cameralatencymeasurement.md) Camera / live-stream chunk_e2e latency measurement using internal pipeline timestamps
18 [skill18rtspstreamingoutput.md](references/skill18rtspstreamingoutput.md) OPT-IN RTSP streaming output: tee1-tap re-stream, RTSPStreamingServer, SW_ENCODER toggle. Generate only when user explicitly requests RTSP

For end-to-end evaluation, read § 12 first; load build/test/curl/latency/camera/Kafka as needed.

§ 18 is opt-in — generate only when the user explicitly requests RTSP output; otherwise skip § 18 and the RTSP_* rules below.


Key Files Map

The full source-to-target file mapping lives in [skill14implementationchecklist.md](references/skill14implementationchecklist.md):

  • Files copied verbatim from references/ (non-trivial algorithms — cycle

detection, qwenvlutils preprocessing, DeepStream IOptions API, protobuf sources) with the rationale per file.

  • Files copied as adaptable templates (Dockerfile, compose.yaml, Triton

config and model.py, ddm_net.py, Pylon emulation config, etc.).

  • Files generated from skill sections — each annotated with the Critical

Rules below that the generation must follow exactly.

  • Docker build prerequisites and post-build verification checklist.

Config files (nvdspreprocesstemplate.txt, nvdsinferencetemplate.txt, vlm_prompts.txt) are used as-is from configs/.

When skill06b is loaded, read configs/actions.json from the project root and run the § 6b-G generation workflow to produce nvdsactiondetector/missingnumber_detector.py. If configs/actions.json is absent or invalid, fall back to copying the reference file.


Critical Rules

Each rule's full detail lives in the linked skillNN*.md reference file.

Tag Rule summary Details in
MANAGERINITIN_MAIN SOPProcessManager init in main() before uvicorn.run() — not inside lifespan() skill01fastapi_endpoints.md
NAMED_KWARGS createvideoprocessor() uses named kwargs; camera args as separate kwargs skill06sopprocessmanager.md
LIVEREQUIRESSTREAM_TRUE stream: true required for live inputs (RTSP / camera) skill08basler_camera.md
VLMDISABLEDDISABLESSOPCHECKER DISABLEVLMINFERENCE=true auto-disables SOP checker at import skill06sopprocessmanager.md
CHUNKPARAMSMAX_LENGTH ChunkParams.maxlengthsec = 10s internal; 60s API default skill06sopprocessmanager.md
VLMWARMUPBEFORE_DDM ModelInitializer: VLM warmup FIRST, then CV dummy pipeline skill06sopprocessmanager.md
VLMWARMUP3_FRAMES VLM warmup needs 3 frames (torch.zeros) — Qwen3VL hangs on < 3 skill06sopprocessmanager.md
THREADPOOLSIZES 4 thread pools: cv(32), clip(32), vlminference(64), vlmrequest(64) skill06sopprocessmanager.md
MEDIAINFOPYMEDIAINFO Media info via pymediainfo; live sources set fps=30/duration=inf directly skill06sopprocessmanager.md
CAMERAEMULATIONPYLON_CAMEMU PYLON_CAMEMU=1 for camera emulation (serial 0815-0000) skill08basler_camera.md
DEEPSTREAMLIBHIDE DeepStream lib hide trick: rename lib → lib.tmp during gst-plugin-pylon build skill08basler_camera.md
VLMREALGPU_FRAMES VLM uses real GPU frames via DecodedFrameRetriever; never torch.zeros for inference skill06sopprocessmanager.md
BUFFERRETRIEVERSTATIC_BASE DecodedFrameRetriever MUST inherit BufferRetriever statically via super().init(); runtime class.bases mutation hangs pipeline.attach() skill06sopprocessmanager.md
FRAMERETRIEVERPRIORITY createinferencepipeline: frameretriever= kwarg takes priority over framequeue skill03deepstream_pipeline.md
MUXORIGINALRESOLUTION nvstreammux uses original resolution (not 224); pass muxwidth/muxheight from getmediainfo() (probe live RTSP for non-camera inputs; camera path unaffected) skill03deepstreampipeline.md, skill06sopprocess_manager.md
FILEURINODOUBLEPREFIX createinferencepipeline file source: check file_path.startswith("file://") before prepending — API passes file:// URLs directly skill03deepstream_pipeline.md
CLEANUPONDISCONNECT Pipeline cleanup on client disconnect via triggerstopprocessors in try/finally skill07sse_streaming.md
UNIFIEDCLIPPOST_PROCESS Unified clippostprocess() for file + live; stop() puts None in scorequeue skill06sopprocessmanager.md
ABORTINFLIGHTVLM Abort in-flight VLM requests on stop() via llm.abort(req_id) skill06sopprocessmanager.md
LOGGEREXPORTGET_LOGGER dslogger.py must export getlogger skill06sopprocessmanager.md
KAFKAUSECREATE_PRODUCER Kafka: use create_producer() from messager.py; no Messager class skill06sopprocessmanager.md
USERPROMPTPRIORITY User request text takes priority over VLMPROMPTPATH file; {"type":"text"} in the request overrides the config-file prompt skill06sopprocessmanager.md
EVALUSECONFIG_PROMPT Eval/latency requests omit request text by default so the VLM uses VLMPROMPTPATH skill12evaluationworkflow.md, skill13verificationcurl.md, skill15latencymeasurement.md, skill17cameralatency_measurement.md
CHUNKSCHEMAFIELD_NAMES Chunk schema: chunkidx, cvboundaryscore, checkerresult; summary chunk_idx=-1 skill06sopprocessmanager.md
SEQUENTIALFRAMEDRAIN Drain decodedframequeue (FIFO, shared across chunks) in a SINGLE thread and submit VLM per chunk incrementally; parallel drain steals frames → 0-frame chunks / wrong VLM input skill06sopprocessmanager.md
WALLCLOCKBEFORE_GPU DecodedFrameRetriever.consume(): capture wallclockentry = time.time() BEFORE GPU dlpack; queue 3-tuple (timestamp, wallclockentry, tensor) skill06sopprocessmanager.md, skill17cameralatencymeasurement.md
CHUNKE2EPIPELINE_TIMESTAMPS Write pipelinechunkendtimestamp (last frame wallclock) and pipelinevlmreadytimestamp (tme2e.now()) into chunk_info for camera latency (§ 17) skill06sopprocessmanager.md, skill17cameralatencymeasurement.md
VLMINFERENCEREQUIRED_KWARGS Every VLLMInference.inference() call must pass videofps, systemprompt, maxcompletiontokens skill06sopprocessmanager.md
UNIFORMCHUNKINGBYPASSES_DDM chunkingoptions.algorithm="uniform" → fixed-length chunks; createinferencepipeline(uniformchunk=True) skips DDM but keeps tee1 fanout; Stage 2 uses uniformclippost_process skill02pydanticschemas.md, skill03deepstreampipeline.md, skill06sopprocessmanager.md
DDMTEMPORALCONFIGURABLE SLIDINGWINDOWSSIZE = 2*FRAMESPERSIDE + SEQUENCE_BATCH rendered into preprocess/nvinferserver (no hard-coded 18); Triton config.pbtxt sequence dim -1 skill04configtemplates.md, skill05tritonddm_model.md
DDMTRTOPTIONAL_PATH DDMTRTOPTIMIZATION=true runs DDM via TensorRT (per-thread contexts, fixed batch = SEQUENCE_BATCH); PyTorch fallback; never both. PyTorch is default skill05tritonddmmodel.md
DDMTRTSTREAM_ORDERING DDMTensorRTEngine.infer(): waitstream(current)executeasync_v3torch.cuda.synchronize(device) (NOT per-stream). Per-stream sync leaves TRT aux-stream work in flight → gst-CV SIGSEGV (NVBug 6289256) skill05tritonddmmodel.md
METADATALICENSEFROM_FILE /v1/metadata reads licenseInfo from DSSOPLICENSEPATH (default /opt/nvidia/nvdssop/license.txt); never hard-code license text skill01fastapi_endpoints.md
CAMERAEMULATIONFRAMES_RGB Pylon emulation PNGs must be explicit 3-channel RGB (matches Emulation_0815-0000.pfs PixelFormat=RGB8Packed); generate via nvvideoconvert ! videoconvert ! "video/x-raw,format=RGB" ! pngenc skill08basler_camera.md
COMPOSEENVPASSTHROUGH docker compose only substitutes ${VAR} references; every runtime env var must be explicitly listed under environment: to reach the container. skill09dockerbuilddeploy.md

The four RTSP_* rules below apply **only when the optional RTSP streaming-output feature
(§ 18) is requested**. They do not apply to the default build — skip them if the user did
not ask for RTSP output.

| RTSPOUTPUTTAPSTEE1 | RTSP output branch links from the existing tee1 (added after the main inference link) only when rtspport is present. | skill18rtspstreamingoutput.md | | RTSPLEAKYQUEUETINY | RTSP branch queue must be leaky=2 + tiny cap (max-size-buffers=2) to prevent backpressure and NVMM pool exhaustion. | skill18rtspstreamingoutput.md | | RTSPKEYINTMAX30 | RTSP H.264 encoder must set key-int-max=30 (and B-frames disabled) to allow downstream seeking. | skill18rtspstreamingoutput.md | | RTSPENCODERFALLBACK | Select software/hardware H.264 encoder based on SWENCODER with MJPEG fallback. | skill18rtspstreaming_output.md |