DEV Community

Cian O'Sullivan
Cian O'Sullivan

Posted on

The Architecture of Live Video Streaming: How HLS, DASH, and CDNs Actually Work

Live video streaming has become the backbone of modern entertainment infrastructure. Whether a user is watching a football match, joining a video conference, or consuming on-demand content, the underlying delivery pipeline is an extraordinary feat of distributed systems engineering.

Yet most developers treat streaming as a black box. You point a video player at a URL and it works. But how does a single origin server deliver 4K video to millions of concurrent viewers without collapsing? How does the player seamlessly switch between 480p and 4K mid-stream without buffering? And why does the same stream load in 200ms in Dublin but take 4 seconds in rural Kerry?

This article breaks down the complete architecture - from ingest to last-mile delivery - with real protocol analysis and code examples.

The Streaming Pipeline: 5 Stages

Every live video stream traverses five distinct architectural stages before reaching the viewer's screen:

INGEST ──▶ TRANSCODE ──▶ PACKAGE ──▶ CDN ──▶ CLIENT
(Camera)    (Encode)     (Segment)   (Edge)   (Player)
 RTMP/SRT   H.264/265    HLS/DASH   HTTP      ExoPlayer
Enter fullscreen mode Exit fullscreen mode

Let's examine each stage.

Stage 1: Ingest - Getting the Raw Feed

The raw video signal enters the pipeline via one of two dominant protocols:

RTMP (Real-Time Messaging Protocol)

Originally developed by Macromedia (later Adobe), RTMP operates over TCP port 1935. Despite being officially deprecated, it remains the de facto ingest protocol for most streaming infrastructure due to its universal encoder support.

# Simplified RTMP handshake sequence
# C0 + C1 (client) -> S0 + S1 + S2 (server) -> C2 (client)

import struct
import os

def create_rtmp_c0_c1():
    c0 = struct.pack('B', 3)  # RTMP version 3
    timestamp = struct.pack('>I', 0)
    zero = struct.pack('>I', 0)
    random_bytes = os.urandom(1528)
    c1 = timestamp + zero + random_bytes
    return c0 + c1
Enter fullscreen mode Exit fullscreen mode

SRT (Secure Reliable Transport)

SRT is the modern successor, developed by Haivision. It operates over UDP with built-in AES-128/256 encryption and Forward Error Correction (FEC). SRT's killer feature is its adaptive bitrate recovery - it dynamically adjusts packet retransmission based on measured round-trip time (RTT), making it exceptionally resilient over unreliable WAN links.

Stage 2: Transcoding - The Adaptive Bitrate Ladder

A single 4K ingest feed must be transcoded into multiple renditions to serve the diverse range of client devices and network conditions. This set of parallel encodes is called the ABR Ladder (Adaptive Bitrate Ladder).

A typical production ABR ladder:

Rendition Resolution Bitrate Codec Use Case
UHD 3840x2160 15 Mbps H.265/HEVC Smart TV, Console
FHD 1920x1080 6 Mbps H.264/AVC Desktop, Tablet
HD 1280x720 3 Mbps H.264/AVC Mobile (Wi-Fi)
SD 854x480 1.5 Mbps H.264/AVC Mobile (4G)
Low 640x360 800 Kbps H.264/AVC Weak connections

FFmpeg Transcoding Pipeline

#!/bin/bash
# Production ABR ladder transcoding with FFmpeg

ffmpeg -i "srt://ingest.example.com:9000" \
  -filter_complex "[0:v]split=4[v1][v2][v3][v4]" \
  -map "[v1]" -c:v libx264 -b:v 6000k -maxrate 6600k \
    -bufsize 12000k -preset fast -g 48 -sc_threshold 0 \
    -s 1920x1080 -profile:v high -level 4.1 \
  -map "[v2]" -c:v libx264 -b:v 3000k -maxrate 3300k \
    -bufsize 6000k -preset fast -g 48 -sc_threshold 0 \
    -s 1280x720 -profile:v main -level 3.1 \
  -map "[v3]" -c:v libx264 -b:v 1500k -maxrate 1650k \
    -bufsize 3000k -preset fast -g 48 -sc_threshold 0 \
    -s 854x480 -profile:v main -level 3.0 \
  -map "[v4]" -c:v libx264 -b:v 800k -maxrate 880k \
    -bufsize 1600k -preset fast -g 48 -sc_threshold 0 \
    -s 640x360 -profile:v baseline -level 3.0 \
  -map 0:a -c:a aac -b:a 128k -ar 44100 \
  -f hls -hls_time 6 -hls_list_size 10 \
  -hls_flags delete_segments+independent_segments \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0 v:3,a:0" \
  stream_%v/playlist.m3u8
Enter fullscreen mode Exit fullscreen mode

