What Is HLS?
HLS (HTTP Live Streaming) is Apple's adaptive bitrate streaming protocol, introduced in 2009 and standardized as RFC 8216 in 2017. It is the dominant streaming protocol on the internet today, used by virtually every major streaming platform — Netflix, Disney+, YouTube, Twitch, Hulu, and countless others — to deliver video to browsers, mobile devices, and smart TVs.
The central insight of HLS is simple but powerful: instead of sending video as a continuous stream (which breaks catastrophically when the network fluctuates), split the video into small segments and serve them over plain HTTP. The client downloads segments ahead of playback, monitors its download speed, and dynamically switches between quality levels to maintain smooth playback.
The M3U8 Playlist File
The .m3u8 file is the text-based manifest that tells the HLS player what to download. The name comes from M3U (an audio playlist format from the 1990s) extended to UTF-8 encoding.
Master Playlist
The master playlist (also called the multivariant playlist) lists all available quality renditions of a stream. The player downloads this first, picks the appropriate quality, and follows the media playlist URL.
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-STREAM-INF:BANDWIDTH=400000,RESOLUTION=426x240,CODECS="avc1.42c01e,mp4a.40.2"
240p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,CODECS="avc1.42c01e,mp4a.40.2"
360p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=1400000,RESOLUTION=854x480,CODECS="avc1.4d401f,mp4a.40.2"
480p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2"
720p/index.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=5000000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2"
1080p/index.m3u8
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="en",URI="subtitles/en.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Español",DEFAULT=NO,LANGUAGE="es",URI="subtitles/es.m3u8"
Key master playlist tags:
| Tag | Purpose |
|---|---|
#EXTM3U |
Required first line — identifies as Extended M3U |
#EXT-X-VERSION |
HLS protocol version (3 is widely compatible; 7 for new features) |
#EXT-X-STREAM-INF |
Describes a rendition: bandwidth, resolution, codecs |
BANDWIDTH |
Peak bandwidth in bits/second — used for ABR decisions |
AVERAGE-BANDWIDTH |
Average bandwidth (more accurate for ABR) |
RESOLUTION |
Video dimensions WxH |
CODECS |
RFC 6381 codec strings (e.g., avc1.640028 = H.264 High Profile Level 4.0) |
FRAME-RATE |
Frames per second (important for high-frame-rate content) |
#EXT-X-MEDIA |
Alternate renditions: audio tracks, subtitles, closed captions |
#EXT-X-I-FRAME-STREAM-INF |
I-frame only playlist for trick play (fast forward/rewind) |
Media Playlist
The media playlist lists the actual video segments with their durations. The player requests this to know what to download next.
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:6.006,
segment000.ts
#EXTINF:6.006,
segment001.ts
#EXTINF:6.006,
segment002.ts
#EXTINF:5.994,
segment003.ts
#EXT-X-ENDLIST
Key media playlist tags:
| Tag | Purpose |
|---|---|
#EXT-X-TARGETDURATION |
Maximum segment duration in seconds (rounded up) |
#EXT-X-MEDIA-SEQUENCE |
Sequence number of first segment (for live streams) |
#EXT-X-PLAYLIST-TYPE |
VOD (complete, static) or EVENT (live with growing list) |
#EXTINF |
Duration of following segment (e.g., 6.006, — comma required) |
#EXT-X-ENDLIST |
Present for VOD/EVENT — marks the playlist as complete |
#EXT-X-MAP |
Initialization segment (for fMP4 segments, HLS v6+) |
#EXT-X-KEY |
Encryption key information for AES-128 or SAMPLE-AES DRM |
#EXT-X-DISCONTINUITY |
Marks timeline gap (e.g., ad insertion) |
#EXT-X-PROGRAM-DATE-TIME |
Wall clock time of first segment (ISO 8601) |
HLS Segment Formats
MPEG-2 Transport Stream (.ts)
The original HLS segment format. Each .ts file is an independent, self-contained MPEG-2 Transport Stream. .ts segments work with HLS version 1-5 and have excellent compatibility with older devices.
# Examine a .ts segment
ffprobe -v quiet -print_format json -show_streams segment000.ts
Fragmented MP4 (.fmp4)
Introduced in HLS version 6 (2016), fragmented MP4 segments offer several advantages over .ts:
- Smaller file size (no transport stream overhead)
- Same format as DASH segments (enabling shared CDN infrastructure)
- Better support for modern codecs (HEVC/H.265, FLAC audio)
- Required for low-latency HLS (LHLS)
fMP4 requires an initialization segment (#EXT-X-MAP) containing the box headers.
Creating HLS Streams with FFmpeg
FFmpeg has native HLS output support:
# Simple HLS from an MP4 — single quality, .ts segments, 6-second segments
ffmpeg -i input.mp4 \
-c:v libx264 -c:a aac \
-hls_time 6 \
-hls_playlist_type vod \
-hls_segment_filename 'segments/segment%03d.ts' \
output.m3u8
# Multi-bitrate HLS with master playlist
ffmpeg -i input.mp4 \
-filter_complex "[0:v]split=3[v1][v2][v3]; [v1]scale=1280:720[720p]; [v2]scale=854:480[480p]; [v3]scale=640:360[360p]" \
-map "[720p]" -map 0:a -c:v:0 libx264 -b:v:0 2800k -c:a:0 aac -b:a:0 128k \
-var_stream_map "v:0,a:0" \
-map "[480p]" -map 0:a -c:v:1 libx264 -b:v:1 1400k -c:a:1 aac -b:a:1 128k \
-var_stream_map "v:1,a:1" \
-map "[360p]" -map 0:a -c:v:2 libx264 -b:v:2 800k -c:a:2 aac -b:a:2 96k \
-var_stream_map "v:2,a:2" \
-f hls \
-hls_time 6 \
-hls_playlist_type vod \
-hls_segment_filename 'hls/%v/segment%03d.ts' \
-master_pl_name master.m3u8 \
'hls/%v/index.m3u8'
# fMP4 segments (better for HEVC, LHLS)
ffmpeg -i input.mp4 \
-c:v libx265 -c:a aac \
-hls_time 6 \
-hls_segment_type fmp4 \
-hls_fmp4_init_filename init.mp4 \
-hls_playlist_type vod \
output.m3u8
Live Streaming with HLS
For live streaming, the media playlist is continuously updated:
# Live HLS stream from RTMP input
ffmpeg -i rtmp://ingest.server.com/live/stream_key \
-c:v libx264 -preset veryfast -tune zerolatency \
-c:a aac -b:a 128k \
-hls_time 2 \
-hls_list_size 10 \
-hls_flags delete_segments \
-hls_playlist_type event \
live/stream.m3u8
Live playlist characteristics:
- No
#EXT-X-ENDLIST— the player polls for updates #EXT-X-MEDIA-SEQUENCEincrements as old segments are removedhls_list_sizecontrols how many segments stay in the playlist (DVR window)- Typical live latency: 15-30 seconds (3-5 segment durations)
Low-Latency HLS (LHLS / LL-HLS)
Apple's Low-Latency HLS (LL-HLS) extension, added to the protocol in 2019, reduces live streaming latency to 2-5 seconds:
Key mechanisms:
- Partial segments: segments are published incrementally as they are produced (not waiting for the full segment)
- Preload hints: the player is told to prefetch the next partial segment before it is fully available
- Rendition reports: the playlist includes information about other rendition playlists to avoid extra round trips
LL-HLS requires HLS version 9 and fMP4 segments. Most major CDNs (Cloudflare, Fastly, AWS CloudFront) now support LL-HLS.
Playing HLS in the Browser
HLS is natively supported in Safari on macOS and iOS via the <video> element. Other browsers (Chrome, Firefox, Edge) require JavaScript libraries:
<!-- hls.js — the most popular HLS player for non-Safari browsers -->
<video id="video" controls></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
const video = document.getElementById('video');
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource('https://cdn.example.com/video/master.m3u8');
hls.attachMedia(video);
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Safari native HLS
video.src = 'https://cdn.example.com/video/master.m3u8';
}
</script>
HLS Encryption and DRM
HLS supports AES-128 encryption for segment-level content protection:
#EXT-X-KEY:METHOD=AES-128,URI="https://keyserver.example.com/key/abc123",IV=0x00000000000000000000000000000001
#EXTINF:6.006,
segment000.ts
For premium content protection, SAMPLE-AES with FairPlay (Apple), Widevine (Google), or PlayReady (Microsoft) provides hardware-backed DRM. Most commercial streaming services use DRM on top of HLS.
HLS vs DASH
| Feature | HLS | DASH |
|---|---|---|
| Standardization | RFC 8216 (Apple-led) | ISO/IEC 23009-1 (MPEG) |
| Browser native support | Safari only | None natively |
| Segment format | .ts or fMP4 | fMP4 or WebM |
| Manifest format | M3U8 (text) | MPD (XML) |
| Low latency | LL-HLS (2-5s) | DASH-IF CMCD (~2s) |
| Adoption | Dominant (especially Apple ecosystem) | Strong (especially Android) |
In practice, most major platforms support both — the CDN serves whichever format the client requests.
Related conversions
Common video conversions that pair well with this guide: