Nodeflux Central
Video Analysis

API Reference — Video Analysis

Endpoint untuk upload video rekaman, manajemen Job analisis offline, assign analitik, dan konfigurasi pipeline.

Semua endpoint memerlukan header Authorization: Bearer <token>. Basis URL mengikuti variabel lingkungan VITE_API_URL yang dikonfigurasi pada instalasi Lenz. Endpoint yang menggunakan {nvrServerId} di-proxy oleh Raisa Gateway ke Media Server yang dikonfigurasi sebagai System Media Server — ganti {nvrServerId} dengan ID Media Server yang aktif.


Upload Video

Endpoint untuk mengunggah file video rekaman secara bertahap (chunked upload). File besar dikirim dalam potongan-potongan kecil menggunakan session_id yang sama. Sistem mendukung resume — jika koneksi terputus, lanjutkan dari chunk terakhir tanpa mengulang dari awal.

POST
/api/visionaire-media/{nvrServerId}/videos/upload

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

Query Parameters

autoplay?boolean

Jika true, video otomatis diputar sebagai stream RTSP setelah upload selesai.

Defaulttrue

Request Body

multipart/form-data

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

curl -X POST "https://lenz.example.com/api/visionaire-media/0/videos/upload" \  -F file="string" \  -F filename="rekaman-2026-01.mp4" \  -F chunk_index="0" \  -F total_chunks="10" \  -F total_size="104857600"
{  "success": true,  "data": {    "message": "Chunk received",    "session_id": "sess-abc123",    "video_id": "abc123def456",    "chunk_index": 0,    "chunks_received": 1,    "total_chunks": 10,    "bytes_written": 10485760,    "total_size": 104857600,    "progress": 10,    "status": "uploading",    "seq": 1,    "instance": null  }}
GET
/api/visionaire-media/{nvrServerId}/videos/upload/status/{sessionId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

sessionId*string

ID sesi upload yang dikembalikan saat chunk pertama diterima.

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire-media/0/videos/upload/status/string"
{  "success": true,  "data": {    "session_id": "sess-abc123",    "video_id": "abc123def456",    "original_filename": "rekaman-2026-01.mp4",    "status": "uploading",    "bytes_written": 52428800,    "total_size": 104857600,    "chunks_received": 5,    "total_chunks": 10,    "progress": 50,    "created_at": "2026-01-15T08:00:00Z",    "updated_at": "2026-01-15T08:02:30Z"  }}
GET
/api/visionaire-media/{nvrServerId}/videos/upload/resume/{sessionId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

sessionId*string

ID sesi upload yang ingin dilanjutkan.

Query Parameters

filename?string

Nama file asli (opsional, untuk verifikasi).

video_id?string

ID video yang terkait (opsional, untuk verifikasi).

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire-media/0/videos/upload/resume/string"
{  "success": true,  "data": {    "message": "Session found, can resume",    "session_id": "sess-abc123",    "video_id": "abc123def456",    "original_filename": "rekaman-2026-01.mp4",    "status": "paused",    "chunks_received": 5,    "total_chunks": 10,    "bytes_written": 52428800,    "total_size": 104857600,    "progress": 50,    "missing_chunks": [      5,      6,      7,      8,      9    ],    "can_reuse_session": true  }}
POST
/api/visionaire-media/{nvrServerId}/videos/upload/cancel/{sessionId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

sessionId*string

ID sesi upload yang akan dibatalkan.

Response Body

application/json

curl -X POST "https://lenz.example.com/api/visionaire-media/0/videos/upload/cancel/string"
{  "success": true,  "message": "Upload cancelled successfully",  "session_id": "sess-abc123"}

Manajemen Video (Job)

Endpoint untuk melihat, mengambil detail, dan menghapus video yang telah diunggah. Setiap video yang diunggah mewakili satu Job analisis offline.

GET
/api/visionaire-media/{nvrServerId}/videos

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

Query Parameters

search?string

Pencarian parsial case-insensitive pada ID dan nama file video.

sort_by?string

Kolom pengurutan.

Default"created_at"
Value in"original_filename" | "file_size" | "duration" | "started_at" | "created_at"
sort_order?string

Arah pengurutan.

Default"desc"
Value in"asc" | "desc"
page?integer

Nomor halaman (1-indexed).

Default1
Range1 <= value
per_page?integer

Jumlah item per halaman. Nilai 0 mengembalikan semua item.

Default10
Range0 <= value

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire-media/0/videos"
{  "success": true,  "data": {    "videos": [      {        "id": "abc123def456",        "original_filename": "rekaman-2026-01.mp4",        "file_path": "/storage/videos/rekaman-2026-01.mp4",        "file_size": 104857600,        "created_at": "2026-01-15T08:00:00Z",        "status": "streaming",        "duration": 3600,        "started_at": "2026-01-15T00:00:00Z",        "started_at_src": "metadata",        "ended_at": "2026-01-15T01:00:00Z",        "instance": null      }    ],    "count": 1,    "pagination": {      "current_page": 1,      "per_page": 10,      "total_items": 1,      "total_pages": 1    }  }}
GET
/api/visionaire-media/{nvrServerId}/videos/{videoId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

videoId*string

ID unik video.

Response Body

application/json

application/json

curl -X GET "https://lenz.example.com/api/visionaire-media/0/videos/string"
{  "success": true,  "data": {    "video": {      "id": "abc123def456",      "original_filename": "rekaman-2026-01.mp4",      "file_path": "/storage/videos/rekaman-2026-01.mp4",      "file_size": 104857600,      "created_at": "2026-01-15T08:00:00Z",      "status": "streaming",      "duration": 3600,      "started_at": "2026-01-15T00:00:00Z",      "started_at_src": "metadata",      "ended_at": "2026-01-15T01:00:00Z",      "device": {        "name": "rekaman-2026-01",        "url": "file:///storage/videos/rekaman-2026-01.mp4",        "scheme": "file",        "channel": "live",        "silent_audio": false,        "status": "running",        "publish_url": "rtsp://192.168.1.10:1935/live/rekaman-2026-01",        "created_at": "2026-01-15T08:00:00Z",        "updated_at": "2026-01-15T08:01:00Z",        "error_count": 0,        "restart_count": 0,        "uptime": 3600000      },      "instance": null    }  }}
{  "success": false,  "message": "video not found"}
DELETE
/api/visionaire-media/{nvrServerId}/videos/{videoId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nvrServerId*integer

ID numerik Media Server (NVR).

videoId*string

ID unik video.

Response Body

application/json

curl -X DELETE "https://lenz.example.com/api/visionaire-media/0/videos/string"
{  "success": true,  "message": "Video deleted successfully",  "video_id": "abc123def456"}

Katalog Analitik

Endpoint untuk mengambil daftar analitik yang tersedia di instance Visionaire — digunakan untuk mengisi dropdown pemilihan analitik saat assign ke video. Field free_seats menunjukkan berapa seat lisensi masih tersedia untuk analitik tersebut.

GET
/api/visionaire/analytic_list

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Query Parameters

instance?string

ID instance spesifik pada mode federation (opsional)

is_aggregated?boolean

Jika true, gabungkan data dari seluruh instance pada mode federation

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire/analytic_list"
{  "analytic_num": 2,  "analytics": [    {      "id": "NFDSS-FR",      "name": "Face Recognition",      "description": "Deteksi dan pengenalan wajah",      "publisher": "Nodeflux",      "type": "fr",      "major_version": 4,      "minor_version": 2,      "free_seats": 3,      "all_seats": 5,      "seats": [        {          "serial_number": "SN-001",          "active_status": true        },        {          "serial_number": "SN-002",          "active_status": false        }      ]    },    {      "id": "NFDSS-LPR",      "name": "License Plate Recognition",      "description": "Pembacaan plat nomor kendaraan",      "publisher": "Nodeflux",      "type": "lpr",      "major_version": 4,      "minor_version": 1,      "free_seats": 2,      "all_seats": 4,      "seats": []    }  ],  "code": 200,  "deployment_key": "dk-abc123",  "hardware_id": "hw-xyz456",  "message": "success",  "version": {    "major": 4,    "minor": 2,    "patch": 1  }}
GET
/api/visionaire_active_analytic_list

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire_active_analytic_list"
{  "ok": true,  "message": "successfully get active analytic list",  "data": {    "analytic_num": 1,    "analytics": [      {        "id": "NFDSS-FR",        "name": "Face Recognition",        "description": "Deteksi dan pengenalan wajah",        "publisher": "Nodeflux",        "type": "fr",        "major_version": 4,        "minor_version": 2,        "free_seats": 3,        "all_seats": 5,        "seats": []      }    ]  }}

Assignment Pipeline

Endpoint untuk men-assign, memperbarui, dan menghapus analitik pada stream internal yang dibuat dari video yang diunggah. Setelah upload selesai, sistem membuat stream internal dengan offline_mode: true — gunakan nodeId dan streamId dari stream tersebut untuk endpoint ini.

Sistem tidak mengizinkan assign analitik baru saat analisis sedang berjalan (running) atau terjadwal (scheduled). Tunggu hingga analisis selesai, atau batalkan jadwal terlebih dahulu sebelum menambah analitik baru.

GET
/api/visionaire/pipeline/{nodeId}/{streamId}/{analyticId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nodeId*string

ID node tempat stream berjalan.

streamId*string

ID stream video.

analyticId*string

ID analitik yang ditugaskan.

Query Parameters

instance?string

ID instance pada mode federation (opsional).

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire/pipeline/node-001/stream-uuid-001/NFV4-MPA"
{  "analytic_id": "NFV4-MPA",  "code": 200,  "message": "success",  "node_num": 1,  "stream_id": "stream-uuid-001",  "config": {    "args": {},    "env": {},    "object_confidence_threshold": 0.5,    "sub_analytics": [      {        "name": "counting",        "is_active": true,        "areas": [          {            "name": "Pintu Masuk",            "points": [              {                "x": 0.2,                "y": 0.5              },              {                "x": 0.8,                "y": 0.5              }            ],            "direction": "both"          }        ],        "object_confidence_threshold": 0.5      }    ]  }}
POST
/api/visionaire/pipeline/{nodeId}/{streamId}/{analyticId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nodeId*string

ID node tempat stream berjalan.

streamId*string

ID stream video.

analyticId*string

ID analitik yang ditugaskan.

Query Parameters

instance?string

ID instance pada mode federation (opsional).

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

curl -X POST "https://lenz.example.com/api/visionaire/pipeline/node-001/stream-uuid-001/NFV4-MPA" \  -H "Content-Type: application/json" \  -d '{    "sub_analytics": [      {        "name": "counting",        "is_active": true,        "areas": [          {            "name": "Pintu Masuk",            "points": [              {                "x": 0.2,                "y": 0.5              },              {                "x": 0.8,                "y": 0.5              }            ],            "direction": "both"          }        ],        "object_confidence_threshold": 0.5      }    ]  }'
{  "analytic_id": "NFV4-MPA",  "code": 200,  "message": "success",  "node_num": 1,  "stream_id": "stream-uuid-001",  "ok": true}
PUT
/api/visionaire/pipeline/{nodeId}/{streamId}/{analyticId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nodeId*string

ID node tempat stream berjalan.

streamId*string

ID stream video.

analyticId*string

ID analitik yang ditugaskan.

Query Parameters

instance?string

ID instance pada mode federation (opsional).

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

curl -X PUT "https://lenz.example.com/api/visionaire/pipeline/node-001/stream-uuid-001/NFV4-MPA" \  -H "Content-Type: application/json" \  -d '{    "sub_analytics": [      {        "name": "counting",        "is_active": true,        "areas": [          {            "name": "Pintu Masuk — Revisi",            "points": [              {                "x": 0.1,                "y": 0.5              },              {                "x": 0.9,                "y": 0.5              }            ],            "direction": "in"          }        ],        "object_confidence_threshold": 0.6      }    ]  }'
{  "analytic_id": "NFV4-MPA",  "code": 200,  "message": "success",  "node_num": 1,  "stream_id": "stream-uuid-001",  "ok": true}
DELETE
/api/visionaire/pipeline/{nodeId}/{streamId}/{analyticId}

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

nodeId*string

ID node tempat stream berjalan.

streamId*string

ID stream video.

analyticId*string

ID analitik yang ditugaskan.

Query Parameters

instance?string

ID instance pada mode federation (opsional).

Response Body

application/json

curl -X DELETE "https://lenz.example.com/api/visionaire/pipeline/node-001/stream-uuid-001/NFV4-MPA"
{  "analytic_id": "NFV4-MPA",  "code": 200,  "message": "success",  "node_num": 1,  "stream_id": "stream-uuid-001",  "ok": true}

Konfigurasi Analitik

Endpoint untuk mengambil konfigurasi default dan skema form analitik — digunakan saat membangun UI form konfigurasi pipeline, serta untuk memvalidasi konfigurasi raw JSON sebelum diterapkan.

GET
/api/visionaire/analytics/{analyticId}/config

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

analyticId*string

ID analitik

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire/analytics/NFDSS-FR/config"
{  "analytic_id": "NFDSS-FR",  "configs": [    {      "name": "object_confidence_threshold",      "type": "number",      "label": "Confidence Threshold",      "description": "Ambang batas kepercayaan deteksi (0.0 – 1.0)",      "value": 0.5,      "required": false,      "min": 0,      "max": 1,      "step": 0.01    }  ],  "sub_analytics": [],  "message": "success",  "ok": true}
Empty
GET
/api/visionaire/analytics/{analyticId}/config/form

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Path Parameters

analyticId*string

ID analitik

Response Body

application/json

curl -X GET "https://lenz.example.com/api/visionaire/analytics/NFDSS-FR/config/form"
{  "analytic_id": "NFDSS-FR",  "configs": [    {      "name": "object_confidence_threshold",      "type": "number",      "label": "Confidence Threshold",      "description": "Ambang batas kepercayaan deteksi (0.0 – 1.0)",      "value": 0.5,      "required": false,      "min": 0,      "max": 1,      "step": 0.01    }  ],  "sub_analytics": [    {      "name": "counting",      "display_name": "Counting",      "configs": []    }  ],  "message": "success",  "ok": true}
POST
/api/visionaire/analytics/config/validate

Authorization

bearerAuth
AuthorizationBearer <token>

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://lenz.example.com/api/visionaire/analytics/config/validate" \  -H "Content-Type: application/json" \  -d '{    "analytic_id": "NFDSS-FR",    "config": "{\\"object_confidence_threshold\\": 0.7, \\"areas\\": []}",    "logic": null  }'
{  "valid": true,  "errors": [],  "parsed_config": {    "object_confidence_threshold": 0.7,    "areas": []  },  "message": "configuration is valid",  "ok": true}
{  "valid": false,  "errors": [    "object_confidence_threshold must be between 0 and 1"  ],  "parsed_config": null,  "message": "configuration validation failed",  "ok": false}

On this page