Key parameters explained:

  • -g 48: GOP (Group of Pictures) size. At 24fps, this creates a keyframe every 2 seconds - critical for clean ABR switching.
  • -sc_threshold 0: Disables scene-change detection to enforce consistent GOP boundaries.
  • -hls_time 6: Each HLS segment is exactly 6 seconds long.

Stage 3: Packaging - HLS vs DASH

Once transcoded, the renditions must be packaged into a streaming format that HTTP-based CDNs can cache and serve. Two protocols dominate.

HLS (HTTP Live Streaming)

Developed by Apple (RFC 8216), HLS is the universal standard. It works by slicing the continuous video stream into small .ts (Transport Stream) or .fmp4 (Fragmented MP4) files, each typically 2-6 seconds long. A plain-text .m3u8 manifest file acts as the index.

Master Playlist (Multi-Bitrate):

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=6000000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2"
1080p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3000000,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2"
720p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=854x480,CODECS="avc1.4d401e,mp4a.40.2"
480p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,CODECS="avc1.42c015,mp4a.40.2"
360p/playlist.m3u8
Enter fullscreen mode Exit fullscreen mode

Rendition Playlist (Segment References):

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:1842
#EXTINF:6.006,
segment_1842.ts
#EXTINF:6.006,
segment_1843.ts
#EXTINF:6.006,
segment_1844.ts
Enter fullscreen mode Exit fullscreen mode

DASH (Dynamic Adaptive Streaming over HTTP)

DASH (ISO/IEC 23009-1) is the open, vendor-neutral alternative. Instead of .m3u8, it uses an XML-based Media Presentation Description (.mpd). DASH exclusively uses .mp4 containers (no .ts), which reduces overhead.

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011"
     type="dynamic"
     minimumUpdatePeriod="PT2S">
  <Period>
    <AdaptationSet mimeType="video/mp4"
                   segmentAlignment="true">
      <Representation id="1080p" bandwidth="6000000"
                      width="1920" height="1080">
        <SegmentTemplate
          media="1080p/seg_$Number$.m4s"
          initialization="1080p/init.mp4"
          startNumber="1" duration="6000"
          timescale="1000"/>
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>
Enter fullscreen mode Exit fullscreen mode

HLS vs DASH - When to Use Which?

Feature HLS DASH
Apple device support Native Requires MSE
DRM support FairPlay Widevine, PlayReady
Container format .ts or .fmp4 .mp4 only
Latency (standard) 15-30s 10-20s
Low-latency mode LL-HLS (~3s) LL-DASH (~3s)
Industry adoption Universal YouTube, Netflix

In practice, most production deployments generate both formats simultaneously from the same transcoded renditions.

Stage 4: CDN Edge Caching - The Performance Multiplier

This is where the real magic happens. A Content Delivery Network caches the video segments at geographically distributed Points of Presence (PoPs), eliminating the round-trip latency to the origin server.

How CDN Caching Works for Video

Without CDN:
  Viewer (Dublin) ---- 120ms RTT ----> Origin (Frankfurt)
  Every segment request = 120ms+ latency

With CDN:
  Viewer (Dublin) ---- 3ms RTT -----> CDN Edge (Dublin PoP)
  First request  = cache MISS (origin pull: 120ms)
  All subsequent = cache HIT  (3ms)
Enter fullscreen mode Exit fullscreen mode

For a 2-hour live stream with 6-second segments, that's 1,200 segment requests per viewer. With a CDN, only the first viewer triggers an origin pull. Every subsequent viewer on the same edge node receives the segment from local cache in single-digit milliseconds.

Cache-Control Headers for Live Video

# Nginx configuration for HLS origin

location ~ \.m3u8$ {
    # Manifests: short TTL (must update frequently)
    add_header Cache-Control "public, max-age=1, s-maxage=1";
}

location ~ \.(ts|m4s)$ {
    # Segments: long TTL (immutable once created)
    add_header Cache-Control "public, max-age=86400, immutable";
}

location ~ init\.mp4$ {
    # Init segments: very long TTL
    add_header Cache-Control "public, max-age=604800, immutable";
}
Enter fullscreen mode Exit fullscreen mode

The key insight: manifest files change every segment duration (they point to new segments), so they need ultra-short cache TTLs. But the segments themselves are immutable - they can be cached aggressively.

Ireland-Specific Network Topology

Ireland's internet infrastructure has a unique characteristic that directly impacts streaming performance: INEX (Internet Neutral Exchange). INEX operates two major peering facilities:

  • INEX Dublin (Equinix DB3, Interxion DUB1/DUB2)
  • INEX Cork (Equinix CK1)

Major CDN providers (Cloudflare, Akamai, Fastly) maintain edge nodes that peer directly at INEX. This means that for Irish users connecting through ISPs like Eir, Virgin Media, or Vodafone Ireland, video segments traverse zero international hops if the CDN has pre-positioned content at the Dublin exchange.

