Real-Time Object Tracking API (traject)
Viewtron AI cameras support a unique real-time tracking mode called traject that continuously streams target position data to your server via HTTP POST. Unlike alarm-based detection events that fire once per event, traject sends continuous updates at approximately 7 posts per second for the entire duration a target is being tracked. Each post is only ~1.7 KB of XML data containing the target ID, target type (person, car, or motorcycle), and bounding box coordinates — no images are included.
This makes traject fundamentally different from every other detection type in the Viewtron API. Alarm-based methods like human detection or line crossing send a single event with images when something happens. Traject gives you a continuous stream of position data that lets you know exactly where a target is, how long it has been there, and when it leaves. The stream starts within ~140ms of a target being detected and stops within ~1 second of the target leaving the camera's view.
Important: Traject is only available from IPC cameras directly — NVRs do not forward traject data. The camera must be subscribed to the traject data type via httpPostV2 configuration.
What You Can Build
- Real-time position dashboards — display target locations on a map or floor plan that updates in real time
- Presence-based relay control — turn on lights, activate alarms, or control relays while a person is present (see the ESP8266 relay controller project)
- Dwell time analysis — calculate exactly how long each target stays in view, down to sub-second precision
- Speed and direction estimation — track bounding box movement between frames to estimate velocity
- Occupancy counting — monitor how many targets are simultaneously active in the camera's field of view
- Custom alarm logic — build your own detection rules based on target position, duration, or movement patterns
How It Works
- Enable traject on the camera — subscribe to the
trajectdata type in the httpPostV2 configuration and enable "Smart track data" in the camera's HTTP Post V2 web interface - Your server receives continuous XML posts while any target is being tracked — approximately 7 posts per second per target
- Parse the position data using the Viewtron Python SDK (
pip install viewtron) or Node.js SDK — each post contains one or more targets with targetId, targetType, and bounding rect coordinates - Track targets over time — use the targetId to correlate posts for the same target, calculate dwell time and movement
- Detect departure — when posts stop arriving for a targetId, the target has left the camera's view
Comparison with Other Methods
| Method | Signal Type | Posts While Present | Gaps While Present | Data per Post |
|---|---|---|---|---|
GetAlarmStatus polling | perimeterAlarm=true | Periodic (your poll rate) | Yes (5-20 seconds) | ~660 bytes |
| Alarm server push | One POST per event | 1-2 per entry | Yes (20-60 seconds) | ~510-530 KB (with images) |
httpPostV2 traject | Continuous POSTs | 6-12 per second | None | ~1.7 KB (no images) |
The key advantage of traject is zero gaps. Alarm-based methods have significant blind periods where a target is present but no data is being sent. Traject provides continuous confirmation that a target is still there.
Traject Data Fields
Each traject POST contains one or more tracked targets:
| Field | Type | Description |
|---|---|---|
targetId | uint32 | Unique ID for the tracked target — new ID assigned per entry |
targetType | string | person, car, or motor |
rect | x1, y1, x2, y2 | Bounding box in normalized coordinates (0-10000) |
point | x, y | Target center point (may be 0,0) |
velocity | uint32 | Target velocity (may be 0) |
direction | uint32 | Target direction (may be 0) |
trajectlength | list | Trajectory path points (may be empty) |
currentTime | tint64 | Timestamp in microseconds |
mac | string | Camera MAC address |
deviceName | string | Camera name |
The velocity, direction, and trajectlength fields are included in the XML but are typically reported as zero in current firmware. You can calculate speed and direction yourself by tracking bounding box position changes between consecutive posts.
Parsing Traject Events
- Python SDK
- Node.js SDK
- IPC XML (v1.x)
The SDK includes a Traject class for parsing traject posts. The ViewtronServer handles the HTTP connection and keepalives:
pip install viewtron
from viewtron import ViewtronServer
import time
# Active targets: {targetId: {type, first_seen, last_seen, post_count}}
active_targets = {}
TARGET_TIMEOUT = 2.0
def on_traject(event, client_ip):
"""Called for each traject post (~7/sec per target)."""
now = time.time()
for target in event.targets:
tid = target["targetId"]
if tid in active_targets:
active_targets[tid]["last_seen"] = now
active_targets[tid]["post_count"] += 1
else:
active_targets[tid] = {
"type": target["targetType"],
"first_seen": now,
"last_seen": now,
"post_count": 1,
}
print(f" [ARRIVED] Target {tid} ({target['targetType']})")
# Expire departed targets
expired = [tid for tid, t in active_targets.items()
if now - t["last_seen"] > TARGET_TIMEOUT]
for tid in expired:
t = active_targets.pop(tid)
dwell = t["last_seen"] - t["first_seen"]
print(f" [DEPARTED] Target {tid} ({t['type']}) — "
f"dwell: {dwell:.1f}s, posts: {t['post_count']}")
server = ViewtronServer(port=5002, on_traject=on_traject)
server.serve_forever()
See the Python SDK reference for the full Traject class API.
npm install viewtron-sdk
const { ViewtronServer } = require('viewtron-sdk');
const activeTargets = new Map();
const TARGET_TIMEOUT = 2000; // ms
const server = new ViewtronServer({ port: 5002 });
server.on('traject', (event, clientIP) => {
const now = Date.now();
for (const target of event.targets) {
const tid = target.targetId;
if (activeTargets.has(tid)) {
const t = activeTargets.get(tid);
t.lastSeen = now;
t.postCount++;
} else {
activeTargets.set(tid, {
type: target.targetType,
firstSeen: now,
lastSeen: now,
postCount: 1,
});
console.log(` [ARRIVED] Target ${tid} (${target.targetType})`);
}
}
// Expire departed targets
for (const [tid, t] of activeTargets) {
if (now - t.lastSeen > TARGET_TIMEOUT) {
const dwell = ((t.lastSeen - t.firstSeen) / 1000).toFixed(1);
console.log(` [DEPARTED] Target ${tid} (${t.type}) — dwell: ${dwell}s, posts: ${t.postCount}`);
activeTargets.delete(tid);
}
}
});
server.start();
Traject is IPC-only. Each post contains a <traject> list with one or more tracked targets:
<?xml version="1.0" encoding="UTF-8" ?>
<config version="1.7" xmlns="http://www.ipc.com/ver10">
<types>
<openAlramObj>
<enum>MOTION</enum><enum>SENSOR</enum><enum>PEA</enum>
</openAlramObj>
<subscribeRelation>
<enum>ALARM</enum>
<enum>FEATURE_RESULT</enum>
<enum>ALARM_FEATURE</enum>
</subscribeRelation>
<targetType>
<enum>person</enum>
<enum>car</enum>
<enum>motor</enum>
</targetType>
</types>
<subscribeOption type="subscribeRelation">FEATURE_RESULT</subscribeOption>
<currentTime type="tint64">1774646121524166</currentTime>
<mac type="string"><![CDATA[58:5b:69:5f:42:1b]]></mac>
<sn type="string"><![CDATA[I421B0Z1173Q]]></sn>
<deviceName type="string"><![CDATA[FaceCam]]></deviceName>
<traject type="list" count="1">
<item>
<targetId type="uint32">434</targetId>
<point>
<x type="uint32">0</x>
<y type="uint32">0</y>
</point>
<rect>
<x1 type="uint32">6534</x1>
<y1 type="uint32">2708</y1>
<x2 type="uint32">7585</x2>
<y2 type="uint32">6388</y2>
</rect>
<velocity type="uint32">0</velocity>
<direction type="uint32">0</direction>
<targetType type="targetType">person</targetType>
<trajectlength type="list" count="0"/>
</item>
</traject>
</config>
Multiple targets can be tracked simultaneously — each appears as a separate <item> in the <traject> list with a unique targetId. The count attribute reflects the number of targets in that post.
See the IPC Event Format reference for the complete v1.x XML structure.
Configuration
Enable traject on an IPC camera by sending this XML to SetHttpPostConfig:
<?xml version="1.0" encoding="UTF-8"?>
<config version="1.0" xmlns="http://www.ipc.com/ver10">
<httpPostV2><postUrlConf>
<urlList type="list" count="1"><item>
<urlId>1</urlId>
<switch>true</switch>
<url>
<protocol>http</protocol>
<domain><![CDATA[192.168.0.53]]></domain>
<port>80</port>
<path><![CDATA[/API]]></path>
<authentication>none</authentication>
</url>
<heatBeatSwitch>true</heatBeatSwitch>
<keepaliveTimeval>90</keepaliveTimeval>
<subscribeDateType type="list" count="1">
<item>traject</item>
</subscribeDateType>
<subscriptionEvents type="list" count="1">
<item>PERIMETER</item>
</subscriptionEvents>
</item></urlList>
</postUrlConf></httpPostV2>
</config>
The "Smart track data" checkbox must also be enabled in the camera's HTTP Post V2 web interface (Edit HTTP POST dialog). The camera will not send traject data even if configured via API unless this checkbox is checked.
Important Notes
- Traject is IPC-only. NVRs do not forward traject data and do not expose the smart track data subscription.
- Works through NVR PoE. When an IPC is connected to an NVR via PoE, the camera still sends traject directly to your server. The XML format is identical — the source IP will be the NVR's PoE interface.
- No images included. Traject posts contain only position data (~1.7 KB). For images, use a parallel alarm-based subscription.
- Recommended dual setup: Configure the NVR's HTTP POST for alarm events with images, and configure the IPC's httpPostV2 for traject tracking. This gives you both event snapshots and continuous position data.
- New targetId per entry. Each time a target enters the camera's view, it receives a new unique targetId. The same physical person will get different IDs if they leave and return.
For a working automation example, see the ESP8266 Relay Controller project, which uses traject data to control a relay for continuous human presence detection — keeping a relay energized for the entire duration a person is in view with zero gaps.
Relevant API Endpoints
| Endpoint | Purpose | Reference |
|---|---|---|
| SetHttpPostConfig | Configure httpPostV2 with traject subscription | Webhook Config |
| GetHttpPostConfig | Read current httpPostV2 configuration | Webhook Config |
| GetSmartPerimeterConfig | Configure the perimeter detection zone that triggers tracking | Intrusion Detection Config |
Integrations
Viewtron traject tracking also integrates with automation platforms via published packages:
| Platform | Package | What It Does |
|---|---|---|
| Home Assistant | viewtron-home-assistant | Real-time presence detection as native HA sensors — automate lights, relays, alarms |
| Node-RED | node-red-contrib-viewtron | Traject data direct to Node-RED flows — build presence logic visually |
Related Applications
- Human Detection & Intrusion Detection — event-based detection with images (complements traject)
- Relay Control & IoT Automation — trigger relays based on traject presence data
- People Counting & Traffic Analytics — count targets crossing lines or entering areas
- Webhook Event Notification — complete webhook setup and format reference
Related Products
- Viewtron AI Security Cameras — IP cameras with built-in traject tracking
- Viewtron IP Camera NVRs — NVRs for centralized camera management (traject requires direct IPC connection)
Questions & Development Inquiries
- Email: mike@viewtron.com
- Phone: 561-433-8488
- Forum: NVR Webhook Setup Guide
Mike Haldas is available for questions, consultation, and custom software development for Viewtron API related projects. Email details about your project to mike@viewtron.com.