Media Storage
What This Page Covers
This page explains how recordings, clips and snapshots are stored and accessed within the Video Management Capability. It covers the S3 storage layout, the presigned URL access pattern, recording segmentation, clip assembly, snapshot upload paths and metadata persistence.
For the runtime flows that produce these media artifacts, see Streaming Flows. For camera and channel setup, see Camera Configuration.
Storage Architecture
All media — recordings, clips and snapshots — is stored in AWS S3. The Cloud NVR never serves media directly to clients. Instead, it presigns S3 URLs and hands them to the client, which then interacts with S3 directly for both uploads and downloads.
Client
│
├── Upload (presigned PUT) ──────► AWS S3
│ │
└── Download (presigned GET) ◄────────┘
Cloud NVR
├── Presigns URLs (PUT for uploads, GET for downloads)
├── Tracks metadata in RDS database
└── Listens on SQS for upload confirmations
This pattern keeps media transfer off the Cloud NVR, allowing it to focus on metadata coordination and authorization.
Presigned URL Pattern
Every media access — read or write — uses presigned S3 URLs. The Cloud NVR generates these on demand, scoped to a specific object and operation.
| Operation | URL Type | Who Uses It |
|---|---|---|
| Recording download | Presigned GET | Client (playback) |
| Snapshot download | Presigned GET | Client (viewing) |
| Clip download | Presigned GET | Client (playback) |
| Snapshot upload | Presigned PUT | Client or Local Agent |
Presigned URLs carry embedded credentials and have a limited expiration time. No additional authorization is required once the client has the URL — S3 validates the signature directly.
Access Flow
- Client requests media through the Cloud VMS API.
- Cloud VMS forwards the request to the Cloud NVR.
- Cloud NVR queries its database for metadata (paths, time ranges).
- Cloud NVR presigns the appropriate S3 URLs.
- Client receives URLs and interacts with S3 directly.
Recordings
Segmentation
While a live stream is active, the NVR Worker continuously segments the stream into 30-second recording files and uploads them to S3.
| Property | Value |
|---|---|
| Segment duration | 30 seconds |
| Upload method | rclone (HTTPS to S3) |
| Temporary storage | tmpfs on the NVR Worker |
| Trigger | Automatic while stream is active |
The NVR Worker is stateless — it buffers the current segment in tmpfs and uploads it to S3 as soon as the segment window closes. Multiple workers can process independent streams simultaneously.
Upload Notification
When a segment is uploaded, two notification paths fire in parallel:
- S3 → SQS — S3 emits an event to an SQS queue. The Cloud NVR listens on this queue for clip assembly (see below).
- NVR Worker → Cloud NVR — The worker directly notifies the Cloud NVR over HTTP that a segment was uploaded.
The Cloud NVR then persists recording metadata to its database.
Metadata
Each recording entry in the database contains:
| Field | Purpose |
|---|---|
| Channel ID | Which camera channel this recording belongs to |
| Time range | Start and end timestamp of the 30-second segment |
| S3 path | Object key in the recordings bucket |
| Status | Upload state (used during clip assembly) |
Playback
When a client requests recordings for a channel:
- The Cloud NVR queries its database, optionally filtering by time range.
- For each matching recording, it generates a presigned S3 GET URL.
- The client receives a list of recordings with their presigned URLs.
- The client downloads segments directly from S3.
The client is responsible for stitching segments together for continuous playback.
Clips
A clip is a user-defined time range extracted from continuous recordings. Unlike recordings (which are produced automatically), clips are explicitly requested by the user.
Assembly Process
Clip creation is asynchronous because the requested time range may extend into the present — segments that haven't been uploaded yet must be waited for.
| Phase | What Happens |
|---|---|
| Request | Client specifies channel ID, start time and end time |
| Entry creation | Cloud NVR creates a clip entry with status: in_progress |
| Existing segments | NVR queries the database for recordings already within the time range and appends them to the clip |
| Waiting | NVR listens on SQS for new recording uploads that fall within the range |
| Completion | Once all segments in the range are covered, clip status is set to finished |
Clip Lifecycle
| Status | Meaning |
|---|---|
in_progress | Clip is being assembled — some recordings may still be uploading |
finished | All recordings within the time range are included and the clip is accessible |
The client can poll the clip status endpoint until it transitions to finished.
Access
Finished clips are accessed using the same presigned GET URL pattern as individual recordings. The clip object in S3 contains the concatenated segments for the requested time range.
Snapshots
Snapshots are single-frame image captures associated with a camera channel. They use a two-step upload pattern: the Cloud NVR creates the metadata entry and provides a presigned PUT URL, then the uploader sends the image directly to S3.
Upload Paths
| Source | Description |
|---|---|
| Client-uploaded | The mobile app or web client captures a frame and uploads it via the presigned PUT URL |
| Agent-captured | The Local Agent on the hub captures a frame from the camera's snapshot URL and uploads it via the presigned PUT URL |
Both paths produce the same result in S3 — the distinction is only in who initiates the capture.
Upload Flow
- Client (or agent) requests a snapshot entry for a channel via the VMS API.
- Cloud NVR creates a snapshot entry in the database.
- Cloud NVR presigns an S3 PUT URL for the snapshot object.
- The presigned URL is returned to the requester.
- The requester uploads the image directly to S3 using the PUT URL.
Retrieval
Snapshots are retrieved through the same presigned GET URL mechanism as recordings. The client requests snapshot metadata for a channel, receives presigned download URLs, and fetches images directly from S3.
Metadata Database
The Cloud NVR maintains all media metadata in an RDS database. This database is the source of truth for what media exists and where it is stored — S3 is treated as a dumb object store.
| Entity | Key Fields |
|---|---|
| Recording | channel_id, time_start, time_end, s3_path |
| Clip | channel_id, clip_id, time_start, time_end, status |
| Snapshot | channel_id, snapshot_id, s3_path |
The VMS and NVR databases share the same RDS instance but use separate schemas.
Storage Characteristics
| Property | Recordings | Clips | Snapshots |
|---|---|---|---|
| Produced by | NVR Worker (automatic) | Cloud NVR (on request) | Client or Local Agent |
| Storage location | S3 recordings bucket | S3 recordings bucket | S3 recordings bucket |
| Upload method | rclone (NVR Worker → S3) | Assembled from recordings | Presigned PUT (client → S3) |
| Access method | Presigned GET URL | Presigned GET URL | Presigned GET URL |
| Granularity | 30-second segments | User-defined time range | Single frame |
NVR Worker and S3
The NVR Worker uses rclone as its S3 upload mechanism. This provides:
- Retry on transient failures
- Checksum verification of uploaded objects
- Efficient transfer without loading full segments into memory
The worker stores segments temporarily in tmpfs (RAM-backed filesystem) before upload. This avoids disk I/O bottlenecks and keeps the worker stateless — if a worker instance dies, no persistent state is lost. The segments that were in tmpfs are simply not uploaded, and the recording will have a gap for that period.
Where to Continue
| Goal | Page |
|---|---|
| See the streaming and recording flows step by step | Streaming Flows |
| Understand camera setup and channel creation | Camera Configuration |
| See the full video management model | Overview |