The problem: a cover video on every connection
Snip Bio lets creators add a 60-second video to their profile. The upload is a 1080p file from a phone, around 150 MB. A visitor on fast Wi-Fi should see it sharp; one on a train with a weak signal should see it play without stalling, just blurrier; and if the signal improves halfway through, the picture should get sharper without restarting.
Downloading one file can't do that. Adaptive bitrate streaming can.
1. Transcode into a ladder
A worker (07.05 A job queue on Postgres with SKIP LOCKED) transcodes the upload into several versions at different resolutions and bitrates: a ladder. Apple's HLS authoring specification gives one possible ladder for 16:9 H.264 video, for example:
| Resolution | Bitrate (kbit/s) |
|---|---|
| 416 × 234 | 145 |
| 640 × 360 | 365 |
| 960 × 540 | 2,000 |
| 1280 × 720 | 3,000 to 4,500 |
| 1920 × 1080 | 6,000 to 7,800 |
Transcoding is the heavy step: minutes of CPU per minute of video per rung. It parallelises well by splitting the video into pieces, transcoding them on many workers and joining the results, so even long videos are ready quickly.
2. Cut it into segments
Each version is cut into short segments, a few seconds each, stored as separate files. Apple's specification says target durations should be 6 seconds, and that key frames (frames that decode without reference to earlier ones) should be present every two seconds.
Segments are what make switching possible: the player can fetch segment 5 at 2,000 kbit/s and segment 6 at 6,000 kbit/s. That only works if every rung's segments start at the same moments, on a keyframe, which is why keyframe placement is aligned across the ladder.
3. Describe it in playlists
With HLS (HTTP Live Streaming, RFC 8216), a master playlist lists the variants, and each variant has a media playlist listing its segments:
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=545000,RESOLUTION=640x360
360p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2400000,RESOLUTION=960x540
540p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=7000000,RESOLUTION=1920x1080
1080p/index.m3u8#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:6.0,
seg-000.ts
#EXTINF:6.0,
seg-001.ts
#EXT-X-ENDLISTBANDWIDTH is the variant's peak segment bitrate in bits per second. The player measures how fast segments
arrive and how much video it has buffered, and picks the variant for each next segment. RFC 8216 deliberately leaves
that switching algorithm to clients. DASH is the other widely used format; the idea is the same.
4. Serve it from the CDN
Every segment is a small, immutable file, which is exactly what CDNs are best at (02.05 A CDN for static content): cache them for a long time, and the origin sees almost nothing after the first viewers. A popular video's segments are served from edges near viewers; the playlists, tiny and cacheable too, point at them.
What it costs
- Storage multiplies: every rung is a full copy of the video. A short tail of rarely watched videos can skip the top rungs, generated only if anyone watches.
- Encoding time before the video is ready: show "processing" in the meantime, and transcode the lowest rung first so playback can start soon.
- Segment length trade-off: shorter segments switch quality and start faster but mean more requests and less efficient compression; longer ones are the reverse.
Seen in production
Apple
DocsHLS authoring specification
The specification says key frames (IDRs) should be present every two seconds, target and segment durations should nominally be 6 seconds, and segments must not exceed the target duration by more than half a second. It offers one possible set of bitrate variants, from 416 × 234 at 145 kbit/s up to 1920 × 1080 at 7,800, and says the default video variant should be the 2,000 kbit/s one.
What we foundSix-second segments, keyframes every two seconds, and a published example bitrate ladder.
HTTP Live Streaming (HLS) authoring specification for Apple devicesdeveloper.apple.com ↗IETF
2017RFC 8216: HTTP Live Streaming
A master playlist provides a set of variant streams, each a different version of the same content, and a media playlist lists media segments. Each variant's BANDWIDTH is its peak segment bitrate, in bits per second, and the RFC states that clients should switch between variant streams to adapt to network conditions, while the algorithms they use to switch are beyond its scope.
What we foundA master playlist of variant streams, media playlists of segments, and switching left to the client.
RFC 8216: HTTP Live Streaming (Pantos and May)rfc-editor.org ↗Snip transcodes its ladder with keyframes wherever the encoder chooses, different for each rung. Players stall or glitch when switching quality. Why?
Recap
Interview questions
How does adaptive bitrate streaming work, and how would you build the processing pipeline?