Skip to main content

Build an ACAP application that consumes scene metadata

This guide provides steps on how to build a simple ACAP application that consumes Track Consolidation output and/or Fusion Tracker output scene metadata using the Device Data Hub API.

Prerequisites​

  1. An Axis device that supports AXIS Scene Metadata
  2. For AXIS OS 13 or later, Developer Mode enabled on the device
  3. Docker
    • For Windows and macOS, use the automatically upgradable Docker desktop stable
    • For Linux, use Docker Engine version 23.0.0 or later
  4. Git

Overview​

The guide contains the following steps:

  1. Cloning the ACAP Native SDK Examples repository containing the application source code
  2. Build the application
  3. Install and start the application

Lets get started!

Step 1: Cloning the repository​

Execute the following command from a terminal to clone the repository containing the ACAP Native SDK Examples.

Clone the ACAP Native SDK Examples repository
git clone https://github.com/AxisCommunications/acap-native-sdk-examples.git

Navigate to the device-data-hub > consume-scene-metadata folder where you should be able to find a directory called app. That directory contains the consume_scene_metadata.c application source code which can be compiled and run on the target device.

Step 2: Build the application​

Run the following commands in your working directory:

info

Depending on the network your local build machine is connected to, you may need to add proxy settings for Docker. See Proxy in build time.

docker build --tag <APP_IMAGE> .

APP_IMAGE is the tag name that will be set on the built image, e.g., consume_scene_metadata:1.0

info

Default architecture is armv7hf. To build for aarch64, update the ARCH variable in the Dockerfile, or set it in the docker build command via build argument:

docker build --build-arg ARCH=aarch64 --tag <APP_IMAGE> .

Copy the result from the container image to a local directory named build:

docker cp $(docker create <APP_IMAGE>):/opt/app ./build

The working directory now contains a build folder with the following files:

consume-scene-metadata
├── app
│ ├── consume_scene_metadata.c
│ ├── LICENSE
│ ├── Makefile
│ └── manifest.json
├── build
│ ├── consume_scene_metadata
│ ├── consume_scene_metadata_1_0_0_armv7hf.eap
│ ├── consume_scene_metadata_1_0_0_LICENSE.txt
│ ├── consume_scene_metadata.c
│ ├── debug
│ │ └── consume_scene_metadata
│ ├── LICENSE
│ ├── Makefile
│ ├── manifest.json
│ ├── package.conf
│ ├── package.conf.orig
│ └── param.conf
├── Dockerfile
└── README.md
  • build/manifest.json - Defines the application and its configuration.
  • build/package.conf - Defines the application and its configuration.
  • build/param.conf - File containing application parameters.
  • build/consume_scene_metadata - Application executable binary file.
  • build/consume_scene_metadata_1_0_0_armv7hf.eap - Application package .eap file.
  • build/consume_scene_metadata_1_0_0_LICENSE.txt - Copy of LICENSE file.

Step 3: Install and start the application​

Browse to the application page of the Axis device:

http://<AXIS_DEVICE_IP>/index.html#apps
  • Click on the tab Apps in the device GUI
  • Click (+ Install app) button to upload the application package .eap file
  • Browse to the built application .eap file and choose one, depending on architecture:
    • consume_scene_metadata_1_0_0_aarch64.eap
    • consume_scene_metadata_1_0_0_armv7hf.eap
  • Click Install
  • Run the application by enabling the Start switch

Inspect the generated output​

The application log can be found at

http://<AXIS_DEVICE_IP>/axis-cgi/admin/systemlog.cgi?appname=consume_scene_metadata

----- Contents of SYSTEM_LOG for 'consume_scene_metadata' -----


