# X-Edge Vision > On-premise video AI for the edge. IP cameras in, real-time detections out, watched from any browser on your network. > Full documentation corpus. Source: https://edgevision-docs.pages.dev/ --- ## Product overview > What X-Edge Vision is, what it does, and what runs on the device. X-Edge Vision is an edge video analytics appliance. It connects to IP cameras over RTSP, runs GPU-accelerated object detection on an NVIDIA Jetson, and shows live video, detections, events and system health in a browser-based operator console. Everything runs on the device itself. There is no cloud service and no desktop client, and nothing leaves your site. ### What you get - **Live view with AI overlay.** Watch one camera, two cameras side by side, or a 2×2 grid over low-latency WebRTC. Detection boxes and track trails are matched to the exact video frame they belong to. - **Zones and rules.** Draw zones on a camera image, then combine a zone with object classes to make a rule. - **Events and alarms.** Rule matches and health conditions become events that operators can acknowledge, resolve and export. A notification inbox shows what is unread. - **Analytics.** Detection counts and trends over time, per camera and per class. - **Camera management.** Add and test RTSP cameras, enable or disable them, and keep their credentials encrypted on the device. The appliance checks the video relay continuously and repairs any camera path it has lost. - **Model registry.** Upload an ONNX model, build its TensorRT engine on the device, and assign it to cameras. YOLOX and YOLOv5 detectors are supported first, and the detector is a replaceable component. - **System health.** Camera, video, inference and device health. A condition has to hold, and then clear, before an event opens or closes, so a flapping camera does not flood the event log. - **Secure by default.** A new appliance is claimed with a one-time setup code. After that, sign-in uses short-lived sessions, passwords are hashed with Argon2id, there are Administrator, Engineer and Operator roles, and every change is written to an audit log. ### Who it is for | Role | What they do | |---|---| | Operator | Watches live video, handles alarms and notifications. | | Engineer | Manages cameras, zones, rules and models. | | Administrator | Everything an engineer does, plus users and the audit log. | | Installer | Puts the device on site, connects it to the network and updates it. | ### What runs on the device The console, the API, the detection pipeline and the database all run on the Jetson. Only the video relay runs in a container. - **Platform:** NVIDIA Jetson. The product is built and validated on a Jetson TX2. - **Console address:** `http://:5080/` - **Video:** goes from the camera to your browser through a relay and is not decoded or re-encoded on the way. - [Quick start](/install-deploy/quickstart/) — Open the console, claim the device and see your first camera. - [Architecture](/architecture/) — How video, detections and control flow through the device. --- ## Quick start > Claim a new X-Edge Vision device, add a camera and watch live video with detections. This page takes a device that is installed on your network and gets you to live video with detections. It assumes the device has already been provisioned and has the release installed. If it has not, ask your installer or Xisom support. ### What you need - The device's network address, and a login name for it. - A laptop or PC on the same network, with a current browser. - At least one IP camera that serves RTSP and is reachable from the device. Below, `
` is the device's address and `` is its login name. 1. **Check that the device answers.** From your laptop: ```bash curl -s -o /dev/null -w '%{http_code}\n' http://
:5080/health/live ``` It prints `200`. Anything else means the service is not running. See [Running and status](/operate/running-and-status/). 2. **Read the setup code.** A new device has no owner yet, and every page except the setup screen answers `NOT_PROVISIONED` until someone claims it. The device prints a one-time code to its log: ```bash ssh @
'grep "Setup code" ~/backend.log | tail -1' ``` The code works once and expires after 24 hours. After five wrong attempts the device refuses further tries (`429`) until it is restarted. A new code is generated every time an unclaimed device starts, and older codes stop working. 3. **Claim the device.** Open `http://
:5080/` in your browser. Enter the setup code, then create the first administrator account. The password must be at least 12 characters. 4. **Add a camera.** Open **Cameras** and add the camera's RTSP address and, if it needs one, its login. Test the connection, then enable the camera. The device stores camera credentials encrypted and never shows them again. 5. **Watch it live.** Open **Live View**. Choose one camera, two side by side, or a 2×2 grid, and assign cameras to the tiles. Once an AI model is assigned to the camera, detection boxes are drawn on the video. 6. **Check the AI model.** Open **AI Models**. The two built-in detectors, `yolox-tiny-416-fp16` and `yolov5n-640-fp16`, show as **Registered** until their engine file is on the device, and as **Ready** after it is there and the service has restarted. Your installer places the engine files. You can also upload your own ONNX model from this page. ### If something does not work - **The page loads but a camera tile has no picture.** The video relay may be stopped, or the network blocks `8189/udp`. See [Troubleshooting](/troubleshooting/no-video/). - **You cannot find the setup code.** The log is `~/backend.log` in the login's home folder. `journalctl` shows nothing, because the service does not log to it. - **Every page says `NOT_PROVISIONED`.** The device is not claimed yet. Go back to step 2. - [Running and status](/operate/running-and-status/) — Start, stop and check the services, and find the logs. - [Updating a device](/operate/updating-a-device/) — Install a signed update bundle on site. --- ## Running and status > Check, start and stop the X-Edge Vision services on the device, and find their logs. Two services make up the appliance. Run these commands on the device, over `ssh`. | | Backend (and the detection pipeline it supervises) | Video relay | |---|---|---| | Is it running | `systemctl is-active edgevision-api` | `docker ps --filter name=edge-relay` | | Start | `sudo systemctl start edgevision-api` | `docker start edge-relay` | | Stop | `sudo systemctl stop edgevision-api` | `docker stop edge-relay` | | Log | `~/backend.log` | `docker logs edge-relay` | The backend log is a file in the login's home folder. `journalctl -u edgevision-api` shows nothing, by design. ### Two behaviours that look like faults but are not - **A stopped relay stays stopped.** Its restart policy brings it back after a reboot or a Docker restart, but deliberately not after an explicit `docker stop`. In the same way, the backend being *enabled* means it starts at boot, not that it is running now. - **The backend can run with no video.** The two are independent. A missing relay shows as camera tiles with no picture, not as a failed service. When the relay is back, the backend restores its camera paths at its next check, which runs every 30 seconds by default, with no restart. ### Check a device ```bash # The appliance answers. curl -s -o /dev/null -w '%{http_code}\n' http://
:5080/health/live # 200 # It starts again after a reboot. ssh @
'systemctl is-enabled edgevision-api' # enabled # Which version it runs. ssh @
'cat ~/edgevision/VERSION' ``` Then open the console and watch **Live View**: the boxes should sit on the objects, and the reported rate should hold. ### Where things are | Path on the device | What it is | |---|---| | `~/edgevision/EdgeVision.Api` | The backend program | | `~/edgevision/wwwroot/` | The operator console | | `~/edgevision/edgevision.db` | The database (SQLite) | | `~/edgevision/appliance.json` | Seeds the first camera and the built-in models | | `~/edgevision/models/` | Uploaded models and the engines built from them | | `~/edgevision/install.log` | Everything the installer printed | | `~/backend.log` | The backend log | After the first start, the database is the authority for cameras and models, not `appliance.json`. ### Back up the database The installer snapshots the database before each update and keeps three. To take one by hand, stop the service first. A copy taken while the service holds the file is not consistent. ```bash ssh @
'sudo systemctl stop edgevision-api && cd ~/edgevision \ && cp -p edgevision.db backups/manual-$(date -u +%Y%m%dT%H%M%SZ).db \ && sudo systemctl start edgevision-api' ``` --- ## Updating a device > Install a signed X-Edge Vision update on site in about two minutes, and read the result. For the person on site. An update takes about two minutes. If anything below is unclear, stop and contact support before you start. ### What you need - The two update files, with the same name and one ending in `.sig`: `edgevision--tx2-arm64.tar.gz` and `edgevision--tx2-arm64.tar.gz.sig`. Both are needed. The second proves the first came from Xisom and was not changed. - A laptop on the same network as the device, the device's address, and its login name. Do not switch the device off or unplug it from the moment you press Enter in step 3 until you see the last line. ### Steps 1. **Copy the two files to the device**, into one folder (here `incoming`), from the laptop. If the folder does not exist yet, make it first with `ssh @
mkdir -p incoming`. ```bash scp edgevision--tx2-arm64.tar.gz edgevision--tx2-arm64.tar.gz.sig @
:incoming/ ``` 2. **Log in to the device:** ```bash ssh @
``` 3. **Run the update** with the name of the first file, as yourself and not with `sudo`: ```bash edgevision-install incoming/edgevision--tx2-arm64.tar.gz ``` It prints what it is doing. Wait until it returns to the prompt, then read the last lines. ### What the last line means | It says | What it means | What you do | |---|---|---| | `Installed .` | The device runs the new version and the video part is running. | Open `http://
:5080/` and check the version at the bottom of the page. | | `Installed , but the relay is NOT running: ...` | The device runs the new version, but cameras show no video until the video part is fixed. | Do not try again. Send the log to support and say the device shows no video. | | `Not installed: ...` and `The device is still running .` | Nothing was changed. The line before says why. | See the reasons below. | | `Not installed: the new version did not start.` and `The previous version is running again.` | The new version did not work and the device put the old one back by itself. | Send the log to support. Do not try the same files again. | | `THE DEVICE IS NOT RUNNING. Do not switch it off.` | The device could not recover on its own. | Do not switch it off. Send the log to support now. | #### Reasons after "Not installed" | The reason starts | Usually | What to do | |---|---|---| | `there is no signature file beside the bundle` | The `.sig` file is missing or named differently. | Copy the `.sig` file with the same name into the same folder and repeat step 3. | | `the signature does not match` | The file was damaged while copying, or it is the wrong file for this device. | Copy both files again from the original source and repeat step 3. If it happens again, send the log to support. | | `a file in the bundle does not match its checksum` | The same, or the update itself is wrong. | Copy again. If it happens again, send the log to support. | | `version ... is already installed` | This update is already on the device. | Nothing to do. | | `version ... is older than the installed ...` | You have an older update than the one on the device. | Nothing was changed. Ask support for the right file. | | `not enough free space` | The device is full. | Send the log to support. | | `this bundle is for a Jetson TX2` | You are logged in to a different machine. | Log out, check the address and start again from step 2. | | `this must not be run as root` | The command was run with `sudo` or as the administrator. | Run it again as the normal login, without `sudo`. | | `this bundle needs a newer device setup` | The device needs a setup step that only support can do. | Send the log to support. | ### What to send back when something goes wrong Send two things to support: 1. The log, from the laptop: ```bash scp @
:edgevision/install.log . ``` 2. The version the device runs, from the device: `cat edgevision/VERSION`. Also say which file name you used and what the last line said. ### What the installer protects Before anything changes, the installer checks the signature against the public key that was installed on the device when it was set up, and every file against the bundle's checksums. It always refuses an older version, because database migrations only run forward. It takes a database snapshot and, if the new version does not answer, puts back the previous program, console, inference code and database. Copying the files by USB stick has not been tried, so it is not described here. --- ## Troubleshooting > Symptoms, causes and fixes for an X-Edge Vision device. Find your symptom in the table. For video problems, see [No video](/troubleshooting/no-video/). | Symptom | Cause and fix | |---|---| | Every page says `NOT_PROVISIONED` | The device is not claimed yet. Read the setup code and claim it. See [Quick start](/install-deploy/quickstart/). | | The setup code is rejected | It works once, expires after 24 hours, and a restart of an unclaimed device makes a new one. Read the latest from `~/backend.log`. After five wrong attempts the device answers `429` until it is restarted: run `sudo systemctl restart edgevision-api`, then read the new code. | | `journalctl -u edgevision-api` is empty | Expected. The service writes to `~/backend.log` instead. | | `~/backend.log` is large | Only an update rotates it, keeping one older copy. Between updates it grows. Check its size with `ls -la ~/backend.log`. | | The service is running but does not start after a reboot | Check `systemctl is-enabled edgevision-api`. If it says anything but `enabled`, contact support to re-run the device setup. | | Both built-in models show **Registered** | Their engine files are not on the device yet. Your installer places them, and the models become **Ready** after the service restarts. You can also upload your own model. | | Choosing ByteTrack leaves the IOU tracker running | The ByteTrack library or its tracker file is not installed on the device. The screen names which one is missing. | ### Related - [No video](/troubleshooting/no-video/) - [Running and status](/operate/running-and-status/) - [Updating a device](/operate/updating-a-device/) --- ## No video > The console loads but a camera tile shows no picture. The console and the video take different routes, so the console can work while video does not. ### Check in this order 1. **Is the relay running?** On the device: ```bash docker ps --filter name=edge-relay ``` If nothing is listed, start it with `docker start edge-relay`. A relay that was stopped by hand stays stopped on purpose. Within about 30 seconds of it returning, the backend puts the camera paths back without a restart. 2. **Is `8189/udp` open?** If the console connects and reports a connection but no video ever arrives, this is the usual cause. Allow `8189/udp` between the browser and the device, along with `8889/tcp`, `8554/tcp` and `5080/tcp`. 3. **Is the camera reachable?** Open **Cameras** and test the camera. The camera state names its cause. A camera that is off, unreachable or rejecting its login shows no video however the device is working. 4. **Did an update leave the relay down?** The last line of an update that says `but the relay is NOT running` means the device runs the new version without video. Do not install again. Send `~/edgevision/install.log` to support. ### Related - [Architecture](/architecture/) - [Running and status](/operate/running-and-status/) --- ## API overview > The public REST and WebSocket interfaces of the X-Edge Vision appliance, and the rules every route follows. The appliance exposes a REST API under `/api/v1` and a WebSocket stream at `/ws/v1/stream`, both on port `5080`. The operator console uses the same interfaces. The full REST contract, with every request and response body, is the OpenAPI file [`/openapi/rest-v1.json`](/openapi/rest-v1.json). It is generated from the code and checked against real responses. ### Public surfaces | Surface | Use | |---|---| | `/api/v1/*` | REST routes, authenticated per route | | `/ws/v1/stream` | Live detections, camera status and alarm events as JSON | | `/whep/*` | WebRTC video signalling. The video itself travels from the relay to the browser, not through the API | | `GET /health/live` | Anonymous liveness check. It answers `200` when the service is up | ### Rules every route follows | Topic | Rule | |---|---| | Authentication | Send `Authorization: Bearer `. An access token is valid for 15 minutes. The refresh token is an HttpOnly cookie, `ev_refresh`, valid for 14 days. | | Roles | `read` (Administrator, Engineer, Operator), `configure-inference` (Administrator, Engineer) and `administer` (Administrator). | | Unclaimed device | Until an administrator is claimed, every path answers `403 NOT_PROVISIONED` except `/health/live`, `/api/v1/setup/*` and `/api/v1/system/info`. | | Errors | `application/problem+json` with a stable `code`. Branch on `code`, never on `title` or `detail`, which are prose and can be reworded. Field validation is `422 VALIDATION_FAILED` with an `errors` map keyed by the JSON field name. | | Concurrent edits | Reads of editable rows carry a weak `ETag`. Send it back as `If-Match` on a write. A missing `If-Match` gets `428`, and a stale one gets `412` with the current version in `current`. | | Partial updates | In a `PATCH`, a missing field means leave it unchanged, and an explicit `null` means clear it. | | Lists | Always an object with an `items` array. Offset paging returns `total`, `page` and `pageSize`. Keyset paging returns `total` and `nextCursor`. | | Asynchronous work | `202 Accepted` means the work was requested, not finished. Read the outcome from a status route. | | Audit | Every change that reaches its handler writes an audit entry named `resource.action`, for example `camera.update`. | ### Live stream 1. Request a ticket with `POST /api/v1/ws-tickets` and a bearer token. The reply is `{ ticket, expiresInSeconds }`. A ticket works once and lasts 30 seconds. 2. Open `GET /ws/v1/stream?ticket=` as a WebSocket. A missing, expired or used ticket answers `401` before the handshake. 3. The first frame is `hello`. The socket starts with no cameras, so send `{ "type": "subscribe", "cameras": [""] }` for up to 64 cameras. A **detection** arrives as a JSON object with no `type` field. Every other frame has a string `type`: `hello`, `subscribed`, `clock`, `cameraStatus`, `event` and `alertState`. Clients tell the two apart by whether `type` is present. Up to 16 viewers can be connected at once by default. When the limit is reached the server closes the socket with `1008 too many clients`. A client that does not read fast enough is closed with `1008 too slow`, and should reconnect. ### Versioning The version is in the path, `/api/v1` and `/ws/v1`. Within a version, new routes, new optional request fields, new response fields and new error codes can be added. Ignore fields you do not know, and handle an unknown error `code` by its HTTP status class. Removing or renaming a route or field, changing a type or meaning, or making a policy stricter is a breaking change. It goes through a deprecation period or a new version path. The REST API, the live stream and the detection payload are versioned separately. The detection payload carries `schemaVersion`, currently `"1.0"`. --- ## Architecture > How video, detections and control move through the X-Edge Vision appliance. The appliance keeps video and detection data on **separate paths**. Video is never decoded or re-encoded on its way to your browser, and the backend never touches a video frame. Detections travel as small messages and are drawn over the frame they were computed on. ```mermaid flowchart LR cam[IP cameras
RTSP] --> relay[Video relay
MediaMTX] cam --> pipe[Detection pipeline
DeepStream] relay -- "WebRTC video" --> browser[Operator console
in your browser] pipe -- "detections" --> api[EdgeVision API] api -- "WebSocket + REST" --> browser api --- db[(SQLite)] api --- models[(Model store)] api -. "supervises" .-> pipe api -. "keeps camera paths" .-> relay ``` ### The three planes - **Video plane.** Camera, then relay, then browser over WebRTC. The relay passes the video through without decoding it. - **Metadata plane.** The detection pipeline publishes one detection message per frame. The API forwards it over a WebSocket, and the browser draws it over the frame it belongs to. - **Control and state.** The API starts and stops the detection pipeline, keeps the relay's camera paths in place, builds TensorRT engines, handles authentication, and stores all state in a local SQLite database. ### Network ports The device listens on these ports. Allow them on your site network. | Port | Used for | |---|---| | `5080/tcp` | Operator console and API | | `8554/tcp` | RTSP, served by the relay | | `8889/tcp` | WebRTC signalling (WHEP) | | `8189/udp` | WebRTC media (ICE) | If `8189/udp` is blocked, the console connects but no video arrives. ### Failure behaviour - The API can run without video. If the relay stops, camera tiles show no picture but the console keeps working. When the relay comes back, the API restores its camera paths within about 30 seconds, without a restart. - A release that fails to start is rolled back by the installer, along with the database snapshot taken before it. See [Updating a device](/operate/updating-a-device/). - [Running and status](/operate/running-and-status/) — Check what is running and where its logs are. - [API overview](/api-reference/overview/) — The public interfaces and how they are versioned. --- ## Release notes > What changed in each X-Edge Vision release. Releases are numbered `major.minor.patch`. The current version is shown at the bottom of the console and in `GET /api/v1/system/info`. ### 0.1.3, 2026-10-20 - **Fixed:** a new device no longer lists its two built-in detectors as **Ready** when their engine files are not on the device. They show as **Registered**, with the path to put the engine at, and become **Ready** at the next start once the file is there. ### 0.1.2, 2026-10-20 - **Fixed:** a device installed over `ssh` now reports its real version. Before, it reported `1.0.0`, so the installer refused every update bundle as a downgrade. - **Fixed:** a rollback now puts back the console and the inference code together with the program and the database. Before, a release that failed to start could leave the previous backend running behind the new console. ### 0.1.1, 2026-10-20 - **Added:** signed update bundles. `edgevision-install` on the device checks the signature and every file, refuses an older version, installs the new one, and restores the previous program and database if the new version does not answer. - **Added:** the video relay travels in the bundle and is loaded offline. If the relay cannot be started, the appliance keeps the new version and the installer says why. - **Added:** the console footer and `/api/v1/system/info` report the release version. ### 0.1.0, 2026-10-19 The first versioned release. - **Inference on the device:** a DeepStream pipeline for YOLOX, YOLOv5, YOLOv8, YOLOv8 segmentation and YOLOv8 pose detectors, one pipeline serving several cameras, and a selectable ByteTrack tracker. - **Appliance:** claiming a new device, sign-in with roles, a readable audit trail, cameras with decided states and causes, a model registry that builds its own engines, events with rules and zones, notifications, analytics and a health board. - **Console:** Overview, Live View, Cameras, Events, Analytics, AI Models, System Health and Settings, with zone drawing and an alarm list that can be exported. - **REST contract:** a generated OpenAPI contract for every route, and a check that refuses a change that breaks the one on the device.