What is HLS streaming?
HTTP Live Streaming is a text playlist, a pile of short media files and a set of rules for a player. Here is how those pieces fit together and why it became the default way to deliver video.
HLS, short for HTTP Live Streaming, is Apple's way to send video in short pieces called segments. A text playlist, the m3u8 file, lists the segments in order. Everything travels over plain HTTP, like a web page. A top playlist points to several quality levels, so the player can switch as the connection changes.
Open an HLS stream in a text editor and there is almost nothing there. You see a few lines that start with #EXT, some durations and some file names. That thinness is the point. Apple designed HTTP Live Streaming in 2009 so that any web server and any cache could serve video. The smart part lives in the player, not in special streaming servers. More than fifteen years later, most video on the web is sent this way. Every video on VideoBB is too.
This guide explains what an HLS stream is made of and what the key playlist tags mean. It shows how on-demand and live delivery differ. It also covers where HLS plays on its own and where it needs a JavaScript player. It assumes you know what a rendition ladder is. If not, read the adaptive bitrate guide alongside it. The video streaming hub shows where HLS sits in the whole chain, from transcoding to delivery.
This document describes a protocol for transferring unbounded streams of multimedia data. It specifies the data format of the files and the actions to be taken by the server (sender) and the clients (receivers) of the streams.
RFC 8216, HTTP Live Streaming, abstract
The three parts of an HLS stream
An HLS presentation has a multivariant playlist (RFC 8216 calls it a master playlist; the current draft revision renamed it), one media playlist per rendition, and the media segments themselves. The multivariant playlist lists the available renditions with their peak bitrate, resolution and codecs. Each media playlist lists that rendition's segments in order with their durations. The segments hold a few seconds of encoded video and audio each.
Segments were first MPEG-2 transport stream files with a .ts extension, the same format used in broadcast television. Since 2016 HLS has also supported fragmented MP4 (fMP4) segments. These are now the preferred choice for two reasons. The same segments can serve MPEG-DASH players, and fMP4 handles HEVC and AV1 cleanly. The video formats hub explains MP4 and the other containers if these names are new. Audio-only renditions can be packed AAC, MP3 or AC-3, and subtitles travel as WebVTT segments. Playlists are served with the MIME type application/vnd.apple.mpegurl.
The tags that matter
A complete list is in RFC 8216. These are the ones you will see in nearly every stream.
| Tag | Where | Meaning |
|---|---|---|
#EXTM3U | Both | Required first line; declares an extended M3U playlist |
#EXT-X-VERSION | Both | Protocol compatibility version the playlist requires |
#EXT-X-STREAM-INF | Multivariant | Describes a rendition: BANDWIDTH, RESOLUTION, CODECS, FRAME-RATE; next line is its media playlist URL |
#EXT-X-MEDIA | Multivariant | Alternate renditions such as audio languages or subtitle tracks |
#EXT-X-TARGETDURATION | Media | Maximum segment duration in seconds; required |
#EXTINF | Media | Duration of the segment named on the next line |
#EXT-X-MEDIA-SEQUENCE | Media | Sequence number of the first segment; lets a live playlist drop old segments |
#EXT-X-MAP | Media | The initialisation segment for fMP4 renditions |
#EXT-X-KEY | Media | Encryption method and key URL (AES-128 or SAMPLE-AES) |
#EXT-X-DISCONTINUITY | Media | Encoding parameters change at this point, for example an inserted advert |
#EXT-X-PLAYLIST-TYPE | Media | VOD (never changes) or EVENT (only appended to) |
#EXT-X-ENDLIST | Media | No more segments will be added; absent in a live playlist |
What a player does with all this
On load, the player fetches the multivariant playlist and chooses a first rendition. Apple's guidance is that a client plays the first variant listed before it has measured any bandwidth. So the order of that list is a deliberate choice by the author. The player then fetches the chosen media playlist, downloads the first segments, and starts decoding once it has enough buffered to be confident of continuous playback.
From then on the loop is simple: measure how quickly the last segment arrived, compare with the BANDWIDTH values in the multivariant playlist, and decide whether the next segment should come from a higher or lower rendition. Because every rendition is segmented at the same timestamps, switching means fetching the next segment from a different media playlist and nothing more. No renegotiation with the server is involved, because the server is just serving files.
On-demand versus live
For a video on demand, the media playlist is complete and ends with #EXT-X-ENDLIST. It never changes, so it can be cached for as long as the video exists. Seeking is a matter of adding up #EXTINF durations to find the right segment. For live, the playlist is a sliding window. The encoder adds a new segment every few seconds and drops the oldest. The player re-fetches the playlist at roughly the target duration to find new segments. RFC 8216 tells clients not to start closer than three target durations from the end of a live playlist. That is why classic HLS live latency is measured in tens of seconds. The Low-Latency HLS extensions in the current draft add partial segments to bring that down.
Segment length and keyframes
Apple's authoring specification recommends a target duration of six seconds and keyframes at least every two seconds. Shorter segments let the player switch renditions and recover from stalls faster. The cost is more playlist entries and more HTTP requests per minute. Longer segments are friendlier to caches. Whatever the length, each segment must begin with a keyframe. Otherwise a player switching into it would have nothing to decode from. This is why the transcoding guide spends so long on keyframe intervals.
Making an HLS package with ffmpeg
For a single rendition, FFmpeg's hls muxer does the segmenting and playlist writing in one command.
- Encode and segment:
ffmpeg -i source.mp4 -c:v libx264 -crf 21 -g 48 -keyint_min 48 -sc_threshold 0 -c:a aac -b:a 128k -f hls -hls_time 6 -hls_playlist_type vod -hls_segment_type fmp4 index.m3u8. With 24 fps input,-g 48places a keyframe every two seconds. - Check the output:
index.m3u8is the media playlist,init.mp4the initialisation segment, andindex0.m4sonward the media segments. - Serve the folder over HTTPS with the correct MIME types and open the playlist in Safari, or in another browser through hls.js, to confirm playback.
- For a full ladder you would repeat with several renditions and write a multivariant playlist that lists them; the transcoding guide has the multi-rendition command.
Where HLS plays
- Safari on macOS, iOS and iPadOS plays HLS natively through the ordinary video element. On iPhone this was for years the only way to stream at all, because Media Source Extensions were not available there.
- Chrome, Firefox and Edge on desktop do not play HLS natively. They do support Media Source Extensions, so a JavaScript library such as hls.js reads the playlist and feeds segments to the browser's decoder.
- Apple TV, Android TV, smart TV platforms and games consoles all ship HLS support. That makes it the lowest common denominator for reaching every screen.
- The VideoBB embeddable player handles both paths automatically; the embed guide shows how to place it, and the embedding guide covers sizing and options.
Frequently asked questions
Is HLS only for Apple devices?
No. Apple created it and Safari plays it natively. But hls.js and similar libraries make it work in every major browser through Media Source Extensions. Smart TVs, set-top boxes and Android all support it too. That reach is why platforms standardise on it. One HLS package reaches every screen, whereas DASH cannot reach older iPhones without HLS alongside it.
What is the difference between .ts and fMP4 segments?
MPEG-2 transport stream segments are the original HLS format, taken from broadcast. They carry a fixed overhead in every packet. Fragmented MP4 segments, added in 2016, use the ISO Base Media File Format. They have lower overhead, support HEVC and AV1 properly, and can be shared with DASH players. New setups usually choose fMP4. The .ts format remains for older players.
Why is live HLS delayed by so many seconds?
A classic live player starts several segments behind the newest one to protect against stalls. RFC 8216 recommends staying at least three target durations from the live edge. With six-second segments that alone means around twenty seconds, before encoding and delivery add their share. Low-Latency HLS cuts this with partial segments and blocking playlist requests. The cost is more complex servers.
Can I download an HLS stream as a single file?
The segments can be joined, because each one is a self-contained piece of the same stream. FFmpeg will read an m3u8 URL as input and remux it into an MP4 with stream copy. Whether you may do so depends on the rights to the content. On VideoBB the per-video privacy settings control who can reach a stream in the first place.
Sources
- RFC 8216: HTTP Live Streaming — The HLS specification, including the quoted abstract
- Apple: HTTP Live Streaming — Apple's HLS documentation and authoring specification
- FFmpeg formats documentation: hls muxer — Options used in the packaging command
- MDN: Media Source API — How non-Safari browsers play HLS through JavaScript
Related guides

Adaptive bitrate streaming, explained
A player that changes quality mid-stream is making a prediction every few seconds. How the rendition ladder is built, how the player chooses a rung, and what makes the choice hard.

HLS vs DASH
Two protocols that solve the same problem in almost the same way. Where they still diverge: device support, DRM, low latency, manifests and the CMAF packaging that lets one set of segments serve both.

Video transcoding, explained
Transcoding turns one source file into a set of aligned versions ready for adaptive streaming. Here is what happens at each stage, and which settings decide the result.

How to embed a video on a website
Copy one iframe, understand the six attributes it carries, and add the query parameters that control autoplay, mute, start time and looping.