ABR Streaming
Back to blog
Protocols & Protection

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.

ABR Streaming Team5 min read
LL-HLSCMAFLow LatencyDASHLive

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:

  • availabilityTimeOffset on a SegmentTemplate tells 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