Skip to main content

Video on demand: hosting and streaming stored video

Upload, organise and deliver recorded video efficiently with object storage and HLS.

Recorded video is a delivery problem more than a hosting problem. Get the storage and the delivery format right and the rest is easy.

Where the files live

Store video in object storage, not on the web server's disk — see Object storage basics. Object storage is cheap, scales, and can be served directly to viewers or via a CDN without touching your app server.

Deliver as HLS, not a raw MP4

A single huge MP4 forces the whole file (or a large chunk) before playback, and cannot adapt to slow connections. HLS breaks the video into small segments and serves a manifest the player follows, enabling:

  • Instant start (play while downloading).

  • Adaptive quality (switch renditions mid-playback).

  • Seek anywhere, quickly.

Transcode an uploaded MP4 into HLS segments with FFmpeg · source:

bash
ffmpeg -i input.mp4 \
  -vf "scale=-2:720" -c:v libx264 -preset veryfast -crf 21 \
  -c:a aac -b:a 128k \
  -hls_time 6 -hls_playlist_type vod \
  -hls_segment_filename "seg_%03d.ts" index.m3u8

Generate a ladder (1080p/720p/480p) and a master manifest for adaptive playback.

Organise with metadata

Keep a thumbnails, title, description and duration per asset so your library is browsable. MediaCMS, PeerTube and Jellyfin (all listed under app hosting) are ready-made front-ends if you would rather not build one.

Bandwidth expectations

VOD bandwidth = bitrate × concurrent viewers. A popular 1080p library at 5 Mbps with 50 simultaneous viewers is 250 Mbit/s — object storage behind a CDN is the sane architecture at that point.

Access control

If the video is private, do not rely on an unguessable URL alone. Use signed URLs (time-limited) or a token check at the edge. Public marketing video can be genuinely public; paid content must not be.

Related reading