Skip to content

Grid tile limits

NovaVMS renders live video in a fixed grid. The cloud backend accepts six layouts; the browser is responsible for decoding each tile.

Grid layouts

Source: cloud/internal/grids/models.go (ValidLayouts, MaxCamerasPerPage). The frontend type system in frontend/src/lib/types.ts and the page-level layout list in LivePage.tsx currently advertise extra layouts (e.g. 4x4) that the backend rejects with a 400 — saving such a grid fails server-side. Stick to the six layouts below.

LayoutColumns x rowsTiles per page
1x11 x 11
2x22 x 24
2x32 x 36
2x42 x 48
3x33 x 39
3x43 x 412

A saved grid may contain multiple pages; each page holds up to 12 tiles (the backend hard cap MaxCamerasPerPage = 12). Pages are paginated — only the active page decodes video.

Per-browser decoder limits

The cloud backend enforces concurrent-viewer limits in three tiers (cloud/internal/sfu/viewer_limiter.go):

TierDefaultEnv var
Per camera10 (env) / 5 (code default)MAX_VIEWERS_PER_CAMERA
Per organisation20(not exposed via env yet)
Global100(not exposed via env yet)

The browser additionally caps simultaneous hardware-accelerated video decoders.

BrowserWebRTC PeerConnections testedMSE fallback testedNotes
Chrome (desktop)1212Backend hard cap caps a single page at 12 tiles.
Edge (desktop)1212Same engine as Chrome.
Firefox (desktop)1212MSE used for H.265.
Safari (macOS)1212MSE fallback path not exercised as heavily in TTFF testing.
Safari (iOS)44iOS throttles concurrent video decoders.
Chrome (Android)66Varies by device hardware.

Per-device observed limits depend on CPU and GPU; the backend per-camera and per-org viewer caps apply in addition.

Degradation behaviour

ConditionBehaviour
Browser cannot decode the camera codec in WebRTCTransport falls back to MSE/fMP4. See Live view transport.
Decoder count exceeded on the deviceNew tiles stay in the “Waiting for video” state until an existing tile is freed.
PeerConnection fails to establish after 5 sTile shows a reconnect indicator; retries in the background.
Per-camera viewer cap hitNew viewer receives a “Camera busy” rejection (ErrCameraBusy).
Per-org or global viewer cap hitNew viewer receives an “Organisation busy” or “Server busy” rejection.
Gateway offlineTile renders the last thumbnail with an Offline badge.