Portal
Live View
Watch live streams, move between cameras, and jump into archive playback quickly.
Primary workspace
Status
ONLINE
Streaming live
Recording
ACTIVE
1hr segments
Protocol
HLS
H264 stream
Camera
Loading
—
Loading camera...
Connecting...
CONNECTING
--:--:--PDT
PTZ Control
▲
◄
⌂
►
▼
Zoom
🔍+
🔍−
Camera Presets — Click to Move Camera
Loading presets...
📋 Camera Grid
Snapshots refresh every 10 seconds · click any card to watch live
Camera
Date Range
From
To
⏩ Live Timelapse — —
Plays today's archive at fast speed · no build step
PDT
🕐 --:--
TIMELAPSE
—
—
Timelapse Capture
Interval
5
min · 288/day
10
min · 144/day
15
min · 96/day
Not running
Build Timelapse Video
5 fps
Slow
Slow
10 fps
Normal
Normal
24 fps
Fast
Fast
30 fps
Fastest
Fastest
Select interval to see estimate
🎬 Source
📅 Time range (optional — leave blank for all snapshots)
Snapshots
Start timelapse to capture snapshots
Dashboard
⏳ Loading…
Cameras
—
total
Online
—
streaming live
Recordings
—
total clips
Rec Hours
—
stored
Storage
—
GB used
Timelapse
—
snapshots
Live Pushes
—
active streams
Bandwidth
—
total ingest
Data Usage
—
estimated
Disk Used
—
of total
Camera Status
Loading cameras...
Camera Health — Last hour (checks every 5 min)
First health check runs 30 seconds after server start...
Alert Email Settings
🔲 Pick a layout above (1 / 2 / 4 / 6 / 8 / 10 / 16), choose your cameras, then click Apply to populate this grid.
Use Sync Playback with a date + time to scrub all cameras together.
Use Sync Playback with a date + time to scrub all cameras together.
System Status
Live snapshot from self-heal watchdog (refreshes every 30s)
Overview
Core Services
Platform Checks
Recent Incidents (last 24h)
Server Health
Real-time system resources, services, and watchdog status
⏳ Loading…
Bandwidth & Cost (B2)
Cloud storage usage, per-camera egress, and a cost estimate at Backblaze's public rates. Ceiling estimate — real invoice lives on Backblaze.
📊 Measured per-camera bandwidth NEW
Loading…
Click Refresh to load.
Source: parsed from
/var/log/nginx/access.log. Tracks actual bytes-sent per /live/<camId>/ request — the true viewer traffic. Updates nightly at 02:30. The existing "Bandwidth & Cost" table above still shows the estimate; this card shows reality.
⏳ Loading…
Daily Highlights
Auto-generated Netflix-style reel of each camera's most interesting events. Emailed nightly.
⏳ Loading…
SLA Monitoring
Uptime tracking and SLA compliance per camera
⏳ Loading…
Billing & Usage
Manage pricing, per-client charges, and generate invoices
📊 At a glance — this month
Loading...
Feature Pricing
📊 Cost & Margin Analysis
Per-camera operational cost grouped by site. Revenue is computed from feature pricing × camera options. Margin = revenue − cost.
💸 Internal cost rates — what WE pay (drives margin math)
Infrastructure
Per-feature cost — added per camera when feature is enabled
Margin link
Per-cam total = storage + bandwidth + server + (enabled feature costs).
Loading…
📋 Per-Client Usage Report
Loading…
Loading per-client usage…
Payment Gateway Configuration click to expand
Configure Stripe for direct payments, or set custom payment links per client (QuickBooks, PayPal, etc.)
Webhook URL:
Add this endpoint in your Stripe Dashboard → Developers → Webhooks → "Add endpoint", then copy the signing secret here. Leaving secrets blank keeps the saved value.
https://hdrelay.io/api/stripe/webhook ·
Events: checkout.session.completed, checkout.session.async_payment_succeeded, checkout.session.async_payment_failed, checkout.session.expiredAdd this endpoint in your Stripe Dashboard → Developers → Webhooks → "Add endpoint", then copy the signing secret here. Leaving secrets blank keeps the saved value.
🔗 Default Payment Link (for all clients without a custom link)
This link appears on every client's invoice unless overridden per-client. Supports QuickBooks, PayPal, Stripe Payment Links, or any URL.
Invoice Tracking
📍 Sites — Generate Per-Site Invoice
One invoice per site, sent to the assigned bill-to client. Manager / accountant / admin users are excluded automatically.
📝 Draft Invoices
Editable invoices not yet sent to the client. Tweak line items / amounts / notes, then click Submit to finalize.
Client Accounts
Publishing
Flow Player
Multi-camera carousel embed — cycles through multiple cameras automatically with arrow controls. Completely separate from single-camera Player Profiles.
Loading…
Administration
Stream Servers
Manage regional DigitalOcean droplets that serve HLS streams to clients. Each camera is assigned to one server — the portal resolves the assignment to the correct HLS URL automatically.
Configured Servers
Loading…
How it works
- Each camera has a Stream Server field (dropdown in Manage Cameras → Edit). Default is west.
- The portal builds HLS URLs pointing to the assigned server's HLS Base URL for clients.
- The regional droplet runs a sync agent (
cam-sync-agent.sh) that polls/api/agent/cameras?server=east&token=TOKENand auto-configures MediaMTX paths for cameras assigned to it. - To move a camera east: edit it → pick East Coast → Save. The east droplet syncs within 60 s.
Sync Agent command (run on the east droplet):
The cam-sync-agent.sh script (in
curl https://hdrelay.io/api/agent/cameras?server=east&token=YOUR_SYNC_TOKENThe cam-sync-agent.sh script (in
/opt/camsentry-app/) runs this every 60 s, generates mediamtx paths, and reloads MediaMTX only when the config changes.
East Droplet Quick Setup
1. Provision a DigitalOcean droplet (NYC1 or NYC3, 2–4 vCPU).
2. Install MediaMTX:
3. Point
4. In this portal, click + Add Server, key =
5. Edit any camera → Stream Server → East Coast → Save. Streams shift within 60 s.
2. Install MediaMTX:
bash /opt/camsentry-app/east-droplet-setup.sh east.hdrelay.io YOUR_SYNC_TOKEN3. Point
east.hdrelay.io DNS A record at the new droplet IP. 4. In this portal, click + Add Server, key =
east, set HLS Base to https://east.hdrelay.io/live, paste the same token. 5. Edit any camera → Stream Server → East Coast → Save. Streams shift within 60 s.
Audit Log
Every admin action — user/camera/permission changes, payment-config edits — recorded with who, when, and from which IP.
Loading…
ℹ Audit log retains the most recent 10,000 entries. Older entries roll off automatically. The log captures key admin actions (user lifecycle, camera lifecycle, payment-config changes); read-only actions are not logged.
Operations Alerts
Internal alerts for the ops team — self-heal events, system health, SSL expiry. For client-facing detection alerts use the Camera Alerts page.
Operations Channels
Pipeline used by
self-heal.sh on the droplet. These alerts go to the ops/admin team only — never to customers.Get one at api.slack.com → your app → Incoming Webhooks → Add New Webhook to Workspace.
Comma-separated. Uses the SMTP provider configured below.
Shared SMTP Infrastructure
Used by both Operations alerts and Camera Alerts. Configure once.
Email Alerts
Use `587` for STARTTLS or `465` for SMTPS.
SMS / Webhook Alerts
Send SMS via Twilio, Vonage, or any webhook that accepts POST with {to, message}.
Alert On These Events
Choose which detection types trigger email/SMS alerts:
Notification Recipients
Only addresses on these lists receive the matching alert. Separate multiple emails with commas, semicolons, or new lines. Leave blank to disable that category.
AI detections (person, vehicle, etc.), motion, and loitering events.
Camera offline/online, disk usage, service health, and other system warnings.
Quiet Hours
Suppress email/SMS alerts during these hours (detection still runs, alerts show in portal).
From
To
Camera Alerts
Configure detection & health alerts per camera. These alerts go to your clients/users — not the ops team.
Inheritance: camera → site default → global default. Leave a field blank to inherit.
For ops alerts (self-heal, system health), see Operations Alerts.
For ops alerts (self-heal, system health), see Operations Alerts.
Pick a camera above to configure its alerts.
My Invoices
View your current service charges and usage
Loading invoice...
My Account
👤
—
@—
—
My Cameras
⏳ Loading…
My Sites
⏳ Loading…
🕐 Display Preferences
Change Password
Smart Search
🔍
Loitering Detection
Configure per-camera alerts when people linger too long
How Loitering Detection Works
🎯 AI Loitering
Uses AI object tracking to detect when a person stays in the same area beyond the set time. Most accurate — ignores shadows and wind.
Uses AI object tracking to detect when a person stays in the same area beyond the set time. Most accurate — ignores shadows and wind.
📡 Motion Loitering
Uses continuous motion detection. Alerts when motion persists in a zone beyond the set time. Works for any movement, not just people.
Uses continuous motion detection. Alerts when motion persists in a zone beyond the set time. Works for any movement, not just people.
⏰ One Alert Per Event
Each loitering event triggers only one alert. The person must leave and return to trigger again.
Each loitering event triggers only one alert. The person must leave and return to trigger again.
Loading cameras...
Traffic Statistics
Live HLS stream accesses and bandwidth, sourced from server access logs.
Loading…
Viewer Statistics
Total viewers per camera. Live counts auto-refresh every 15 seconds. View tracking must be enabled per camera for monthly/yearly/all-time figures.
Loading viewer statistics…
Viewer Analytics
Live viewers, monthly/yearly totals, country breakdown
Loading viewer analytics...
Detection Analytics
Activity trends, object breakdowns, and peak hours
Loading analytics...
Loading detection settings...
⟨/⟩ Embed Generator
Generate embed code for your cameras — live streams or timelapse
Configuration
Live stream options
Expires: —
💡 Subdomains auto-match (e.g. "example.com" covers *.example.com). Press Enter, comma, or space to add.
Preview
iFrame Embed
Direct Stream URL
HTML Wrapper
WordPress Shortcode
JS Widget (one-liner)
Use when the parent page already has a layout - no iframe, no sandbox, inherits your CSS. SPAs can call
HDRelay.refresh() after route changes.Native HLS.js Player
Power-user option - includes hls.js from a CDN and a real
<video> tag. Edit/style it however you want. Works in any framework.Direct M3U8 (VLC / OBS / native)
Paste this URL into VLC (Media -> Open Network Stream), OBS Browser Source, Roku, or any HLS player. Bypasses the web player entirely.
📺 Smart TV URL NEW
Opens fullscreen on the TV — no chrome, auto-play, auto-reconnect, screen wake-lock.
Works on Samsung Tizen, LG webOS, Roku Browser, Fire TV browser, Chromecast, Android TV. URL is short (6-character ID) so it's typeable on a TV remote.
Tip: bookmark this URL on the TV browser and set it as the home page for a one-click lobby display.
🗂 Saved TV URLs
Click Refresh to load saved TV URLs.
Every TV URL you generate is saved here. Revoke makes the link stop working immediately for the lobby it's deployed to.
Demo Shares
Generate public no-login demo links with QR codes. Collect viewer info via a pre-watch form. Ideal for marketing events, trade shows, and signage.
Loading…
Recordings
Browse, search and replay footage across Server, Cloud and SD — automatically merged and de-duped.
📍 --
💡 Tip — click a date pill below to jump straight to that day.
1
Pick a camera
2
Jump to date & time
— we'll pick the best source automatically.
Nudge
Download range — merge hours into one file click to expand ▾
From
To
Pick a date/time range above, then click Estimate.
How it works: recordings are written as 1-hour segments. The merged MP4 is a lossless concatenation of whole hourly files — the actual output will cover every segment that overlaps your range, which means it may include a few minutes before your start or after your end. For exact-second trimming, download the merged MP4 and clip it in a video editor.
Merged MP4 limited to 24 h per request (disk safety). For longer ranges, use Download TAR — streams raw hourly files in one archive, no disk temp, any length.
Merged MP4 limited to 24 h per request (disk safety). For longer ranges, use Download TAR — streams raw hourly files in one archive, no disk temp, any length.
Playback
--
Recordings load on demand
Pick a camera above, then load the list — we keep the page snappy by only pulling clips when you ask for them.
Camera
Click any thumbnail to view full size. Auto-capture runs hourly at :13 and fires only if the last capture is older than the configured interval.
Loading…
Camera
Camera Information
⏳ Loading…
Retention Overview
Loading…
Cloud (B2): long-term archive · Local: droplet disk cache (fixed 2h) · Events: AI/motion detection clips · Timelapse: snapshot retention. Changes autosave on the row. Set any retention to Off to disable that storage entirely.
Sites
Each site groups cameras by location
Loading sites...
All Sites
| Site Name | Location | Cameras | Users | Action |
|---|---|---|---|---|
| ⏳ Loading… | ||||
📷 Cameras
| Name | Site | IP | Brand | PTZ | Retention | Action |
|---|---|---|---|---|---|---|
| ⏳ Loading… | ||||||
🎬 Player Profiles
Give each camera several player "looks" — one for admins, one for public embed, one for a timelapse loop. Each profile gets its own embed URL so you can paste different versions on different sites.
⏳ Loading cameras…
👥 Users
| Name | Username | Role | Sites | Brand | Permissions | Action |
|---|---|---|---|---|---|---|
| ⏳ Loading… | ||||||
Deprecated
Layout Editor — Removed
The per-role sidebar editor has been removed. Client sidebar visibility is now driven entirely by each user's permissions — manage them on the Manage Users page.
Why was this removed?
User permissions in the Manage Users page already control which sidebar items each client sees. The Layout Editor was a second, parallel system doing the same job — a common source of "why can't I see X" confusion. With the editor gone, there is exactly one place to control what a user can see: their permissions row.
User permissions in the Manage Users page already control which sidebar items each client sees. The Layout Editor was a second, parallel system doing the same job — a common source of "why can't I see X" confusion. With the editor gone, there is exactly one place to control what a user can see: their permissions row.
To restrict a client's sidebar:
1. Open Manage Users → click Manage on the client's row
2. Toggle off the features they shouldn't see (Live View, Recordings, Detection, etc.)
3. Save — they will see the new layout on their next page load
1. Open Manage Users → click Manage on the client's row
2. Toggle off the features they shouldn't see (Live View, Recordings, Detection, etc.)
3. Save — they will see the new layout on their next page load
White Label Branding
Create custom brands — each client sees your logo, colors and company name
Active Brands
⏳ Loading…
Create New Brand
Colors
Live Preview
📹
HD Relay
Secure Camera Portal
SIGN IN
Logo / Icon Upload
No logo
PNG, JPG, SVG or WEBP · Max 2MB · Recommended: 200x60px for banner or 60x60px for icon
Browser Favicon · shows in browser tab
None
PNG, ICO, SVG or WEBP · Max 512KB · Recommended: 32×32 or 64×64
Login Background Image · optional URL, overrides color
Quick Templates · click to apply preset colors
🔗 Client Login URL
Share this URL with your client — the login page renders in their brand colors, logo, and favicon.
Enter a Brand Key above to generate…
Assign Brand to Users