Low-Latency HLS and CMAF: Cutting the Live Delay
How CMAF chunked encoding, LL-HLS partial segments, preload hints, and LL-DASH cut live latency from 30s to under 3s — plus the real tradeoffs.
Traditional HLS and DASH were built for scale, not speed. A classic live HLS deployment with 6-second segments and a 3-segment buffer sits 20–30 seconds behind the live edge — fine for a movie, unacceptable for sports, auctions, or betting. Low-Latency HLS (LL-HLS), CMAF chunked transfer, and Low-Latency DASH (LL-DASH) were designed to close that gap to a few seconds while keeping the CDN-friendly, segment-based delivery model. This post breaks down how they work and where the latency actually goes.
Where the latency comes from
Live latency is the sum of several stages, and segment duration dominates:
- Encoder/packager delay — the encoder must finish a full segment before it can publish it.
- Segment availability — a 6s segment isn't downloadable until its last frame is encoded.
- Player buffer — players hold 2–3 segments before starting playback to absorb network jitter.
- CDN propagation — the segment must reach the edge the viewer hits.
With 6s segments and 3 buffered, you are structurally ~18s behind before network and CDN overhead. The core trick of low latency is to stop waiting for whole segments and start delivering sub-segment pieces as they encode.
CMAF: the shared container
CMAF (Common Media Application Format) is the fragmented-MP4 container that
makes all of this practical. Its key property for low latency is the CMAF
chunk — a segment is encoded as a sequence of small moof+mdat chunks,
each holding a fraction of the segment (often a single GOP or even one frame's
worth of data).
Two ideas combine:
- Chunked encoding — the encoder emits CMAF chunks as soon as they are ready instead of buffering a whole segment.
- Chunked transfer encoding — the origin/CDN streams those chunks over HTTP
using
Transfer-Encoding: chunked, so the player receives the head of a segment while its tail is still being produced.
Because CMAF is a single container, the same media files can serve both HLS and DASH — you signal them differently in the manifest but the segments are identical, which halves storage and improves cache hit ratio.
LL-HLS in detail
Apple's LL-HLS adds several playlist constructs. You can inspect any of these on a real manifest with the manifest tool.
Partial segments (EXT-X-PART)
Each full segment is published incrementally as parts — typically 200–500ms each. The player can fetch and play parts as they appear, long before the parent segment is complete:
#EXT-X-PART:DURATION=0.33334,URI="seg1.0.mp4",INDEPENDENT=YES
#EXT-X-PART:DURATION=0.33334,URI="seg1.1.mp4"
#EXT-X-PART:DURATION=0.33334,URI="seg1.2.mp4"
#EXTINF:1.00002,
seg1.mp4
INDEPENDENT=YES marks a part that begins with an IDR frame, so the player can
start decoding there.
Preload hints
The server advertises the next part before it exists so the player can issue a blocking request for it ahead of time:
#EXT-X-PRELOAD-HINT:TYPE=PART,URI="seg2.0.mp4"
The player requests this URI immediately; the server holds the response open and flushes the part the moment it is encoded. This removes a full round-trip from the critical path.
Blocking playlist reload
Instead of polling the media playlist on a timer (and discovering new parts late), the player requests a specific future state:
GET /media.m3u8?_HLS_msn=152&_HLS_part=3
The server blocks the response until media sequence 152, part 3 is available, then returns immediately. This delivers playlist updates with near-zero latency and eliminates wasteful polling.
Rendition reports
#EXT-X-RENDITION-REPORT lets the player know the current state of other
renditions so an ABR switch doesn't require a fresh full playlist fetch and
re-sync — important when you're operating on a tight buffer.
LL-DASH in detail
DASH achieves low latency with the same CMAF chunks but different signaling:
availabilityTimeOffseton aSegmentTemplatetells the player a segment becomes available before its nominal end time, because chunks stream as they encode.availabilityTimeComplete="false"signals the segment is delivered via chunked transfer.- A
<ServiceDescription>with<Latency target="3000"/>and<PlaybackRate min="0.96" max="1.04"/>lets the client gently speed up or slow down playback to hold its target latency.
<ServiceDescription id="0">
<Latency target="3000" min="2000" max="6000"/>
<PlaybackRate min="0.96" max="1.04"/>
</ServiceDescription>
That playback-rate trick — imperceptibly nudging speed to maintain a target offset — is one DASH leaned into early and LL-HLS players later adopted too.
A rough latency budget
Targeting ~3 seconds glass-to-glass, an approximate breakdown looks like:
- Capture + encode (chunked, ~333ms chunks): ~0.3–0.5s
- Packaging + first-chunk publish: ~0.2s
- CDN delivery of parts: ~0.3–0.6s
- Player buffer (a few parts): ~0.5–1.5s
These are illustrative, not benchmarks — your real numbers depend on chunk size, CDN, and how aggressively the player trims its buffer.
The tradeoffs
Low latency is not free:
- Thinner buffer = less resilience. A 1-second buffer tolerates far less jitter; a single slow part causes a visible stall. Low-latency streams rebuffer more on poor networks.
- CDN support is mandatory. Blocking playlist reloads and chunked transfer require origin and edge support; misconfigured caching can serve stale parts or break the blocking semantics entirely.
- ABR is harder. Throughput estimation on sub-second parts is noisy, so low-latency ABR leans more on buffer-occupancy signals than raw bandwidth measurement.
- More requests. Parts multiply request volume 3–10x versus whole segments, raising request-per-second load on the CDN.
Takeaways
CMAF chunked encoding is the foundation; LL-HLS layers parts, preload hints, and
blocking reload on top, while LL-DASH uses availabilityTimeOffset and playback-
rate control to hit the same target. The engineering reality is a constant
tension between latency and stability — push the buffer too thin and your
rebuffering ratio climbs. Validate your low-latency manifest structure with
the manifest tool, and once you're live, watch the rebuffering
tradeoff land in your QoE numbers (see QoE metrics that matter).
Try it yourself
Reading about streaming is one thing — pull apart a real manifest, play a stream, and measure its QoE with the toolkit.
Browse all tools