Probably the most widely used way to deliver live video. It works practically everywhere.
And that's hardly surprising. After all, it's built on HTTP, a protocol with nearly 40 years of history behind it.
Reliable. Universal. Not particularly fast.
Overview
HLS is more about watching live streams than publishing them. For publishing and ingest, real-time protocols such as RTMP, WebRTC, SRT, and RTSP are typically used. HLS, on the other hand, is primarily about delivering small chunks of video to the player. The player requests a chunk. The server delivers it. The player requests the next one. And then another. What could be simpler?
But simple doesn't necessarily mean efficient. Think about it. The player sends an HTTP request to the server to get a list of video segments available for download. Once it receives the response, it starts downloading those segments one by one.
Watching a live stream essentially turns into downloading thousands of small files over HTTP, while constantly sending more requests to refresh the list of available segments. That list, by the way, is called an M3U8 playlist.
m3u8
Player200 OK200 OKIngest
Media Server
HLS - four playback options
HLS needs no SDK at all. The player requests the M3U8 playlist by its URL and downloads the segments over plain HTTP, as the Overview shows; which players to use is covered in HLS players.
What you can choose is how the stream reaches the player. Low Latency HLS splits segments into short parts and brings latency down to 2–3 seconds; it is turned on by the server, and players that do not support it still play the same playlist the usual way. ABR adds a playlist of several qualities, and the player switches between them as its network changes.
The two combine freely, so there are four ways to play an HLS stream:
Latency 2–3 s
LL-HLSABR
Low latency, adaptive quality
An LL-HLS player, such as HLS.js with lowLatencyMode, requests the ABR playlist. Each quality comes in partial segments as soon as they are encoded, and the player switches quality as the network changes.
The same ABR playlist in a player without LL-HLS support, or from a server with LL-HLS turned off. The player downloads whole segments and switches quality at segment boundaries. Every quality is a set of plain files that any CDN caches.
The ordinary playlist in an LL-HLS player: partial segments as soon as they are encoded. The stream is played as it was published, with no transcoding into qualities.
https://media.example.com:8445/live/live.m3u8
Latency 10–30 s
Standard HLSNo ABR
Classic HLS
One playlist and whole segments, played by any HLS player on any device. The simplest and most compatible way to watch a stream, at the cost of the highest latency.
https://media.example.com:8445/live/live.m3u8
Low latency HTTP live streaming
Classic HLS is slow by design. A segment usually lasts 2 to 6 seconds, the server can publish it only once it is complete, and the player waits for about three segments before it starts playing. Add the time spent polling the playlist, and a viewer ends up 10 to 30 seconds behind the live moment.
Low Latency HLS (LL-HLS) is Apple's extension of the protocol that brings this down to 2–3 seconds. It is still HTTP, still M3U8 playlists, still the same segments. What changes is how quickly they reach the player.
The key idea is partial segments. The server cuts each segment into short parts of 200 ms to 1 s and adds them to the playlist with EXT-X-PART as soon as they are encoded. The player no longer waits for a whole segment: it starts downloading the first part while the rest of the segment is still being produced.
And LL-HLS stays backward compatible. A player that knows nothing about parts simply ignores the new tags and plays the full segments as before, with the usual latency.
The price is more of everything: many more HTTP requests and playlists updated several times a second, which every server and CDN on the path must keep up with. LL-HLS is much faster than classic HLS, but it still runs over TCP and still delivers files, so sub-second latency remains the territory of WebRTC.
m3u8
Player200 OK200 OKIngest
Media Server
HLS ABR
Not every viewer has the same network. One watches over fiber, another over a crowded mobile connection. Send everyone the same high-bitrate stream, and the weakest connections start to stall.
HLS ABR (Adaptive Bitrate) is built into the protocol itself. The Media Server transcodes the incoming stream into several qualities, for example 720p, 480p and 240p, and cuts each of them into its own segments with its own M3U8 playlist.
On top of them sits one more playlist, the multivariant (master) playlist. It does not list segments, only the qualities: each EXT-X-STREAM-INF entry gives the bitrate (BANDWIDTH), the resolution and the codecs of one quality and points to its playlist.
The decision is entirely up to the player. It downloads the master playlist, picks a starting quality and then keeps measuring how fast the segments arrive and how much video is left in its buffer. If a segment takes longer to download than it lasts, the buffer drains, and the player switches to a lower quality. When the network recovers, it climbs back up.
The switch happens at a segment boundary: the player simply requests the next segment from a different playlist. For the viewer not to notice the switch, the qualities are cut in sync, with keyframes at the same moments, so the segments of all qualities line up. The server does not track any viewer and does not even know who is watching which quality, and the publisher still sends a single stream.
That makes HLS ABR cheap to scale: every quality is just a set of files that a CDN caches like any others. The flip side is reaction time. The player notices a slow network only after a slow download, and changes quality only at the next segment, so with classic HLS a switch takes seconds rather than the fraction of a second WebRTC needs.
720p/m3u8
720p
Player200 OK200 OKIngest
360p720p
Media Server
HLS players
Playback is where HLS shines. The viewer needs no SDK and no special connection: an ordinary HLS player requests the M3U8 playlist by its URL and then downloads the segments over plain HTTP. On the Media Server the URL follows the stream name: a stream named live plays as /live/live.m3u8, and the server starts cutting the stream into segments as soon as the first viewer asks for it.
A new viewer does not touch the publisher, and the server does not even keep a connection for them: segments are ordinary files, so a CDN or any HTTP cache can serve thousands of viewers from a single copy. The price is the latency we have already talked about.
Publisher App
Media Server
Viewer App
HLS Player
Now let's see how to play an HLS stream with three popular players.
HLS.js and Video.js bring HLS to any modern browser, while Safari plays it natively. In each case the idea is the same: give the player the M3U8 playlist URL and start playback.
HLS.js
HLS.js brings HLS to browsers that cannot play it natively, through Media Source Extensions. It loads the playlist, downloads the segments and feeds them to an ordinary video element:
lowLatencyMode: true turns on Low Latency HLS; hls.levels lists the qualities of an ABR stream and hls.currentLevel switches between them, -1 being automatic.
No setup, no installation. Press Play and watch a live stream delivered from the Media Server over HLS: the player downloads the M3U8 playlist and then the segments, one after another.
LLcast will deploy a dedicated Media Server just for you. Publish a live stream over WebRTC, RTMP, SRT or RTSP, and the server will cut it into segments and an M3U8 playlist, ready for any HLS player. Try adaptive bitrate and experiment with segment settings.