All Case Studies
IoT / Surveillance2025Fullstack Developer

Video Streaming Infra

RTSP-to-HLS infrastructure platform

Hono v4TypeScriptPostgreSQLMinIO S3FFmpegReact 18 + Ant Designhls.jspnpm workspace

Problem

Managing CCTV cameras usually means proprietary NVR software with vendor lock-in, no API access, and limited remote viewing. We needed an open, web-based solution that:

  • Ingests RTSP streams from any IP camera brand
  • Converts to browser-playable HLS format
  • Stores recordings on S3-compatible object storage
  • Provides a clean admin dashboard for camera management

Solution

A modern video streaming infrastructure platform:

  1. Camera CRUD: Add/remove/edit cameras via Ant Design admin panel
  2. FFmpeg Pipeline: Worker process continuously transcodes RTSP → HLS segments
  3. MinIO Storage: HLS .ts segments and .m3u8 playlists stored in S3-compatible MinIO
  4. Live Preview: hls.js player embedded in browser for zero-plugin viewing
  5. Recording Archive: Past recordings browsable by camera and date range

Architecture

IP Camera (RTSP) → FFmpeg Worker (transcode) → MinIO S3 (HLS segments)

Browser ← hls.js player ← HLS .m3u8 playlist ← MinIO presigned URL

Key Tech Decisions

FFmpeg as a Node.js child process

Rather than using a wrapper library, FFmpeg runs as a child process spawned by the Node.js worker. This gives full control over transcoding parameters (resolution, bitrate, segment duration) and proper process lifecycle management. The worker monitors FFmpeg health and auto-restarts on crash.

MinIO over AWS S3

Self-hosted MinIO provides S3-compatible API without egress costs for recording retrieval. Presigned URLs allow secure time-limited access to recordings without exposing bucket credentials to the browser.

HLS over WebRTC

Chose HLS for simplicity and CDN compatibility. WebRTC would require STUN/TURN servers and complex signaling. HLS works everywhere and the 5-10s latency is acceptable for surveillance use cases.

Metrics

Metric Value
Streaming Protocol RTSP → HLS
Storage Backend MinIO S3
Browser Playback hls.js (zero plugin)