REST API Reference
Every feature in the Videre UI is accessible via HTTP REST and WebSocket — suitable for scripting, automation pipelines, and headless integration.
Base URL & Format
Base URL: http://localhost:8080 (configurable with --port)
Content-Type: All POST request bodies are application/json. All JSON responses use Content-Type: application/json.
WebSocket URLs: ws://localhost:8080/stream and ws://localhost:8080/events
Authentication
There is no authentication. The server binds to localhost by default. If you need remote access, use SSH port forwarding — see Remote Access via SSH.
Security warning: Binding to 0.0.0.0 with --host 0.0.0.0 exposes all endpoints to your network with no access control. Use SSH port forwarding for secure remote access.
Error Format
All errors return a JSON object with an error field and an appropriate HTTP status code.
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
404 | Resource not found |
409 | Conflict — operation not allowed in current state (e.g. format change while streaming) |
500 | Internal server error |
Device Management
GET /api/devices
List all available V4L2 camera devices.
| Field | Type | Description |
|---|---|---|
path | string | Device node path |
name | string | Human-readable device name |
driver | string | Kernel driver name |
busInfo | string | Bus location identifier |
POST /api/device/open
Open a camera device for use.
| Request field | Type | Required | Description |
|---|---|---|---|
path | string | Yes | Device node path (e.g. /dev/video0) |
| Response field | Type | Description |
|---|---|---|
ok | bool | Success flag |
name | string | Device name |
path | string | Device node path |
width | int | Current frame width in pixels |
height | int | Current frame height in pixels |
pixelFormat | string | Active pixel format FourCC |
POST /api/device/close
Close the currently open camera device. No request body required.
GET /api/device/info
Get information about the currently open device.
| Field | Type | Description |
|---|---|---|
name | string | Device name |
path | string | Device node path |
width | int | Current frame width |
height | int | Current frame height |
pixelFormat | string | Active pixel format FourCC |
streaming | bool | Whether the device is currently streaming |
GET /api/device/formats
Enumerate all pixel formats and available resolutions for the open device.
| Field | Type | Description |
|---|---|---|
fourcc | string | Four-character pixel format code |
description | string | Human-readable format name |
sizeType | string | "discrete", "stepwise", or "continuous" |
sizes | array | List of {width, height} objects (discrete only) |
stepwise | object|null | Min/max/step bounds (stepwise/continuous only) |
frameRates | object | Map of "WxH" to array of supported FPS values |
GET /api/device/framerate
Get the current frame rate setting.
| Field | Type | Description |
|---|---|---|
fps | float | Current frame rate |
supported | bool | Whether the device supports frame rate control |
minFps | float | Minimum supported FPS |
maxFps | float | Maximum supported FPS |
POST /api/device/framerate
Set the frame rate.
Response: {"ok": true, "actualFps": 30.0} — the driver may clamp or round the requested value.
POST /api/device/format
Set the pixel format. Returns 409 if called while streaming.
POST /api/device/framesize
Set the frame resolution. Returns 409 if called while streaming.
GET /api/device/crop
Get hardware crop support and current crop region.
| Field | Type | Description |
|---|---|---|
supported | bool | Whether the device supports hardware cropping |
bounds | object|null | Maximum crop region (sensor bounds) |
current | object|null | Currently active crop region |
POST /api/device/crop
Apply a hardware crop region.
POST /api/device/crop/reset
Reset the crop region to the full sensor area. No request body required.
Camera Controls
GET /api/device/controls
List all V4L2 controls exposed by the open device (brightness, contrast, exposure, etc.).
| Field | Type | Description |
|---|---|---|
id | int | V4L2 control ID |
name | string | Human-readable control name |
type | string | int, bool, menu, intmenu, button, int64, string, bitmask |
minimum | int | Minimum value |
maximum | int | Maximum value |
step | int | Value step increment |
default | int | Default value |
value | int|string | Current value |
menu | array | Menu entries (only for menu and intmenu types) |
POST /api/device/control
Set a V4L2 control value. The read-back value may differ from the requested value due to driver clamping or rounding.
| Request field | Type | Required | Description |
|---|---|---|---|
id | int | Yes | V4L2 control ID |
value | int|string | Yes | New value to set |
ISP (Raspberry Pi)
These endpoints are only meaningful on Raspberry Pi 5 with an active PiSP ISP pipeline.
GET /api/isp/tuning-files
Lists available tuning files for a given sensor.
GET /api/isp/settings
Returns current ISP state. When PiSP ISP is active, fields include: available, ae, awb, awbGainR, awbGainB, blc, blcValue, lsc, dpc, denoise, sharpen, exposureUs, analogueGain, frameRate, tuningLoaded. Returns {"available":false} when ISP is not active.
POST /api/isp/settings
Updates ISP settings with a partial JSON patch.
Stream Control
POST /api/stream/start
Start capturing frames from the device. Frames become available on the /stream WebSocket.
POST /api/stream/stop
Stop capturing frames. No request body required.
GET /api/stream/decimation
Get the current frame decimation (skip) settings.
| Field | Type | Description |
|---|---|---|
adaptive | bool | Whether adaptive decimation is active |
target_fps | float | Target display FPS (adaptive mode) |
current_decimation | int | Current skip factor (1 = no skip, 2 = every 2nd frame, etc.) |
device_fps | float | Measured device capture FPS |
POST /api/stream/decimation
Configure frame decimation. Adaptive mode adjusts automatically; manual mode sets a fixed skip factor.
$ curl -X POST http://localhost:8080/api/stream/decimation -d '{"decimation": 2}'
GET /api/status
Get pipeline statistics.
| Field | Type | Description |
|---|---|---|
streaming | bool | Whether the pipeline is active |
framesProcessed | int | Total frames processed since stream start |
framesDropped | int | Frames dropped (ring buffer overflow or decimation) |
deviceFps | float | Measured device FPS |
nativeWidth | int | Native frame width from the device |
nativeHeight | int | Native frame height from the device |
WebSocket Endpoints
WS ws://localhost:8080/stream
Binary WebSocket delivering JPEG-encoded frames in real time.
Backpressure protocol: After receiving and processing each frame, the client must send an "ack" text message. The server will not send the next frame until it receives the ack — this prevents unbounded memory growth on slow clients.
| Offset | Size | Type | Field |
|---|---|---|---|
| 0 | 4 | uint32_le | Frame width |
| 4 | 4 | uint32_le | Frame height |
| 8 | 4 | uint32_le | Frame ID (low 32 bits) |
| 12 | 4 | uint32_le | Frame ID (high 32 bits) |
| 16 | variable | bytes | JPEG image data |
ws.binaryType = 'arraybuffer';
ws.onmessage = (event) => {
const data = new DataView(event.data);
const width = data.getUint32(0, true);
const height = data.getUint32(4, true);
const jpeg = new Blob([new Uint8Array(event.data, 16)], {type: 'image/jpeg'});
img.src = URL.createObjectURL(jpeg);
ws.send('ack'); // required — triggers next frame
};
WS ws://localhost:8080/events
JSON WebSocket delivering server-to-client events. The client does not send messages on this socket. Each message is a JSON object with at minimum an event field. See Events Reference for all event types.
events.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(msg.event, msg);
};
Saving Images
POST /api/save
Save the current frame to disk. Files are saved to ~/Pictures/videre/ (created automatically).
| Request field | Type | Required | Description |
|---|---|---|---|
format | string | No | "jpeg" (default), "tiff", or "raw" |
| Source format | jpeg | tiff |
|---|---|---|
| MJPEG | Raw JPEG passthrough | Not supported |
| H264 / YUYV / NV12 / RGB24 | Encoded from RGB24 | 8-bit RGB TIFF |
| GREY (8-bit mono) | Encoded from RGB24 | 8-bit grayscale TIFF |
| Y16 (16-bit mono) | Encoded from RGB24 | 16-bit grayscale TIFF (raw values) |
| Y12 (12-bit mono) | Encoded from RGB24 | 16-bit grayscale TIFF (values ×16) |
Recording Video
POST /api/recording/start
| Field | Type | Required | Description |
|---|---|---|---|
maxBytes | int | No | Maximum file size in bytes (default: ~200 MB) |
format | string | No | "avi" (MJPEG AVI, default) or "raw" (uncompressed DIB AVI) |
POST /api/recording/stop
Stop the active recording. No request body required.
GET /api/recording/status
| Field | Type | Description |
|---|---|---|
recording | bool | Whether recording is active |
path | string | Output file path |
framesRecorded | int | Total frames written |
bytesWritten | int | Total bytes written |
elapsedSec | float | Elapsed recording time |
maxBytes | int | File size limit |
Image Mode
Load a still image for offline analysis. RAW files (DNG, CR2, NEF, etc.) require a paid tier.
GET /api/image/info
Returns image-mode state. Fields: active, filename, width, height, cameraJpegAvailable, renderMode.
POST /api/image/load
Loads an image from raw request bytes. Supply an optional X-Filename header for format detection.
POST /api/image/load-path
Loads an image from a filesystem path on the server.
POST /api/image/unload
Exits image mode and returns to camera streaming.
POST /api/image/rendering
Switches render mode for RAW files. Values: "camera", "libraw", "filmic".
GET /api/image/filmic-params
Returns current filmic parameters (exposure, clarity).
POST /api/image/filmic-params
Updates filmic parameters.
Image Processing
GET /api/processing/chain
Get the full filter/detector chain — all available filters, their parameters, enabled state, and order.
| ID | Name | Category |
|---|---|---|
gaussian_blur | Gaussian Blur | filter |
median_blur | Median Blur | filter |
sharpen | Sharpen | filter |
grayscale | Grayscale | filter |
threshold | Threshold | filter |
canny_edges | Canny Edge Detection | filter |
contour_detector | Contour Detector | detector |
circle_detector | Circle Detector | detector |
blob_detector | Blob Detector | detector |
barcode_detector | Barcode Detector | detector |
Enabling any filter activates the MJPEG decompression path (frames are decoded to RGB24 for processing). When all filters are disabled, the pipeline returns to JPEG passthrough mode.
POST /api/processing/filter/enable
POST /api/processing/filter/param
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Filter/detector ID |
param | string | Yes | Parameter name |
value | int|float | Yes | New value |
Histogram
GET /api/histogram/config
Get histogram configuration constants (bin count, dimensions, etc.).
POST /api/histogram/enable
Enable per-frame histogram computation. No request body required.
POST /api/histogram/disable
Disable histogram computation. No request body required.
POST /api/histogram/analyze/start
Start a 5-second histogram analysis window. Statistics are accumulated across frames for more accurate results. No request body required.
POST /api/histogram/analyze/stop
Stop the analysis window early. No request body required.
ROI Analysis
POST /api/roi/stats
Compute statistics and line profiles for a region of interest on the current frame.
| Request field | Type | Required | Description |
|---|---|---|---|
x | int | Yes | ROI left edge (pixels) |
y | int | Yes | ROI top edge (pixels) |
width | int | Yes | ROI width (pixels) |
height | int | Yes | ROI height (pixels) |
profileMode | string | No | "single" (default) — centre row/column. "average" — averaged across full ROI. |
| Response field | Type | Description |
|---|---|---|
x, y, w, h | int | Actual clamped ROI coordinates |
bitDepth | int | Source bit depth: 8, 12, or 16 |
mono | bool | true for mono cameras (GREY/Y12/Y16); all channel arrays will be identical |
r, g, b, luma | object | Per-channel stats: min, max (uint16, native range), mean, std (float) |
hProfile | object | Horizontal line profile — per-channel uint16 array at ROI centre row |
vProfile | object | Vertical line profile — per-channel uint16 array at ROI centre column |
For GREY/Y12/Y16 sources, analysis runs at native bit depth. For Y12, values are 0–4095; for Y16, values are 0–65535. For all colour sources, bitDepth is always 8.
Overlay System
Overlays are drawn on the live viewport and can optionally be burned into snapshots and recordings (paid tiers).
GET /api/overlays
Returns the full overlay configuration. Fields: global, overlays.
GET /api/overlays/capabilities
Returns tier-gated overlay capabilities. Fields: recordingBurnIn, customAssetOverlay, measurementOverlays.
POST /api/overlays/global
Updates global overlay settings.
POST /api/overlays/create
Creates an overlay. Key fields: id, name, type, enabled, opacity, color, zIndex, position, lineThickness, visibleInPreview, includeInSnapshot, includeInRecording.
POST /api/overlays/update
Updates an existing overlay by id.
POST /api/overlays/delete
Deletes an overlay by id.
Diagnostics
GET /api/diagnostics
Full system diagnostics — host system info, detected hardware, and actionable recommendations.
GET /api/diagnostics/pipeline
Live pipeline timing data from a ring buffer of recent frames.
| Timing field | Description |
|---|---|
captureMs | V4L2 buffer dequeue time |
h264DecodeMs | H.264 frame decode (0.0 if not H.264) |
formatConvertMs | Pixel format conversion to RGB24 |
filterChainMs | All enabled pixel filters (sequential) |
detectorsMs | All enabled detectors (parallel) |
histogramMs | Histogram computation |
downscaleMs | Resolution downscale (if applicable) |
jpegEncodeMs | JPEG encoding for WebSocket delivery |
totalProcessingMs | Total pipeline time per frame |
Settings
POST /api/settings
| Field | Type | Description |
|---|---|---|
closeOnBrowserDisconnect | bool | If true, server shuts down when the browser disconnects (4s grace period). Default: true. |
Usage Data
GET /api/telemetry/consent
Get the current usage data consent status.
| Field | Type | Description |
|---|---|---|
required | bool | Whether consent is required before use |
given | bool | Whether the user has responded to the consent prompt |
tier | string | License tier: "community", "pro", "subscription", "source" |
POST /api/telemetry/consent
Accept or decline usage data consent.
POST /api/telemetry/feature
Record a feature usage event.
Known feature identifiers: histogram, snapshot, recording, filter_enable, flip_h, flip_v, crop, zoom_fit, histogram_open, roi_open.
Licensing
Paid-tier endpoints. Only meaningful in Pro, Subscription, or Source builds.
GET /api/license/status
Returns current license state. Fields: ok, tier, state, hasActivationToken, hasLocalBinding, optionally licenseKey.
POST /api/license/activate
Activates a paid license on the current device.
Response fields: ok, state, tier, activationType, remainingCredits.
POST /api/license/local-bind
Stores a local single-device binding without consuming an activation credit.
POST /api/license/validate-current
Validates the cached activation token with the backend.
POST /api/license/revoke-current
Revokes the current device activation and frees the activation credit.
Events Reference
Events are delivered over the ws://localhost:8080/events WebSocket. Each message is a JSON object with an event field.
| Event | Payload fields | Description |
|---|---|---|
deviceOpened | name, path, width, height, pixelFormat | A camera was opened |
deviceClosed | — | The active camera was closed |
deviceError | error | A device error occurred |
streamStarted | — | Streaming began |
streamStopped | — | Streaming ended |
formatChanged | width, height, pixelFormat | Pixel format or resolution changed |
controlChanged | id, value | A V4L2 control value changed |
recordingStarted | path | Recording began |
recordingStopped | path, framesRecorded, bytesWritten | Recording ended |
recordingProgress | framesRecorded, bytesWritten, elapsedSec | Periodic recording status |
histogramAnalyzeStarted | — | Histogram analysis window opened |
histogramAnalyzeStopped | — | Histogram analysis window closed |
processingConfigChanged | — | Filter chain configuration changed |
usageLimitReached | — | Community 1-hour limit reached; heartbeat verification starting |
usageLimitVerified | — | Heartbeat succeeded; usage verified |
heartbeatFailed | — | Heartbeat failed; app will shut down in 3 seconds |
devicesChanged | — | USB hotplug detected; re-enumerate with GET /api/devices |
Headless Usage
Videre can be operated entirely via REST without a browser — useful for scripting, testing, and embedded deployments.
$ curl -s -X POST localhost:9000/api/device/open -d '{"path":"/dev/video0"}'
$ curl -s -X POST localhost:9000/api/device/framesize -d '{"width":1920,"height":1080}'
$ curl -s -X POST localhost:9000/api/stream/start
$ sleep 1
$ curl -s -X POST localhost:9000/api/save -d '{"format":"jpeg"}'
$ curl -s -X POST localhost:9000/api/stream/stop
$ curl -s -X POST localhost:9000/api/device/close
$ curl -s -X POST localhost:8080/api/stream/start
$ curl -s -X POST localhost:8080/api/recording/start -d '{"format":"avi"}'
$ sleep 10
$ curl -s -X POST localhost:8080/api/recording/stop
$ curl -s -X POST localhost:8080/api/stream/stop
$ curl -s -X POST localhost:8080/api/device/close
Remote Access via SSH
Videre binds to localhost by default. To access it from another machine, use SSH port forwarding — both REST and WebSocket connections tunnel through SSH.
$ ssh -L 8080:localhost:8080 user@camera-host
# Use a different local port
$ ssh -L 9000:localhost:8080 user@camera-host
# Persistent background tunnel
$ ssh -fNL 8080:localhost:8080 user@camera-host
# Two cameras on different ports
$ ssh -L 8080:localhost:8080 -L 8081:localhost:8081 user@camera-host