Eir (Subscriber) ----> INEX Dublin (Peering) <---- Cloudflare Edge PoP
                   |                                     |
                   +---------- RTT: 2-5ms ---------------+
Enter fullscreen mode Exit fullscreen mode

This local peering architecture is why properly configured streaming services can achieve sub-100ms time-to-first-byte (TTFB) for Irish viewers - comparable to serving a static HTML page. For local applications, ensuring stable routing through these domestic exchange points is crucial. You can see how this peering topology is applied in consumer-facing IPTV services at resources like iptvproviders.irish, where the infrastructure documentation covers real-world ISP routing behaviour for Irish households.

However, when the origin server is poorly configured or the CDN lacks an Irish PoP, traffic routes through London or Amsterdam, adding 15-25ms of latency per hop. This is particularly problematic for live sports, where even 200ms of additional delay creates a noticeable "spoiler effect" - a viewer on a slow path hears the neighbour celebrate a goal before seeing it on screen.

Stage 5: Client-Side ABR Algorithm

The final piece of the puzzle is the adaptive bitrate algorithm running inside the video player. This algorithm continuously monitors network conditions and decides which quality rendition to request for each upcoming segment.

Buffer-Based Algorithm (BBA)

Modern players like Google's ExoPlayer (Android) and hls.js (web) primarily use buffer-based algorithms:

// Simplified BBA (Buffer-Based Adaptation) logic

function selectRendition(currentBufferLevel, renditions) {
  const BUFFER_LOW  = 5;   // seconds
  const BUFFER_HIGH = 30;  // seconds

  if (currentBufferLevel < BUFFER_LOW) {
    // Emergency: drop to lowest quality immediately
    return renditions[renditions.length - 1]; // 360p
  }

  if (currentBufferLevel > BUFFER_HIGH) {
    // Buffer is healthy: upgrade to highest quality
    return renditions[0]; // 1080p
  }

  // Linear interpolation between low and high
  const ratio = (currentBufferLevel - BUFFER_LOW)
              / (BUFFER_HIGH - BUFFER_LOW);
  const index = Math.floor(
    (1 - ratio) * (renditions.length - 1)
  );
  return renditions[index];
}
Enter fullscreen mode Exit fullscreen mode

Measuring Real Performance

When debugging streaming issues, these are the key metrics to monitor:

// Using the Media Source Extensions (MSE) API
const video = document.querySelector('video');

const buffered = video.buffered;
const bufferEnd = buffered.length > 0
  ? buffered.end(buffered.length - 1)
  : 0;
const bufferLevel = bufferEnd - video.currentTime;

const quality = video.getVideoPlaybackQuality();
console.log({
  totalFrames: quality.totalVideoFrames,
  droppedFrames: quality.droppedVideoFrames,
  dropRate: (quality.droppedVideoFrames
            / quality.totalVideoFrames * 100)
            .toFixed(2) + '%',
  bufferLevel: bufferLevel.toFixed(1) + 's'
});
Enter fullscreen mode Exit fullscreen mode

If droppedFrames exceeds 1-2% of totalFrames, the client device is struggling with hardware decoding - typically caused by requesting an H.265/HEVC stream on a device that only supports hardware-accelerated H.264.

Low-Latency Streaming: LL-HLS and LL-DASH

Standard HLS introduces 15-30 seconds of end-to-end latency (3 segments x 6 seconds = 18 seconds minimum, plus encoding and CDN propagation delay). For live sports and interactive applications, this is unacceptable.

Low-Latency HLS (LL-HLS) solves this with two key mechanisms:

  1. Partial Segments: Instead of waiting for a complete 6-second segment, the packager emits "partial" sub-segments (typically 200ms-1s each) as soon as they are encoded.

  2. Blocking Playlist Reloads: The CDN edge server holds the client's manifest request open (HTTP long-polling) until a new partial segment is available, eliminating the polling interval entirely.

Standard HLS:
  Client polls manifest every 6s
  Gets new segment
  Plays it
  Latency: 18-30 seconds

LL-HLS:
  Client sends blocking request
  Server holds connection open
  Responds instantly when new partial is ready
  Client plays 200ms chunk
  Latency: 2-4 seconds
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  1. The ABR ladder is everything. A well-designed transcoding pipeline with proper GOP alignment is the foundation of smooth playback.

  2. Cache immutable segments aggressively. Video segments never change after creation - treat them like static assets with long TTLs.

  3. Local peering matters. For regional deployments, verify that your CDN has edge presence at the local Internet Exchange (INEX in Ireland, LINX in London, AMS-IX in Amsterdam).

  4. Buffer-based ABR beats throughput-based. Modern players should make quality decisions based on buffer health, not instantaneous bandwidth measurements.

  5. LL-HLS is production-ready. If you need sub-5-second latency, partial segments with blocking playlist reloads are the standard approach in 2026.

If you found this useful, feel free to follow for more deep-dives into distributed systems, video engineering, and network architecture.

Top comments (0)