~/hailcpy
all projects
personalpythonfastapitypescriptreactffmpeghls

Self-hosted Web Media Player

A FastAPI + React media server I built because nothing off-the-shelf streamed my video collection the way I wanted. Hover previews, scrub-bar previews, on-demand HLS - all lazy, all cached, all snappy.

preview format
WebM (VP8)
scrub bar
VTT sprite sheets
streaming
on-demand HLS

Why

A big video collection on a disk attached to my home server. I wanted to watch it from any device without copying files or fighting Plex. Off-the-shelf options didn't match how I had things laid out, so I wrote my own. The interesting work was making it feel like YouTube on a home box that pre-transcodes nothing.

What makes it not boring

  • Hover previews as a single WebM per video - 20 short clips sampled across the duration, concatenated. WebM not GIF, because GIFs are huge and ugly.
  • Scrub-bar previews as VTT sprite sheets - one tiled JPEG plus a WebVTT cue map, sprite preloaded on VTT load so the browser cache is warm before the first hover. Zero HTTP per hover.
  • On-demand HLS - playlists and .ts segments synthesised at request time via ffmpeg. Storage is the constrained resource on a home box, so segments live as ephemeral output instead of pre-rendered files.
  • Thumbnails, previews, and sprite sheets all generated lazily in background threads on first metadata fetch, then cached. The grid never blocks on encoding.