StreamTest

How to test low-latency HLS (LL-HLS) delivery

Testing low-latency HLS means confirming the playlist actually advertises LL-HLS features, then measuring real end-to-end delay rather than trusting the label. A playlist can be served from an "LL-HLS enabled" encoder and still fall back to regular segment-level latency if partial segments, blocking playlist reloads, or preload hints are missing or misconfigured.

The two things worth separating are protocol compliance (does the playlist have the right tags) and measured latency (is the player actually close to the live edge). A stream can pass one and fail the other.

Which tags in the playlist actually indicate LL-HLS is active?

#EXT-X-SERVER-CONTROL, near the top of the playlist, is the clearest signal; it carries attributes like CAN-BLOCK-RELOAD=YES and PART-HOLD-BACK. If CAN-BLOCK-RELOAD is absent or NO, the server does not support blocking playlist reloads and the client is stuck with poll-based latency regardless of anything else in the file.

#EXT-X-PART-INF:PART-TARGET=0.5 declares the target duration of a partial segment; this must be present alongside actual #EXT-X-PART lines inside each segment's block, or the playlist is only declaring intent without delivering parts.

Each #EXT-X-PART:DURATION=0.5,URI="...",INDEPENDENT=YES entry is a sub-segment the client can fetch before the full segment it belongs to is complete. INDEPENDENT=YES marks a part that starts with a keyframe and can be decoded on its own; without at least one independent part per segment, a client joining mid-segment has nothing to start decoding from.

What is PART-HOLD-BACK and why does it set the latency floor?

PART-HOLD-BACK, part of EXT-X-SERVER-CONTROL, is the minimum distance from the live edge the client should maintain, expressed as a multiple of PART-TARGET, usually around three part durations. A player respecting a PART-HOLD-BACK of 1.5 seconds cannot go lower than that no matter how fast the network is, since it is a deliberate safety margin against playing partial data that might still change.

If measured latency sits noticeably above PART-HOLD-BACK, the bottleneck is elsewhere (network RTT, encoder-to-origin lag, CDN buffering); if it sits at or near PART-HOLD-BACK, the delivery chain is working as designed and further gains require lowering PART-TARGET itself.

How do you check blocking playlist reloads are actually working?

A client requests the next playlist update with query parameters _HLS_msn=<sequence> and _HLS_part=<part index>, and a correctly configured LL-HLS origin holds that request open until the requested part exists, then responds immediately rather than making the client poll. Fetching a playlist URL with these parameters manually and timing the response tells you whether the server actually blocks or just returns instantly with stale data.

If the server ignores the _HLS_msn/_HLS_part parameters and returns the current playlist immediately every time, the client falls back to fixed-interval polling, and latency will drift back up to something closer to a full segment duration.

What does EXT-X-PRELOAD-HINT tell you about how far ahead the server can serve data?

#EXT-X-PRELOAD-HINT:TYPE=PART,URI="..." announces a part the server expects to produce next, letting a client start a request for it before the server has finished writing it and stream the response as bytes arrive. Its presence indicates the origin supports chunked, in-progress delivery rather than only serving fully-written files.

A playlist with parts and blocking reload but no preload hints still works, just with slightly higher latency, since the client waits for each part to fully land before requesting the next rather than racing ahead.

How do you measure actual glass-to-glass or edge-to-player latency?

Embed a visible running clock or frame counter in the source video itself, capture the player's output, and compare timestamps; this measures true end-to-end delay including encoder, packaging, CDN, and player buffering. It is more reliable than trusting any single component's self-reported latency.

A proxy measurement, when you cannot alter the source, is comparing #EXT-X-PROGRAM-DATE-TIME on the newest segment or part against current wall-clock time at the moment the player is actually rendering that content, though this only captures delivery-side latency, not player buffer depth.

What commonly breaks LL-HLS even when the playlist looks correct?

A CDN or proxy in front of the origin that does not support connection-holding for blocking reload requests will time out or return early, silently degrading LL-HLS to regular polling latency even though the origin playlist is fully compliant. This is invisible from the playlist text alone and only shows up as measured latency creeping up.

Players that do not implement the LL-HLS client spec (older hls.js versions, most native Smart TV HLS stacks) will ignore EXT-X-PART entirely and just play the full segment once ENDLIST or the completed segment appears, silently falling back to standard HLS latency.

Step by step

  1. Fetch the media playlist and check for EXT-X-SERVER-CONTROL with CAN-BLOCK-RELOAD=YES.
  2. Confirm EXT-X-PART-INF is present and that segments near the live edge contain EXT-X-PART entries.
  3. Note the PART-HOLD-BACK value as your theoretical latency floor.
  4. Request the playlist with _HLS_msn and _HLS_part query parameters and time how long the response takes to confirm blocking reload is real.
  5. Check for EXT-X-PRELOAD-HINT on the in-progress part.
  6. Measure actual latency with a visible clock in the source compared to player output, or via PROGRAM-DATE-TIME against wall clock as a fallback.
  7. Re-test with the actual target player (not just curl), since LL-HLS support varies significantly by client.

Run it yourself

Free, no sign-up, and every finding links to an explainer.

Frequently asked questions

What latency counts as "low latency" for LL-HLS in practice?
Two to five seconds glass-to-glass is a realistic target for a well-configured LL-HLS chain end to end; sub-second numbers usually describe only the delivery hop, not full player buffer and decode time. Anything above six or seven seconds suggests LL-HLS features are only partially active somewhere in the chain.
Does a smaller PART-TARGET always mean lower latency?
Only up to a point: smaller parts mean more frequent, smaller requests, which increases HTTP overhead and can hurt reliability on higher-RTT or lossy networks. Most production LL-HLS deployments use part durations between 0.33 and 1 second as a practical balance.
Can LL-HLS work over a standard CDN with no special configuration?
Not fully; a CDN needs to support holding connections open for blocking playlist reload requests and ideally chunked transfer for in-progress parts. A CDN that only caches and serves complete files will still deliver the stream, just with latency closer to standard HLS.
Why does my player ignore EXT-X-PART tags entirely?
Most native platform HLS decoders (older Smart TV firmware, many set-top boxes) predate LL-HLS and simply do not parse EXT-X-PART, EXT-X-PRELOAD-HINT, or the blocking-reload query parameters. They still play the stream correctly once each full segment is complete, just at standard HLS latency.

HLS findings, explained

Read next

Last reviewed 2026-09-16.