consume_scene_metadata[5193]: Application started
consume_scene_metadata[5193]: User data: consume_scene_metadata_data
consume_scene_metadata[5193]: Received consumer-scene-metadata: {"channel_id":1,"duration":0.6,"end_time":"2026-05-28T13:09:58.740130Z","id":"05e2024f-f60e-467e-b408-b3391ee38281","parts":[{"object_track_id":"63c62160-a7d9-4431-8c95-8dd8cb941ae4"}],"path":[{"bounding_box":{"bottom":0.5985,"left":0.4247,"right":0.505,"top":0.5036},"timestamp":"2026-05-28T13:09:58.140130Z"},{"bounding_box":{"bottom":0.5985,"left":0.4256,"right":0.5112,"top":0.488},"timestamp":"2026-05-28T13:09:58.240130Z"},{"bounding_box":{"bottom":0.5964,"left":0.4247,"right":0.5181,"top":0.4849},"timestamp":"2026-05-28T13:09:58.340131Z"},{"bounding_box":{"bottom":0.5932,"left":0.4229,"right":0.5252,"top":0.4881},"timestamp":"2026-05-28T13:09:58.440130Z"},{"bounding_box":{"bottom":0.5932,"left":0.4235,"right":0.5323,"top":0.4881},"timestamp":"2026-05-28T13:09:58.540130Z"},{"bounding_box":{"bottom":0.5948,"left":0.4253,"right":0.5395,"top":0.4865},"timestamp":"2026-05-28T13:09:58.640130Z"},{"bounding_box":{"bottom":0.5943,"left":0.4229,"right":0.5484,"top":0.4849},"timestamp":"2026-05-28T13:09:58.740130Z"}],"start_time":"2026-05-28T13:09:58.140130Z"}
consume_scene_metadata[5193]: User data: consume_scene_metadata_data
consume_scene_metadata[5193]: Received consumer-scene-metadata: {"channel_id":1,"duration":0.1,"end_time":"2026-05-28T13:09:58.440130Z","id":"cb014ade-4447-414b-88ae-8f794ebff337","parts":[{"object_track_id":"e2c25529-fc6d-4fc7-9129-b2c60f6abf37"}],"path":[{"bounding_box":{"bottom":0.5068,"left":0.3193,"right":0.3497,"top":0.4235},"timestamp":"2026-05-28T13:09:58.340131Z"},{"bounding_box":{"bottom":0.5053,"left":0.3203,"right":0.3532,"top":0.4235},"timestamp":"2026-05-28T13:09:58.440130Z"}],"start_time":"2026-05-28T13:09:58.340131Z"}

The format of a detection is shown in a more readable way.

{
"channel_id": 1,
"duration": 0.6,
"end_time": "2026-05-28T13:09:58.740130Z",
"id": "05e2024f-f60e-467e-b408-b3391ee38281",
"parts": [
{
"object_track_id": "63c62160-a7d9-4431-8c95-8dd8cb941ae4"
}
],
"path": [
{
"bounding_box": {
"bottom": 0.5985,
"left": 0.4247,
"right": 0.505,
"top": 0.5036
},
"timestamp": "2026-05-28T13:09:58.140130Z"
},
{
"bounding_box": {
"bottom": 0.5985,
"left": 0.4256,
"right": 0.5112,
"top": 0.488
},
"timestamp": "2026-05-28T13:09:58.240130Z"
},
{
"bounding_box": {
"bottom": 0.5964,
"left": 0.4247,
"right": 0.5181,
"top": 0.4849
},
"timestamp": "2026-05-28T13:09:58.340131Z"
},
{
"bounding_box": {
"bottom": 0.5932,
"left": 0.4229,
"right": 0.5252,
"top": 0.4881
},
"timestamp": "2026-05-28T13:09:58.440130Z"
},
{
"bounding_box": {
"bottom": 0.5932,
"left": 0.4235,
"right": 0.5323,
"top": 0.4881
},
"timestamp": "2026-05-28T13:09:58.540130Z"
},
{
"bounding_box": {
"bottom": 0.5948,
"left": 0.4253,
"right": 0.5395,
"top": 0.4865
},
"timestamp": "2026-05-28T13:09:58.640130Z"
},
{
"bounding_box": {
"bottom": 0.5943,
"left": 0.4229,
"right": 0.5484,
"top": 0.4849
},
"timestamp": "2026-05-28T13:09:58.740130Z"
}
],
"start_time": "2026-05-28T13:09:58.140130Z"
}
info

The application outputs the result of Track Consolidation module for source 1.

If you would like to consume Fusion Tracker outout instead, you would need to modify the topic specified in the application source code file to com.axis.scene.frame.v1.