← Back to the blog

Own your media: per-app S3 and recordings

Every app records to its own S3 bucket with its own credentials. How the recording-to-VOD pipeline works and why the storage boundary is per app.

2 min read
Leer en español

Your recordings, your bucket

When StreamHub records a room, the finished MP4 does not sit on the server — it is uploaded to the app's own S3 bucket, using the app's own credentials. Each app points at whatever object storage you like: AWS S3, MinIO, Backblaze B2, Cloudflare R2, any S3-compatible endpoint. The media lives where you decide, not where a vendor decides.

The recording → S3 → VOD pipeline

The critical path is worth understanding because it is the same for a one-off recording or an always-on camera:

  1. Startrecording/start tells LiveKit egress to write apps/<app>/recordings/<slug>.mp4. A VOD row is inserted with status=recording.
  2. Upload — when egress finishes, a background job uploads the local file to the app's S3, builds a public or presigned URL, and (optionally) deletes the local copy.
  3. Finalize — the job generates a snapshot, saves metadata (duration, resolution, codec), sets status=ready, and fires the vod_ready webhook.

On upload failure the local file is kept and recording_failed fires — you never silently lose a recording.

Split and snapshot

Two config knobs shape the output:

  • split_minutes cuts long recordings into parts — each part is its own MP4 and its own VOD, indexed independently. Good for 24/7 cameras.
  • snapshot_seconds captures a periodic JPEG thumbnail during the recording, uploaded to snapshots/.

Configuring an app's S3

curl -X PUT $BASE/apps/live/s3 -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
        "provider": "aws",
        "bucket": "my-live-recordings",
        "region": "us-east-1",
        "accessKeyId": "AKIA...",
        "secretAccessKey": "..."
      }'

Credentials are stored in data/secrets.json and referenced from the app's config — never in the database, never in a log.

Why per-app storage matters

A per-app bucket means clean tenancy: you can hand a customer their own bucket, meet a data-residency requirement by choosing the region, and offboard cleanly by revoking one set of credentials. The recording pipeline is identical whichever provider you point it at — StreamHub only cares that it speaks S3.