Why This Matters
Almost every conversation about a streaming product eventually reaches an m3u8 file, and the people who can read that file fix problems faster than the people who can't. A product manager who can read a multivariant playlist can answer questions about device support and bitrate ladder without paging engineering. A new engineer who can read a media playlist can debug a stall by looking at three tags instead of attaching a debugger. A non-technical founder who knows what a segment is can read a CDN bill and ask the right questions about cache-hit ratio. HLS is also the protocol you ship even when you don't ship HLS — the iOS App Store rejects video apps that use anything else for cellular delivery, the LL-HLS variant is the standard low-latency stack across Apple devices, and every CDN's "live streaming" SKU is HLS first. Understanding HLS is the price of entry for talking sensibly about modern video delivery.
What HLS is, in one paragraph
HLS is a protocol for delivering video as a list of small files over the same HTTP that serves the rest of the web. A producer encodes the video, chops it into pieces of two to six seconds each (called segments), writes a text file that lists those segments in order (called a media playlist, with the extension .m3u8), and uploads everything to a normal web server. A player asks for the playlist, reads which segments exist and where to find them, downloads them in order, and stitches them back into a continuous video. That is the entire idea. Every other tag, attribute, and refinement in the specification is there to handle adaptive bitrate, multiple audio tracks, subtitles, encryption, live updates, ad insertion, and trick play — but the core mechanism is "fetch a text file that points to small media files."
The protocol was introduced by Apple in 2009, was first published as an Internet-Draft the same year, and became IETF Informational RFC 8216 in August 2017. RFC 8216 is the canonical reference, but the protocol has continued to evolve through a series of Internet-Drafts that the IETF tracker labels draft-pantos-hls-rfc8216bis-NN. The active revision as of this writing is draft-22, published on 1 May 2026, which obsoletes RFC 8216 if approved and describes version 13 of the protocol. In parallel, Apple maintains a living document — the HLS Authoring Specification for Apple Devices, revision 2025-09 — that layers normative requirements on top of the RFC for content that intends to play on iPhone, iPad, Apple TV, and Mac. In practice you read both: the IETF document for what HLS is, the Apple document for what HLS must be to ship on Apple's devices.
The two-tier playlist model
HLS uses two kinds of playlist, and almost every confusion about HLS in production comes down to forgetting which tier the file in front of you belongs to.
The multivariant playlist (sometimes still called master playlist — Apple renamed it in revision 2023-04 because the same content was being delivered in many forms, not from a single master) lists every variant of a piece of content. A variant is one combination of video bitrate, video resolution, audio track, codecs, and optionally subtitles. A typical movie has one multivariant playlist that points at four to seven video variants, three to five audio renditions, and one or two subtitle tracks. The multivariant playlist contains no media itself. It is a menu.
The media playlist lists the actual segments for one variant. If the multivariant playlist points at a 1080p H.264 variant, there is a media playlist for that variant, and that media playlist contains a list of the 1080p segment files in order along with each one's duration. The player downloads the multivariant playlist first, picks a variant based on bandwidth and screen size, then downloads that variant's media playlist, then starts pulling segments from it. When network conditions change, the player can switch to another variant by downloading a different media playlist and continuing from there.
The two playlists do not have to share a hostname or a path. Many production stacks serve the multivariant playlist from one origin and the media playlists from a different one — a packager origin for the menu, a CDN edge for the segments. That separation is what lets HLS scale to internet-scale audiences: the multivariant playlist is small and changes rarely, the segments are huge and change every few seconds, and you can cache the two with completely different policies.
What an m3u8 file actually looks like
An m3u8 file is plain UTF-8 text. Every line is either a comment, a tag (a line that begins with #EXT), or a URI (a line that does not begin with #). The first line of every HLS playlist is the magic header #EXTM3U. That marker is the only thing telling the parser that this file is an HLS playlist and not a different variant of the older M3U format used by audio players in the 2000s.
Here is a minimal multivariant playlist that points at three video qualities:
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:BANDWIDTH=1280000,AVERAGE-BANDWIDTH=1100000,RESOLUTION=640x360,CODECS="avc1.64001f,mp4a.40.2",FRAME-RATE=25
360p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=3200000,AVERAGE-BANDWIDTH=2900000,RESOLUTION=1280x720,CODECS="avc1.640020,mp4a.40.2",FRAME-RATE=25
720p/playlist.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=6400000,AVERAGE-BANDWIDTH=5800000,RESOLUTION=1920x1080,CODECS="avc1.640028,mp4a.40.2",FRAME-RATE=25
1080p/playlist.m3u8
Read it top to bottom. The #EXTM3U line declares the file an HLS playlist. The #EXT-X-VERSION:6 line declares the minimum HLS protocol version the player must support to parse this file. The #EXT-X-INDEPENDENT-SEGMENTS line is a player hint that every segment can be decoded without needing the previous segment — a property that matters for ABR switching and trick play. Then three #EXT-X-STREAM-INF lines describe three variant streams, each immediately followed by a URI pointing at the variant's media playlist. The BANDWIDTH value is the peak bitrate the variant can reach. AVERAGE-BANDWIDTH is the long-run average. RESOLUTION and FRAME-RATE give the player the geometry. CODECS is the formal codec string — avc1.64001f means H.264 High profile, level 3.1; mp4a.40.2 means AAC-LC. A player uses those strings to know whether the device can decode the variant at all before trying.
A media playlist looks different. Here is the corresponding 720p/playlist.m3u8:
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-TARGETDURATION:6
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MAP:URI="init.mp4"
#EXTINF:6.000,
segment_00001.m4s
#EXTINF:6.000,
segment_00002.m4s
#EXTINF:6.000,
segment_00003.m4s
#EXTINF:4.480,
segment_00004.m4s
#EXT-X-ENDLIST
#EXT-X-TARGETDURATION:6 says no segment in the list exceeds six seconds, rounded to the nearest integer. #EXT-X-MEDIA-SEQUENCE:0 says the first segment in this playlist has sequence number zero — for VOD that does not change, but for live it advances every refresh. #EXT-X-PLAYLIST-TYPE:VOD tells the player this is a finite, non-changing playlist. #EXT-X-MAP:URI="init.mp4" points to the initialisation segment that contains the codec configuration (this tag only appears when the media is fragmented MP4 / CMAF, not when it's MPEG-TS). Then a series of #EXTINF lines each declare the duration of the next segment, followed by the segment's URI on its own line. The last line, #EXT-X-ENDLIST, tells the player the playlist will not grow.
That is HLS in twenty lines. Everything that follows is detail.
Segment formats: MPEG-TS, fMP4, CMAF
Segments carry the actual video and audio bytes. HLS supports two container formats, with a third being a profile of the second.
MPEG-TS (.ts) is the legacy format. It is the same MPEG-2 Transport Stream that has been used in digital television since the 1990s, with a 188-byte packet structure designed for broadcast. When Apple shipped HLS in 2009, MPEG-TS was the only choice. It has a 5–10% overhead from packet headers and timestamps and cannot easily be shared with DASH. New HLS deployments rarely choose it. Old deployments still ship it because every device that ever played HLS plays MPEG-TS, including very old set-top boxes and the first generation of Apple TV.
Fragmented MP4 (.m4s or .mp4, often just called fMP4) became official in HLS in iOS 10 / 2016. fMP4 is a profile of the ISO Base Media File Format (ISO BMFF, ISO/IEC 14496-12), structured as a small initialisation segment (the moov atom) followed by a series of media segments (each a pair of moof + mdat atoms). Overhead is 1–3%. The init segment is downloaded once and pointed to with the #EXT-X-MAP tag; every subsequent segment can be decoded as long as the init segment is in the player's cache.
Common Media Application Format (CMAF) is a 2017 standard, ISO/IEC 23000-19, that defines a specific profile of fMP4 designed to be playable as both HLS and DASH. A CMAF segment is an fMP4 segment with constraints that match DASH's expectations — single track per file, specific brand identifiers, well-defined chunk boundaries. The economic argument for CMAF is that one set of files on disk serves both HLS and DASH players, halving storage and CDN egress for content distributed in both formats. In 2026, CMAF is the dominant choice for new HLS deployments outside the Apple-only ecosystem; every modern packager (Shaka Packager, AWS MediaPackage, Unified Streaming, Bento4) produces CMAF by default. Apple supports CMAF in HLS for both H.264 and H.265.
The numeric example: a one-hour 1080p H.264 stream at 5 Mbps that is stored as both HLS-only MPEG-TS and CMAF-shared fMP4. The MPEG-TS path stores 1 × 5 Mbps × 3,600 s ÷ 8 ≈ 2.25 GB of .ts files plus a separate 2.25 GB of DASH .m4s files if you also need DASH — 4.5 GB total. The CMAF path stores one set of .m4s files used by both HLS and DASH, around 2.18 GB total. Across a 10,000-hour catalogue at $0.023 per GB per month of S3 storage, the difference is roughly $530 per month — a real number even before CDN egress is factored in.
The 30 tags that matter, grouped by job
The HLS specification defines several dozen tags. In practice, fifteen of them carry 90% of the meaning across both playlists. Group them by the job they do, and the protocol becomes much easier to memorise.
Playlist identity and version. #EXTM3U marks the file as HLS. #EXT-X-VERSION:N declares the minimum protocol version a parser needs; raise the number when you use a tag that requires a newer version. #EXT-X-INDEPENDENT-SEGMENTS is a hint that every segment can decode without referring to the previous one (it matters for ABR switching and seek). #EXT-X-DEFINE declares variable substitutions inside the playlist (added in version 7).
Segment identity and timing. #EXTINF:duration,title precedes every segment URI and declares the segment's exact duration in seconds (decimal, not integer). #EXT-X-TARGETDURATION:N declares the upper bound; for VOD it is a property, for live the player polls the playlist no faster than every TARGETDURATION seconds when the playlist is static. #EXT-X-MEDIA-SEQUENCE:N is the sequence number of the first segment listed; for live this advances every reload. #EXT-X-DISCONTINUITY-SEQUENCE:N tracks how many discontinuities have appeared before the first segment in the list. #EXT-X-PROGRAM-DATE-TIME:YYYY-MM-DDTHH:MM:SSZ ties a segment to wall-clock time — the player can synchronise across renditions and to an external clock.
Segment relationships. #EXT-X-MAP:URI="init.mp4" declares the initialisation segment for fMP4/CMAF; the player downloads it once and re-uses it. #EXT-X-BYTERANGE:length[@offset] lets multiple segments live inside a single file as byte ranges of that file — useful when you want to ship a single .mp4 and let the player fetch ranges. #EXT-X-DISCONTINUITY between two segments tells the player that something fundamental changed: encoder restart, ad break, content change, splice. #EXT-X-GAP marks a missing segment that the player should skip.
Encryption and DRM. #EXT-X-KEY:METHOD=AES-128,URI="key",IV=0x... declares that subsequent segments are encrypted with the named key and method. The modern variant #EXT-X-KEY:METHOD=SAMPLE-AES-CTR carries DRM-style encryption used with FairPlay, Widevine, and PlayReady through the Common Encryption (CENC) framework defined in ISO/IEC 23001-7. #EXT-X-SESSION-KEY is the multivariant-playlist counterpart: it pre-declares keys so the player can fetch them up front before picking a variant.
Multivariant playlist tags. #EXT-X-STREAM-INF precedes every variant and carries the bitrate, resolution, codecs, and frame rate. #EXT-X-MEDIA declares an alternate rendition (e.g. an alternate-language audio track or a subtitle track) and groups it under a GROUP-ID that variants reference. #EXT-X-I-FRAME-STREAM-INF declares a special "I-frames-only" variant used for trick play (fast forward, rewind). #EXT-X-SESSION-DATA lets the publisher attach arbitrary key/value pairs to the multivariant playlist (e.g., the show's title in multiple languages).
Live-specific tags. #EXT-X-PLAYLIST-TYPE:EVENT tells the player that segments will be appended but never removed; the playlist always grows. #EXT-X-PLAYLIST-TYPE:VOD tells the player the playlist is finite and will not change. The absence of both means a sliding window (typical live): the playlist holds the last N segments and shifts forward every TARGETDURATION. #EXT-X-ENDLIST marks the end of any playlist that is finished.
Low-latency tags (added in 2019, still part of HLS in 2026). #EXT-X-PART declares a partial segment — a 200–500 ms slice of an in-progress segment that the player can fetch before the segment is complete. #EXT-X-PRELOAD-HINT tells the player to start fetching the next part or map before its #EXT-X-PART line appears. #EXT-X-RENDITION-REPORT lets a media playlist for one variant report the latest sequence number on a sibling variant, so a switching player doesn't need to refetch every variant's playlist. #EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES allows blocking-reload behaviour: the player asks for playlist.m3u8?_HLS_msn=N&_HLS_part=K and the server holds the request open until that part exists. These are the six mechanisms that turn 30-second HLS into 2–5 second LL-HLS — covered in detail in LL-HLS in depth.
Metadata and ad-insertion. #EXT-X-DATERANGE:ID=...,START-DATE=...,DURATION=...,SCTE35-OUT=... carries arbitrary in-band metadata, most often SCTE-35 ad markers translated from broadcast feeds. #EXT-X-SKIP is a delta-playlist mechanism: the server may send a smaller playlist that skips a contiguous range of older segments, identified by sequence numbers, and the client knows it already has those.
| Tier | Tags | Job |
|---|---|---|
| Identity | #EXTM3U, #EXT-X-VERSION, #EXT-X-INDEPENDENT-SEGMENTS, #EXT-X-DEFINE | Mark the file, declare protocol version, give parsing hints |
| Segment | #EXTINF, #EXT-X-TARGETDURATION, #EXT-X-MEDIA-SEQUENCE, #EXT-X-PROGRAM-DATE-TIME, #EXT-X-MAP, #EXT-X-BYTERANGE, #EXT-X-DISCONTINUITY, #EXT-X-GAP | Declare and locate the actual media |
| Encryption | #EXT-X-KEY, #EXT-X-SESSION-KEY | Wire DRM and AES into the segment fetch |
| Multivariant | #EXT-X-STREAM-INF, #EXT-X-MEDIA, #EXT-X-I-FRAME-STREAM-INF, #EXT-X-SESSION-DATA | Describe variants, alternate renditions, trick-play |
| Live | #EXT-X-PLAYLIST-TYPE, #EXT-X-ENDLIST | Tell the player whether the playlist grows, slides, or ends |
| Low-latency | #EXT-X-PART, #EXT-X-PRELOAD-HINT, #EXT-X-RENDITION-REPORT, #EXT-X-SERVER-CONTROL, #EXT-X-PART-INF | Cut latency from 30 s to 2–5 s |
| Metadata | #EXT-X-DATERANGE, #EXT-X-SKIP | Carry ad markers, deltas, and arbitrary metadata |
Multi-variant playlists and the bitrate ladder
The point of the multivariant playlist is adaptive bitrate. The player picks a variant when it starts, measures throughput while the first few segments arrive, and switches up or down between variants as conditions change. The protocol does not dictate the algorithm — that is the player's job, and the algorithm choice is itself a deep topic covered in the ABR articles of Block 5. What HLS dictates is the shape of the menu the player chooses from.
A well-designed bitrate ladder for HLS in 2026 looks roughly like the table below. The exact numbers come from a synthesis of the Netflix per-title ladder, Apple's recommendations in the HLS Authoring Specification, and the bandwidth distribution Bitmovin and Conviva measure in their annual reports.
| Variant | Resolution | Video bitrate | Codec | When the player picks it |
|---|---|---|---|---|
| 1 | 416 × 234 | 200 kbps | H.264 Baseline | Sub-3G cellular, congested public Wi-Fi |
| 2 | 640 × 360 | 400 kbps | H.264 Baseline | Slow 4G, weak Wi-Fi |
| 3 | 768 × 432 | 800 kbps | H.264 Main | Average 4G |
| 4 | 960 × 540 | 1.6 Mbps | H.264 Main | Strong 4G, home broadband baseline |
| 5 | 1280 × 720 | 3.0 Mbps | H.264 High | Standard home broadband |
| 6 | 1280 × 720 | 4.5 Mbps | H.264 High | Strong home broadband (premium 720p) |
| 7 | 1920 × 1080 | 6.0 Mbps | H.264 High | Fast broadband, large screen |
| 8 | 1920 × 1080 | 8.0 Mbps | H.265 Main | Same audience, ~30% smaller files |
| 9 | 3840 × 2160 | 16 Mbps | H.265 Main10 | 4K capable device, gigabit broadband |
Apple's HLS Authoring Specification adds normative requirements on top of the structural rules:
- Adjacent variants in the ladder should be no more than 200% and no less than 150% of each other in BANDWIDTH — the player needs enough headroom between rungs to make confident switching decisions.
- Every variant must declare
RESOLUTION,FRAME-RATE, and a completeCODECSstring. Variants that omitCODECScannot be filtered by capability and are ignored on devices that don't decode the missing codec. - The lowest variant must be playable on the lowest-capability device in the target audience — for iOS, that is roughly 192 kbps audio-and-video together, H.264 Baseline at 480 × 270.
- If you ship HEVC variants, you must also ship a parallel H.264 ladder so older devices have something to play.
- For HDR content, you ship a parallel SDR ladder. The HLS spec defines
VIDEO-RANGE=SDR|PQ|HLGon#EXT-X-STREAM-INFso the player can pick by signal type.
The #EXT-X-MEDIA tag handles alternate renditions of the same content. A typical multi-language film has one #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",NAME="English",LANGUAGE="en",DEFAULT=YES,URI="audio_en.m3u8" per language, all sharing the GROUP-ID="aac", and each video variant in #EXT-X-STREAM-INF references that group via the AUDIO="aac" attribute. The player downloads the chosen video variant's media playlist and the chosen audio rendition's media playlist in parallel and synchronises them by EXT-X-PROGRAM-DATE-TIME.
#EXT-X-MEDIA groups; each video variant points at its groups by GROUP-ID.
Live HLS: the sliding window
For a live event the playlist is not finite. The encoder produces a new segment every TARGETDURATION seconds, appends it to the media playlist, and (typically) removes the oldest segment to keep the playlist length bounded. The result is a sliding window of N segments that advances forward as time progresses.
A typical live media playlist has six to twelve segments at any moment — three to four times the target duration gives the player enough buffer to absorb variance without storing more than a minute of recent content. The player polls the playlist no more often than once per TARGETDURATION (or once per EXT-X-PART-INF for LL-HLS), reads the new EXT-X-MEDIA-SEQUENCE value to see what changed, downloads any new segments, and discards segments that have rolled off the front of the playlist.
The mechanics of live HLS without LL-HLS produce a 15–45 second glass-to-glass latency. Consider a 6-second target duration:
- The encoder produces 6 seconds of segment before the segment file exists. Glass-to-segment-complete: 6 s.
- The encoder uploads the segment to origin. Origin-to-CDN: typically 200–500 ms.
- The player's playlist poll happens at most every 6 s in the worst case and on average every 3 s. Average wait before the player sees the new segment in a refresh: 3 s.
- The player downloads the segment from CDN. Download time at 5 Mbps over typical broadband: ~500 ms.
- The player buffers two segments before playing them to absorb network variance. Two segments × 6 s = 12 s buffer (typical 1.5–3× the target duration).
Total: 6 + 0.5 + 3 + 0.5 + 12 ≈ 22 seconds glass-to-glass for a standard 6-second-segment HLS live event. Drop the target duration to 2 seconds and the same math gives about 8 seconds. Add Apple's LL-HLS extensions and the same math gives 2–5 seconds. The protocol's latency floor is set by the segment duration, the buffer multiplier, and the playlist refresh cadence — three knobs that all push in the same direction.
A common pitfall: the codec string
The single most common reason a properly-encoded HLS variant fails to play on a real device is a wrong CODECS string. The codec string is a formal RFC 6381 / ISO/IEC 14496-15 identifier: a four-character code plus a profile and level. For H.264 it's avc1.PPCCLL where PP is the profile, CC is the constraint flags, and LL is the level. For HEVC it's hvc1. or hev1. followed by profile/tier/level/constraints. For AAC-LC it's mp4a.40.2. For Opus it's opus. For AC-3 it's ac-3.
The pitfall pattern: a packager writes CODECS="avc1.640028" on the multivariant playlist (H.264 High profile, level 4.0), but the encoder actually produced level 4.1 video. iOS plays it because Safari is permissive; Android decoders reject the variant during the capability check and never download it. The user sees the lower-bitrate fallback variants on Android only. The fix is to either reconcile the codec string with the actual encode (the right answer) or to use hvc1.1.6.L120.90 and let the device pick.
The second common pitfall: omitting CODECS entirely. Apple's HLS Authoring Specification states that CODECS is required on every variant. Some 2018-era packagers still ship playlists without it. The player then doesn't know what it's about to decode, may pick the wrong variant, may fail without a clear error, and may simply skip variants on devices that strictly enforce the rule.
The third common pitfall: using avc1. and mp4a. for an HEVC + AC-3 stream. The codec string and the actual segments must agree. Mismatch is a guarantee of "plays on my Mac, not on the user's Roku."
Why Apple still owns HLS
HLS is an IETF Informational document, but Apple still defines the protocol in practice. Three reasons.
First, the App Store and ATS. Apple's App Store guidelines require HLS for video over cellular in any app that streams more than ten minutes of continuous video. There is no equivalent allowance for DASH or WebRTC for that case. If your app ships on iOS, your live and long-form VOD ships as HLS or it does not ship.
Second, the HLS Authoring Specification is normative for Apple devices. The IETF document is informational and permits many shapes of playlist that Apple's devices will reject. To get content to play on AirPlay, native AVPlayer, Apple TV, and Safari, you author to Apple's revision-tracked spec, not to the IETF document. Apple revises the spec one to three times per year — the September 2023 revision removed HTTP/2 push from LL-HLS; the April 2023 revision renamed master playlist to multivariant playlist; the 2024 and 2025 revisions added spatial-video authoring guidance.
Third, the reference implementation is in Safari and AVFoundation, and there is no public conformance suite that beats it. Apple's mediastreamvalidator tool is the de-facto compliance checker the industry runs before shipping. If your playlist passes mediastreamvalidator and plays in Safari, it plays. If it doesn't, no amount of spec-correctness will help on Apple devices.
The practical consequence: every vendor in the streaming stack — Bitmovin, AWS Elemental, Mux, Wowza, Cloudflare Stream, JW Player, THEO, hls.js maintainers — implements HLS against Apple's spec first and the IETF document second. The IETF document is where you learn the shape of the protocol; the Apple document is where you learn the rules to ship.
Why every other vendor implements HLS anyway
Outside Apple's ecosystem, HLS is still the dominant protocol the wider industry implements — even where DASH is technically a better fit. Bitmovin's Video Developer Report 2025/26 keeps HLS at the top of the "currently in production" list across 167 video developers in 34 countries, while showing future-plan interest declining. The reasons are the same reasons HLS won in the first place.
It is HTTP. Every cache, every CDN, every corporate proxy, every consumer router can serve and accept HLS without configuration. There is no UDP hole-punching, no port range to open, no per-viewer connection state on the origin.
It is text. The multivariant playlist is human-readable; the media playlist is human-readable. Debugging a stall in production starts with curl and ends with a re-encode plus a one-line fix.
It is everywhere. Every modern browser, every smart TV (Tizen, webOS, Roku, Vidaa, Android TV, Fire TV), every set-top box, every gaming console, every iOS and Android device speaks HLS natively or through a small JavaScript library — hls.js for browsers without native support, AVPlayer or ExoPlayer on mobile, Shaka Player as a cross-platform option.
It carries every other capability the industry needs. Multi-language audio via EXT-X-MEDIA. Subtitles via WebVTT and IMSC1. DRM via FairPlay, Widevine, PlayReady through CENC. Ad insertion via EXT-X-DATERANGE and SCTE-35. Trick play via I-frame-only variants. Live, VOD, and event-style playback in one format.
The result is that HLS is the floor under every modern OTT stack. Even when a product ships DASH as the primary delivery protocol — for example, Netflix outside the Apple ecosystem — it ships HLS for iOS, AirPlay, and Apple TV as a parallel rendition pulled from the same CMAF segments via a separate multivariant playlist. That last sentence is the whole CMAF argument: one set of files, two playlists, every device covered.
A live walked example, line by line
Below is a real-shape live HLS media playlist as it would look two minutes into a stream. Each line is annotated.
#EXTM3U ; HLS playlist marker
#EXT-X-VERSION:9 ; uses LL-HLS features, needs v9+
#EXT-X-TARGETDURATION:4 ; each segment ≈4 s
#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=1.0,HOLD-BACK=12.0
; player may use blocking reload; latency anchors
#EXT-X-PART-INF:PART-TARGET=0.5 ; partial segments ≈0.5 s each
#EXT-X-MEDIA-SEQUENCE:300 ; first full segment listed is #300
#EXT-X-DISCONTINUITY-SEQUENCE:1 ; one discontinuity has rolled past
#EXT-X-MAP:URI="init.mp4" ; init segment for fMP4/CMAF
#EXT-X-PROGRAM-DATE-TIME:2026-05-21T14:00:00.000Z; wall-clock anchor for the sliding window
#EXTINF:4.000,
segment_00300.m4s
#EXTINF:4.000,
segment_00301.m4s
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_0.m4s",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_1.m4s"
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_2.m4s"
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_3.m4s"
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_4.m4s"
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_5.m4s"
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_6.m4s"
#EXT-X-PART:DURATION=0.500,URI="segment_00302_part_7.m4s"
#EXTINF:4.000,
segment_00302.m4s
#EXT-X-PART:DURATION=0.500,URI="segment_00303_part_0.m4s",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.500,URI="segment_00303_part_1.m4s"
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="segment_00303_part_2.m4s"
#EXT-X-RENDITION-REPORT:URI="../720p/playlist.m3u8",LAST-MSN=303,LAST-PART=1
#EXT-X-RENDITION-REPORT:URI="../1080p/playlist.m3u8",LAST-MSN=303,LAST-PART=1
Read in order. The header announces a v9+ LL-HLS playlist with a 4-second target duration and 0.5-second partial segments. The sliding window starts at segment 300. Segments 300 and 301 are complete and listed as whole files; segment 302 is in the past for the playlist refresh and is shown both as eight EXT-X-PART slices (so an earlier player saw it as it was being produced) and as a complete #EXTINF:4.000 file once it finished. Segment 303 is in progress: two parts are complete and listed, and the third is announced as a preload hint. Two EXT-X-RENDITION-REPORT lines tell the player exactly how far along the sibling 720p and 1080p playlists are, so a switch can happen without re-polling them.
A player joining this stream now will pick a variant from the multivariant playlist, fetch this media playlist, jump to EXT-X-PART for segment 303 to start the playback head as close to live as possible, and use the preload hint to start the next part's fetch in parallel. Glass-to-glass latency lands around 2 seconds.
Where Fora Soft fits in
Fora Soft has shipped HLS-backed products on every Apple and non-Apple device that matters since 2009 — telemedicine streams that must play on hospital iPads, OTT live events on Apple TV and Roku and Tizen and webOS in parallel, AR/VR companion streams behind a CMAF packager, and e-learning catalogues with multi-language audio rendered through EXT-X-MEDIA groups. Our delivery teams maintain reference HLS ladders for live and VOD and a CMAF-first packaging pipeline that produces HLS and DASH from one origin. When a client ships a video product to the iOS App Store and the same product to a smart-TV ecosystem, the answer is almost always one CMAF packager, one multivariant playlist per market, one bug to fix when it breaks.
What to read next
- LL-HLS in depth: parts, preload hints, blocking reload, rendition reports — the six mechanisms that turn standard HLS into 2–5 second latency.
- CMAF: the packaging format that unified HLS and DASH — why one set of files now serves both protocols.
- The delivery protocol family tree — where HLS sits among the eight 2026 delivery protocols.
Call to action
- Talk to a streaming engineer — bring a sample m3u8 file, your target devices, and your latency goal. We'll review the playlist and the ladder in a 30-minute scoping call.
- See our case studies — OTT, telemedicine, e-learning, AR/VR, video conferencing, surveillance. HLS underlies the delivery layer in most of them.
- Download the HLS multivariant playlist cheat sheet (PDF) — one page, the fifteen tags that matter, a worked multivariant playlist, and the codec-string format. Printable for a wall.
References
- **IETF RFC 8216 — HTTP Live Streaming (Pantos & May, August 2017). The canonical HLS specification. https://www.rfc-editor.org/rfc/rfc8216 — primary source for everything in this article that did not require draft-22 detail.
- draft-pantos-hls-rfc8216bis-22 — HTTP Live Streaming 2nd Edition (Pantos, 1 May 2026). The active Internet-Draft that obsoletes RFC 8216 if approved; describes version 13 of the protocol. Internet-Drafts are subject to change before RFC publication. https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis-22
- Apple HLS Authoring Specification for Apple Devices, revision 2025-09. The living document that layers normative requirements on top of the RFC for content intending to play on Apple devices. https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices — cited for the multivariant rename (revision 2023-04), the HTTP/2 push removal from LL-HLS (revision 2023-09), and the BANDWIDTH spacing / codec-string requirements quoted in §"Multi-variant playlists and the bitrate ladder."
- Apple WWDC 2025 session, "What's new in HTTP Live Streaming" (June 2025). https://developer.apple.com/streaming/Whats-new-HLS.pdf — first-party engineering source from the HLS team for the spatial-video authoring extensions and the 2025 CMAF guidance.
- ISO/IEC 23000-19:2024 — Common Media Application Format (CMAF) for segmented media. The packaging-format standard that defines the CMAF profile of fMP4 used by HLS and DASH. https://www.iso.org/standard/85673.html — paywalled; cited for the CMAF segment structure summary in §"Segment formats."
- ISO/IEC 14496-12 — Information technology — Coding of audio-visual objects — Part 12: ISO Base Media File Format. The fMP4 base specification. https://www.iso.org/standard/83102.html
- IETF RFC 6381 — The 'Codecs' and 'Profiles' Parameters for "Bucket" Media Types (Gellens, Singer, Frojdh, August 2011). The codec-string format used in
CODECSattributes. https://www.rfc-editor.org/rfc/rfc6381 — cited in §"A common pitfall: the codec string." - ISO/IEC 23001-7 — Information technology — MPEG systems technologies — Part 7: Common encryption in ISO base media file format files. The CENC framework used by HLS Sample-AES variants. https://www.iso.org/standard/68042.html
- Bitmovin Video Developer Report 2025/26. Industry survey of 167 video developers across 34 countries on protocol, codec, and pipeline choices. https://bitmovin.com/press-room/bitmovin-com-video-developer-report-2025/ — cited for the production-share split and the "future-plan interest declining" sentiment in §"Why every other vendor implements HLS anyway."
- Mux Engineering, HLS Tags — Everything You Need to Know. A first-party engineering reference from a player and packager vendor; useful cross-check for the tag-by-tag descriptions in §"The 30 tags that matter." https://www.mux.com/articles/hls-ext-tags — secondary source; in any disagreement with the IETF draft or Apple spec, this article followed the standards documents.
- DASH-IF Implementation Guidelines: Content Protection and Security. The CENC implementation profile used by HLS-DASH-shared CMAF stacks. https://dashif-documents.azurewebsites.net/Guidelines-Security/master/Guidelines-Security.html
- DASH-IF Implementation Guidelines: Low-Latency Live Streaming (v1.2, 2024). Cross-referenced for the comparison points between LL-HLS and LL-DASH cited at the end of §"Low-latency tags." https://dashif-documents.azurewebsites.net/Guidelines-LowLatency/master/Guidelines-LowLatency.html
Note on hierarchy: in any disagreement between sources above, this article followed the standards documents (RFC 8216, draft-pantos-hls-rfc8216bis-22, ISO/IEC 23000-19, ISO/IEC 23001-7, RFC 6381) and the Apple HLS Authoring Specification over vendor blogs and analyst reports. The HTTP/2-push and multivariant-naming details, in particular, follow the Apple spec's revision history and contradict older blog posts.


