WendyOS Docs
Hardware Access

Camera Access

Use USB and CSI cameras from WendyOS apps

Camera Access

Camera access is used for webcam streaming, computer vision, image capture, and ML inference pipelines. WendyOS keeps camera devices hidden from apps by default, so your project needs a camera entitlement before the app can open /dev/video*.

Add the entitlement from your project directory:

wendy project entitlements add camera

The older video entitlement is still accepted for compatibility, but new projects should use camera.

Inspect Cameras on a Device

Use the device camera commands to see which cameras WendyOS can see:

wendy device camera list

The output includes a device ID, transport type (usb, csi, or ip), name, and — for local cameras — a path such as /dev/video0. Network cameras show their address instead of a path; see IP Cameras below. Use the ID with view commands:

wendy device camera view --id 0

To request a specific stream shape:

wendy device camera view --id 0 --width 1280 --height 720 --fps 30

If you want to pipe the encoded stream instead of opening a local preview window:

wendy device camera view --id 0 --stdout

For broad hardware inspection, filter the device capability list:

wendy device hardware list --category camera

IP Cameras

WendyOS also manages network (RTSP/ONVIF) cameras alongside local USB and CSI ones. A discovered camera is registered by its MAC address — the one identity that survives a DHCP address change — and given a stable device ID from a reserved band, 200255. That ID never changes for the life of the camera, even if its address does.

Cameras are picked up automatically as the agent's periodic discovery runs. To force a discovery round immediately and list the results in one step:

wendy device camera list --refresh

Network cameras appear in the same camera list table as local ones, with ip in the Type column, the camera's address in the Where column, and a Status of needs login, offline, or ready.

Credentials

Most IP cameras require a login before they will stream. Store one with:

wendy device camera login <id>

This prompts for the password without echoing it, or reads it from the WENDY_CAMERA_PASSWORD environment variable when there is no terminal to prompt on (for example, in CI). The username defaults to admin; pass --user to override it. Credentials are stored on the device and are never returned by any command.

Remove a camera and its stored credentials with:

wendy device camera forget <id>

To validate a camera's stored login without starting a stream:

wendy device camera test <id>

test dials the camera's RTSP port directly and reports one of three outcomes: the credentials were accepted, the camera rejected them (with a wendy device camera login <id> hint), or the camera was unreachable. One nuance worth knowing: a camera that never actually challenged for a login — no authentication required, or just a bad stream path — is still reported as success, with a detail like "did not request authentication; the stream path returned RTSP 404 and may be wrong" rather than claiming the credentials were verified.

wendy device camera view --id <id> works the same way for network cameras as for local ones. If no credentials are stored yet, it reads user/password from a camera entitlement in wendy.json if present, or prompts once interactively, before retrying the stream — see the camera entitlement fields for the wendy.json-based option and its plaintext-storage caveat.

Container Access

Apps with the camera entitlement (see Camera Entitlement) see network cameras exactly like local ones: each registered camera is mirrored into a /dev/video2xx loopback node numbered to match its own device ID — camera 212 is always /dev/video212 — and mounted into the container the same way USB and CSI devices are. A node is created before an entitled container starts; which containers currently count as consumers is kept in sync on every container start, stop, and delete, plus a periodic reconciliation roughly once a minute that catches anything those lifecycle hooks miss, such as a container's task crashing on its own.

The loopback node always carries the camera's sub-stream — the same lower-resolution feed camera view chooses automatically for anything ≤1024px wide. There is currently no way for a container to request the camera's main/high-resolution stream instead.

Builds without the kernel module: mirroring a camera into a container needs the v4l2loopback kernel module. On a WendyOS build that lacks it (or in local development), the agent logs this once and moves on:

running WendyOS build lacks the v4l2loopback module; camera view still works

(that's the underlying sentinel error's own text; the agent's warning log line paraphrases it rather than quoting it verbatim.)

wendy device camera view and wendy device camera test are unaffected either way — only the in-container /dev/video2xx mirror is unavailable.

App Configuration

A minimal wendy.json camera app looks like this:

{
  "appId": "com.example.camera",
  "platform": "linux",
  "version": "1.0.0",
  "entitlements": [
    { "type": "camera" }
  ]
}

To restrict the app to one camera device:

{
  "type": "camera",
  "allowlist": ["/dev/video0"]
}

Common Pairings

Camera apps often also need:

  • network for HTTP or WebSocket video streams
  • gpu for NVIDIA Jetson inference or accelerated image processing
  • persist for saving snapshots or clips

For a camera plus GPU app:

wendy project entitlements add camera
wendy project entitlements add gpu

Then deploy:

wendy run
The Wendy CLI deploying a camera app to a WendyOS device

On this page