Hikvision Cameras & NVRs
Hikvision is a production-tier adapter . It communicates with cameras and NVRs through Hikvision’s ISAPI HTTP+XML protocol with full Digest authentication. The adapter includes input validation on channel/track/snapshot IDs, an SSRF guard on NVR credential resolution, and tenant scoping on every NVR lookup.
What works
Section titled “What works”| Feature | Notes |
|---|---|
| Live MJPEG / snapshot streaming | _SnapshotCache shares one ISAPI fetch per channel across all concurrent viewers |
| PTZ control | Pan / tilt / zoom continuous move, presets (read, set, go-to), patrols |
| Recording playback | Timeline search, segment download |
| NVR import wizard | Auto-discover channels, inherit credentials per-channel with org scoping |
| Motion / line-crossing / intrusion events | Ingest via long-poll alertStream |
| License-plate recognition (LPR) | Event tagging on supported cameras |
| Camera groups, recording templates, view layouts | Full CRUD |
Hik-Connect cloud relay is not supported - local ISAPI only. Two-way audio (G.711u) is supported on compatible cameras via POST /api/v1/cameras/{id}/audio/start and POST /api/v1/cameras/{id}/audio/stop.
Adapter tier
Section titled “Adapter tier”| DG | CB | RR | TS | SSRF | RG |
|---|---|---|---|---|---|
| ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
See Adapter Contract for what each column means.
Prerequisites
Section titled “Prerequisites”- Hikvision camera or NVR firmware V4.x or later (ISAPI support)
- HTTP (port 80) or HTTPS (port 443) access from the FreeSDN host
- An admin-level account or a dedicated operator account with remote login enabled
Adding a standalone camera
Section titled “Adding a standalone camera”- In FreeSDN, open Video Surveillance → Cameras and click Add Camera.
- Select vendor Hikvision, enter the camera IP/hostname, port, and credentials.
- FreeSDN tests the ISAPI connection. On success the camera appears in the camera list.
To add via the API directly:
# Add the camera - supply credentials directly in the same request bodycurl -X POST https://freesdn.example.com/api/v1/cameras/ \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>" \ -H "Content-Type: application/json" \ -d '{ "name": "Lobby", "ip_address": "10.0.1.50", "port": 80, "vendor": "hikvision", "username": "freesdn", "password": "s3cr3t", "site_id": "<site-uuid>" }'Adding an NVR (brownfield import)
Section titled “Adding an NVR (brownfield import)”The NVR import wizard is a four-step process: test connection → discover channels → configure → import.
Step 1 - Test connection
Section titled “Step 1 - Test connection”curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/test-connection \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>" \ -H "Content-Type: application/json" \ -d '{ "host": "10.0.1.64", "port": 80, "username": "freesdn", "password": "s3cr3t" }'Response includes device_name, model, firmware_version, serial_number.
Step 2 - Discover channels
Section titled “Step 2 - Discover channels”curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/discover \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>" \ -H "Content-Type: application/json" \ -d '{ "host": "10.0.1.64", "port": 80, "username": "freesdn", "password": "s3cr3t" }'Returns a channels list (channel ID, name, online status, PTZ flag, RTSP main/sub URLs) and a storage summary (total/used GB per disk).
The adapter queries three ISAPI endpoints in order and uses the first that responds:
GET /ISAPI/ContentMgmt/InputProxy/channels(most NVRs)GET /ISAPI/System/Video/inputs/channelsGET /ISAPI/Streaming/channels(fallback)
Step 3 - Import
Section titled “Step 3 - Import”curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/import \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>" \ -H "Content-Type: application/json" \ -d '{ "host": "10.0.1.64", "port": 80, "username": "freesdn", "password": "s3cr3t", "site_id": "<site-uuid>", "name": "Office NVR", "selected_channels": [1, 2, 3, 4] }'selected_channels is optional - omit it to import all enabled channels. The import is idempotent on external_device_id; re-importing the same NVR automatically re-syncs its channels and returns a normal 201 response with "synced": true - no error is raised and no manual sync call is required.
Step 4 - Sync (on-demand refresh)
Section titled “Step 4 - Sync (on-demand refresh)”After the initial import, sync re-queries the NVR for current channels, adds new cameras, marks missing cameras offline, and updates storage stats:
curl -X POST https://freesdn.example.com/api/v1/cameras/nvrs/<nvr-uuid>/sync \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>"Returns {"added": N, "removed": N, "updated": N}.
Stream URLs
Section titled “Stream URLs”The adapter constructs RTSP URLs using Hikvision’s NVR channel-numbering convention:
| Stream | URL pattern |
|---|---|
| Main stream, channel N | rtsp://user:pass@{host}:554/Streaming/Channels/{N*100+1} |
| Sub stream, channel N | rtsp://user:pass@{host}:554/Streaming/Channels/{N*100+2} |
| Standalone camera main | rtsp://user:pass@{host}:554/Streaming/Channels/101 |
Snapshot:
GET /ISAPI/Streaming/channels/{N*100+1}/picturePTZ control
Section titled “PTZ control”PTZ is available on supported cameras via the cameras module:
# Continuous move (pan right) - action and speed are query paramscurl -X POST 'https://freesdn.example.com/api/v1/cameras/<id>/ptz?action=right&speed=50' \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>"
# Go to a saved preset - action=preset with the preset number as a query paramcurl -X POST 'https://freesdn.example.com/api/v1/cameras/<id>/ptz?action=preset&preset=1' \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>"
# Save (set) a new preset at the current camera position - preset number and name are query paramscurl -X POST 'https://freesdn.example.com/api/v1/cameras/<id>/ptz/presets?preset=1&name=Lobby+Default' \ -H "Cookie: freesdn_access=<token>" \ -H "X-CSRF-Token: <csrf>"Recording playback
Section titled “Recording playback”Search recordings by time range:
curl -H "Cookie: freesdn_access=<token>" -H "X-CSRF-Token: <csrf>" \ "https://freesdn.example.com/api/v1/cameras/recordings/search?camera_id=<id>&start_time=2026-06-01T00:00:00Z&end_time=2026-06-01T06:00:00Z"Returns a list of recording segments with start/end times and a playback URL per segment.
Events
Section titled “Events”The adapter subscribes to the long-poll ISAPI alertStream and ingests motion, line-crossing, intrusion, and LPR events into the FreeSDN event bus. Events appear on the Events page and can trigger Fabric connections.
Security notes
Section titled “Security notes”- Credentials are encrypted at rest with Fernet (derived from
ENCRYPTION_SALT). - Adapter responses are passed through the central
redact_secretsfunction (~89 sensitive keys plus Proxmoxipconfig0-ipconfig31prefix patterns, camelCase-aware) before returning to the UI. Any credential-bearing fields in ISAPI responses are stripped at this layer. - Channel IDs, track IDs, and snapshot IDs are validated (
[0-9]+, bounded) before being interpolated into ISAPI URL paths. - SSRF guard: the NVR
hostfield is validated to block loopback, link-local, and cloud metadata endpoints. RFC 1918 private ranges are allowed by default (on-prem deployments). SetBLOCK_PRIVATE_CAMERA_SUBNETS=1to also block private ranges; useALLOWED_CAMERA_SUBNETS(comma-separated CIDRs) to add custom allowlist entries.
Frontend pages
Section titled “Frontend pages”- CamerasPage - camera grid with live thumbnail previews
- CameraDetailPage - live stream, PTZ, events, recordings tabs
- CameraWallPage - multi-camera wall view
- NVRListPage / NVRDetailPage - NVR list and per-NVR channel view
- MultiPlaybackPage - synchronized multi-channel playback
Backend route prefix
Section titled “Backend route prefix”All cameras-module endpoints mount under /api/v1/cameras/. Sub-routers include nvrs, events, groups, views, recording-templates, access, streams/hls, reports, and lpr.
All product names, logos, and brands are property of their respective owners. FreeSDN is an independent project and is not affiliated with or endorsed by the vendors it integrates with. See Trademarks.