{"id":1298,"date":"2026-09-09T09:48:55","date_gmt":"2026-09-09T02:48:55","guid":{"rendered":"https:\/\/liveapi.com\/blog\/low-latency-hls\/"},"modified":"2026-09-09T13:21:33","modified_gmt":"2026-09-09T06:21:33","slug":"low-latency-hls","status":"publish","type":"post","link":"https:\/\/liveapi.com\/blog\/low-latency-hls\/","title":{"rendered":"Low Latency HLS (LL-HLS): How It Works, Latency, and How to Implement It"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\">13<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span><p>Standard HLS ships live video with 10 to 30 seconds of delay. That&#8217;s fine for a movie. It&#8217;s useless for a sports stream where your viewers hear the neighbors cheer before they see the goal.<\/p>\n<p>Low latency HLS closes that gap to roughly 2 to 5 seconds without asking you to abandon the HLS ecosystem you already run on.<\/p>\n<p>Apple published the extension in 2019, folded it into the main HLS specification in 2020, and every major player now supports it.<\/p>\n<h2>What Is Low Latency HLS?<\/h2>\n<p>Low latency HLS (LL-HLS) is an extension to the HTTP Live Streaming protocol that cuts live stream delay to about 2 to 5 seconds by publishing short partial segments before a full segment finishes encoding.<\/p>\n<p>Standard HLS makes the player wait for a complete segment (typically 2 to 6 seconds of video), then wait again while it polls the playlist to find out that segment exists. Stack up the buffer a player holds before playback and you get double-digit delay.<\/p>\n<p>LL-HLS attacks both halves of that problem. It splits each segment into parts of 200 to 500 milliseconds that the server publishes as soon as they&#8217;re encoded, and it replaces playlist polling with requests the server holds open until new media is ready.<\/p>\n<p>The extension exists because HLS won on reach and lost on speed. It plays natively on iOS, Android, smart TVs, and every browser, and it rides ordinary HTTP caches.<\/p>\n<p>Rewriting all of that to chase latency was never realistic, so Apple made HLS itself faster. Critically, LL-HLS playlists stay <a href=\"https:\/\/developer.apple.com\/documentation\/http-live-streaming\/enabling-low-latency-http-live-streaming-hls\" target=\"_blank\" rel=\"nofollow noopener\">backward compatible<\/a>. A player that doesn&#8217;t understand the new tags ignores them and plays the full segments at normal latency.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Attribute<\/th>\n<th>Standard HLS<\/th>\n<th>Low Latency HLS<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Typical glass-to-glass latency<\/td>\n<td>10\u201330 seconds<\/td>\n<td>2\u20135 seconds<\/td>\n<\/tr>\n<tr>\n<td>Smallest unit published<\/td>\n<td>Full segment (2\u20136s)<\/td>\n<td>Partial segment (0.2\u20130.5s)<\/td>\n<\/tr>\n<tr>\n<td>Playlist discovery<\/td>\n<td>Client polls on a timer<\/td>\n<td>Server holds the request open<\/td>\n<\/tr>\n<tr>\n<td>Playlist size on long streams<\/td>\n<td>Grows to megabytes<\/td>\n<td>Trimmed by delta updates<\/td>\n<\/tr>\n<tr>\n<td>Quality switching<\/td>\n<td>Fetch each rendition&#8217;s playlist<\/td>\n<td>Rendition reports in one response<\/td>\n<\/tr>\n<tr>\n<td>CDN compatibility<\/td>\n<td>Any HTTP cache<\/td>\n<td>Any HTTP cache, cache key must include query strings<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h2>LL-HLS vs LHLS vs CMAF-CTE vs WebRTC<\/h2>\n<p>Four low latency approaches share overlapping vocabulary, and the names are close enough to cause real confusion. Here&#8217;s what separates them.<\/p>\n<p><strong>LL-HLS<\/strong> is Apple&#8217;s official extension, now part of the HLS specification. It uses partial segments plus blocking playlist requests, and it&#8217;s what &#8220;low latency HLS&#8221; means in 2026.<\/p>\n<p><strong>LHLS<\/strong> (no hyphen after the second L) was a community approach that predated Apple&#8217;s spec, pioneered largely at Periscope. It used HTTP chunked transfer encoding to stream a segment while it was still being written. It never became a standard, and Apple&#8217;s LL-HLS effectively replaced it. You&#8217;ll still see the term in older documentation.<\/p>\n<p><strong>CMAF-CTE<\/strong> (Common Media Application Format with chunked transfer encoding, also called LL-DASH on the DASH side) takes the chunked-encoding route inside fragmented MP4 containers. Because <a href=\"https:\/\/liveapi.com\/blog\/what-is-cmaf\/\" target=\"_blank\" rel=\"noopener\">CMAF<\/a> segments can serve both HLS and DASH manifests, one encode covers both ecosystems. Our breakdown of <a href=\"https:\/\/liveapi.com\/blog\/cmaf-vs-hls\/\" target=\"_blank\" rel=\"noopener\">CMAF vs HLS<\/a> digs into that tradeoff.<\/p>\n<p><strong>WebRTC<\/strong> is a different protocol family entirely, built for real-time conversation rather than broadcast. It reaches 100 to 500 milliseconds, but it needs signaling servers, TURN relays, and media servers that scale per viewer. See <a href=\"https:\/\/liveapi.com\/blog\/webrtc-vs-hls\/\" target=\"_blank\" rel=\"noopener\">WebRTC vs HLS<\/a> for where each one wins.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Approach<\/th>\n<th>Typical latency<\/th>\n<th>Transport mechanism<\/th>\n<th>Scales on CDN<\/th>\n<th>Ecosystem<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Standard HLS<\/td>\n<td>10\u201330s<\/td>\n<td>Full segment download<\/td>\n<td>Yes<\/td>\n<td>Universal<\/td>\n<\/tr>\n<tr>\n<td>LL-HLS<\/td>\n<td>2\u20135s<\/td>\n<td>Partial segments + blocking reload<\/td>\n<td>Yes<\/td>\n<td>HLS<\/td>\n<\/tr>\n<tr>\n<td>LHLS (legacy)<\/td>\n<td>3\u20137s<\/td>\n<td>Chunked transfer encoding<\/td>\n<td>Partly<\/td>\n<td>HLS, deprecated<\/td>\n<\/tr>\n<tr>\n<td>CMAF-CTE \/ LL-DASH<\/td>\n<td>3\u20136s<\/td>\n<td>Chunked transfer encoding<\/td>\n<td>Yes<\/td>\n<td>HLS + DASH<\/td>\n<\/tr>\n<tr>\n<td>WebRTC<\/td>\n<td>0.1\u20130.5s<\/td>\n<td>UDP peer\/SFU delivery<\/td>\n<td>No, needs media servers<\/td>\n<td>Real-time apps<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>The rest of this guide uses LL-HLS to mean Apple&#8217;s specification.<\/p>\n<h2>How Does Low Latency HLS Work?<\/h2>\n<p>LL-HLS keeps the HLS delivery model: an <a href=\"https:\/\/liveapi.com\/blog\/what-is-m3u8\/\" target=\"_blank\" rel=\"noopener\">m3u8 playlist<\/a> pointing at media files over HTTP. What changes is what the server publishes and how the client asks for it.<\/p>\n<ol>\n<li><strong>Your encoder pushes a live feed to the origin.<\/strong> Ingest arrives over <a href=\"https:\/\/liveapi.com\/blog\/what-is-rtmp\/\" target=\"_blank\" rel=\"noopener\">RTMP<\/a> or <a href=\"https:\/\/liveapi.com\/blog\/srt-protocol\/\" target=\"_blank\" rel=\"noopener\">SRT<\/a>, with the <a href=\"https:\/\/liveapi.com\/blog\/keyframe-interval\/\" target=\"_blank\" rel=\"noopener\">keyframe interval<\/a> set short, usually 1 to 2 seconds, because segments can&#8217;t be shorter than a GOP.<\/li>\n<li><strong>The packager writes partial segments as they encode.<\/strong> Rather than holding a 4-second segment until it&#8217;s complete, the packager emits parts of 200 to 500 milliseconds and appends an <code>EXT-X-PART<\/code> tag for each one.<\/li>\n<li><strong>The playlist advertises what&#8217;s coming next.<\/strong> An <code>EXT-X-PRELOAD-HINT<\/code> tag names the part that hasn&#8217;t been produced yet, so the client can request it before it exists.<\/li>\n<li><strong>The client asks for the future, not the present.<\/strong> Instead of re-downloading the playlist every few seconds hoping something changed, the player appends <code>_HLS_msn<\/code> and <code>_HLS_part<\/code> query parameters naming the part it wants. The server holds that connection open and answers the instant the part is ready.<\/li>\n<li><strong>The server holds the preload request too.<\/strong> The GET for the hinted part sits open on the origin and starts responding the moment bytes exist, so there&#8217;s no request round trip after the playlist update.<\/li>\n<li><strong>The player starts playback close to the live edge.<\/strong> How close is set by <code>PART-HOLD-BACK<\/code>, the server-recommended distance from the end of the playlist. That single number is the main lever on your latency.<\/li>\n<\/ol>\n<p>The shift that matters is from polling to blocking. Standard HLS wastes time asking &#8220;is there anything new?&#8221; LL-HLS asks &#8220;tell me the moment there is,&#8221; and that removes most of the delay that isn&#8217;t already spoken for by encoding.<\/p>\n<h2>The Five Mechanisms Behind LL-HLS<\/h2>\n<p>Five features do the actual work. Understanding them is the difference between hitting 2 seconds and wondering why you&#8217;re stuck at 8.<\/p>\n<h3>1. Partial Segments<\/h3>\n<p>The core idea. Each media segment is subdivided into parts, and each part gets an <code>EXT-X-PART<\/code> tag carrying a <code>URI<\/code> and a <code>DURATION<\/code>. An optional <code>INDEPENDENT=YES<\/code> attribute flags parts that start with an independently decodable frame, which players need for joining and switching.<\/p>\n<p>Parts are transient. The spec says <code>EXT-X-PART<\/code> tags should be removed once they&#8217;re more than three target durations from the end of the playlist, though clients must still be able to download a part for at least three target durations after its tag disappears. The <code>EXT-X-PART-INF<\/code> tag declares <code>PART-TARGET<\/code>, the part target duration, which every part must respect.<\/p>\n<h3>2. Blocking Playlist Reload<\/h3>\n<p>The client requests a playlist that doesn&#8217;t exist yet. It appends <code>_HLS_msn=&lt;media sequence number&gt;<\/code> and optionally <code>_HLS_part=&lt;part index&gt;<\/code> to the playlist URI, and the server defers its response until that part is available.<\/p>\n<p>This is the single biggest win. Polling costs you up to a full poll interval on every update; blocking costs you nothing. The server signals support with <code>CAN-BLOCK-RELOAD=YES<\/code> in <code>EXT-X-SERVER-CONTROL<\/code>. If it can&#8217;t satisfy the request after blocking for more than three target durations, it should return a 503 rather than hang forever.<\/p>\n<h3>3. Preload Hints<\/h3>\n<p><code>EXT-X-PRELOAD-HINT<\/code> names a resource the server hasn&#8217;t finished producing. The client issues a GET immediately, the server holds it, and bytes flow as soon as they&#8217;re encoded. Optional <code>BYTERANGE-START<\/code> and <code>BYTERANGE-LENGTH<\/code> attributes let a single file host multiple parts by byte range, which cuts down on file count.<\/p>\n<p>Combined with blocking reload, preload hints remove the request round trip between learning a part exists and having its data.<\/p>\n<h3>4. Playlist Delta Updates<\/h3>\n<p>A live playlist on a multi-hour stream grows to megabytes, and re-downloading it several times a second is absurd.<\/p>\n<p>So the client adds <code>_HLS_skip=YES<\/code>, and the server returns only the recent portion, replacing the older entries with an <code>EXT-X-SKIP<\/code> tag carrying <code>SKIPPED-SEGMENTS<\/code>. The server advertises this with <code>CAN-SKIP-UNTIL<\/code>, which must be at least six times the target duration.<\/p>\n<p>This is the one mechanism that affects your playlist version: a playlist containing <code>EXT-X-SKIP<\/code> needs <code>EXT-X-VERSION:9<\/code> or higher, and version 10 if the skip also replaces <code>EXT-X-DATERANGE<\/code> tags. Some guides claim all LL-HLS tags require version 10. They don&#8217;t.<\/p>\n<h3>5. Rendition Reports<\/h3>\n<p>When a player switches quality in standard HLS, it fetches the new rendition&#8217;s playlist and figures out where the live edge is, which is expensive at low latency. <code>EXT-X-RENDITION-REPORT<\/code> solves it by including each other rendition&#8217;s <code>URI<\/code>, <code>LAST-MSN<\/code>, and <code>LAST-PART<\/code> right in the current playlist. The player already knows where to jump in, so <a href=\"https:\/\/liveapi.com\/blog\/adaptive-bitrate-streaming\/\" target=\"_blank\" rel=\"noopener\">adaptive bitrate streaming<\/a> switches stay fast at the live edge.<\/p>\n<p>Here&#8217;s how it looks in a real playlist:<\/p>\n<pre><code>#EXTM3U\r\n#EXT-X-VERSION:9\r\n#EXT-X-TARGETDURATION:4\r\n#EXT-X-PART-INF:PART-TARGET=0.5\r\n#EXT-X-SERVER-CONTROL:CAN-BLOCK-RELOAD=YES,PART-HOLD-BACK=1.5,CAN-SKIP-UNTIL=24.0\r\n#EXT-X-MEDIA-SEQUENCE:412\r\n#EXT-X-SKIP:SKIPPED-SEGMENTS=90\r\n\r\n#EXTINF:4.00000,\r\nsegment412.m4s\r\n\r\n#EXT-X-PART:DURATION=0.50000,URI=\"segment413.0.m4s\",INDEPENDENT=YES\r\n#EXT-X-PART:DURATION=0.50000,URI=\"segment413.1.m4s\"\r\n#EXT-X-PART:DURATION=0.50000,URI=\"segment413.2.m4s\"\r\n#EXT-X-PRELOAD-HINT:TYPE=PART,URI=\"segment413.3.m4s\"\r\n\r\n#EXT-X-RENDITION-REPORT:URI=\"..\/720p\/index.m3u8\",LAST-MSN=413,LAST-PART=2\r\n#EXT-X-RENDITION-REPORT:URI=\"..\/480p\/index.m3u8\",LAST-MSN=413,LAST-PART=2<\/code><\/pre>\n<p>Segment 413 is still being encoded. Three of its parts are published, the fourth is hinted, and the player already has a request open for it.<\/p>\n<p>One note on history. Apple&#8217;s original 2019 draft required HTTP\/2 server push, delivered via an <code>_HLS_push<\/code> directive. CDNs hated it, and it was removed in 2020.<\/p>\n<p>The <a href=\"https:\/\/www.ietf.org\/archive\/id\/draft-pantos-hls-rfc8216bis-17.txt\" target=\"_blank\" rel=\"nofollow noopener\">current specification<\/a> defines exactly three delivery directives: <code>_HLS_skip<\/code>, <code>_HLS_msn<\/code>, and <code>_HLS_part<\/code>. If you&#8217;re reading a guide that tells you to configure HTTP\/2 push for LL-HLS, it&#8217;s out of date.<\/p>\n<h2>Low Latency HLS Latency: What to Actually Expect<\/h2>\n<p>LL-HLS delivers 2 to 5 seconds of glass-to-glass latency in production, with well-tuned deployments landing near 2 seconds. That&#8217;s down from 10 to 30 seconds for standard HLS.<\/p>\n<p>The number isn&#8217;t magic. It&#8217;s arithmetic, and <code>PART-HOLD-BACK<\/code> dominates it. The spec requires <code>PART-HOLD-BACK<\/code> to be at least twice the part target duration and recommends at least three times. So your practical floor is roughly:<\/p>\n<p><strong>latency \u2248 encoder delay + PART-HOLD-BACK + network transit + player buffer<\/strong><\/p>\n<p>Shrink <code>PART-TARGET<\/code> and <code>PART-HOLD-BACK<\/code> together and latency drops. OvenMediaEngine&#8217;s <a href=\"https:\/\/ovenmedia.com\/blog\/low-latency-hls-the-era-of-flexible-low-latency-streaming\" target=\"_blank\" rel=\"nofollow noopener\">measured benchmarks<\/a> show the relationship cleanly:<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Part target duration<\/th>\n<th>PART-HOLD-BACK<\/th>\n<th>Measured latency<\/th>\n<th>Profile<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>1.0s<\/td>\n<td>3.0s<\/td>\n<td>3.73s<\/td>\n<td>Stability first<\/td>\n<\/tr>\n<tr>\n<td>0.5s<\/td>\n<td>1.5s<\/td>\n<td>1.93s<\/td>\n<td>Balanced<\/td>\n<\/tr>\n<tr>\n<td>0.2s<\/td>\n<td>0.6s<\/td>\n<td>1.03s<\/td>\n<td>Aggressive<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<p>Sub-second latency over HTTP is real. It&#8217;s also fragile. A 0.6-second hold-back leaves almost no buffer for a network hiccup, so viewers on unstable connections rebuffer instead.<\/p>\n<p>Most teams land on 0.5-second parts with a 1.5-second hold-back, which trades a second of delay for playback that survives real networks.<\/p>\n<p>Two other factors set a hard ceiling regardless of your tuning. Your keyframe interval bounds segment length, so a 4-second GOP caps how short parts can usefully be. And ingest matters: pushing over SRT rather than RTMP shaves off contribution delay on lossy links. Our guide to <a href=\"https:\/\/liveapi.com\/blog\/what-is-video-latency\/\" target=\"_blank\" rel=\"noopener\">video latency<\/a> breaks down where each millisecond goes.<\/p>\n<h2>Advantages of Low Latency HLS<\/h2>\n<h3>It runs on the CDN you already have<\/h3>\n<p>LL-HLS is still HTTP. No SFUs, no TURN servers, no per-viewer compute. The same <a href=\"https:\/\/liveapi.com\/blog\/multi-cdn\/\" target=\"_blank\" rel=\"noopener\">multi-CDN<\/a> setup that serves standard HLS serves LL-HLS, with one caching change we&#8217;ll cover below.<\/p>\n<h3>It scales to millions of concurrent viewers<\/h3>\n<p>Because delivery is cacheable HTTP, cost per viewer stays flat as audience grows. WebRTC gets you to 500 milliseconds but every additional viewer consumes media-server resources. That&#8217;s the tradeoff behind <a href=\"https:\/\/liveapi.com\/blog\/ultra-low-latency-video-streaming\/\" target=\"_blank\" rel=\"noopener\">ultra low latency video streaming<\/a> architectures.<\/p>\n<h3>Backward compatibility is built in<\/h3>\n<p>Old players ignore the new tags and play full segments. You ship one stream and serve everybody: no parallel pipeline, no user-agent sniffing.<\/p>\n<h3>Native playback on Apple devices<\/h3>\n<p>AVPlayer handles LL-HLS natively from iOS 14 onward. No JavaScript player, no third-party SDK, no workaround for Safari&#8217;s refusal to play MSE-based streams on iPhone.<\/p>\n<h3>Adaptive bitrate still works<\/h3>\n<p>Rendition reports keep quality switching fast at the live edge, so viewers on bad connections drop a rung instead of stalling. Latency doesn&#8217;t cost you ABR.<\/p>\n<h3>One protocol from live to VOD<\/h3>\n<p>The same HLS segments that serve your live stream become your recording. Turning a broadcast into on-demand content is a packaging step, not a re-encode. See <a href=\"https:\/\/liveapi.com\/blog\/live-to-vod\/\" target=\"_blank\" rel=\"noopener\">live to VOD<\/a> for the workflow.<\/p>\n<h2>Disadvantages of Low Latency HLS<\/h2>\n<h3>It can&#8217;t reach sub-second latency<\/h3>\n<p>Two seconds is a floor you can approach but not break by much. Video calls, auctions, and betting interfaces need WebRTC. If your product depends on genuine conversation, LL-HLS is the wrong tool.<\/p>\n<h3>Request volume goes up sharply<\/h3>\n<p>Publishing 0.5-second parts instead of 4-second segments means eight times the media requests, plus a blocking playlist request per part. Origin and CDN request counts climb, and on usage-based pricing so does your bill. Larger parts and byte-range addressing pull it back down.<\/p>\n<h3>Your CDN needs configuring<\/h3>\n<p>Delivery directives are query strings, so <code>_HLS_msn<\/code> and <code>_HLS_part<\/code> must be part of the cache key or the CDN serves stale playlists to everyone. Your CDN also has to tolerate origin connections held open for seconds. Not every edge configuration does this out of the box, and it&#8217;s the most common reason a technically correct LL-HLS deployment delivers standard-HLS latency.<\/p>\n<h3>Tuning is unforgiving<\/h3>\n<p>Get <code>PART-HOLD-BACK<\/code> wrong and you either give up your latency gains or ship a stream that rebuffers constantly. There&#8217;s no safe default that works across every audience, so plan on measuring against real viewers rather than a lab.<\/p>\n<h3>Building the pipeline yourself is a real project<\/h3>\n<p>Partial-segment packaging, blocking request handling, delta updates, rendition reports, and per-rendition part alignment across an ABR ladder add up to months of work, none of which ships a user-facing feature. Most teams reach for managed infrastructure instead.<\/p>\n<p>Now that you know what LL-HLS is, how it works, and where it strains, here&#8217;s the practical side: how to get a low latency HLS stream running, what players and CDNs support it, and whether it fits your project.<\/p>\n<h2>How to Implement Low Latency HLS<\/h2>\n<h3>1. Set your keyframe interval first<\/h3>\n<p>Segments can&#8217;t be shorter than a GOP, so this decision bounds everything downstream. Use a 1- or 2-second keyframe interval with keyframes at fixed positions. Disable scene-change keyframe insertion, because variable GOPs break part alignment across renditions. Your <a href=\"https:\/\/liveapi.com\/blog\/live-streaming-encoder\/\" target=\"_blank\" rel=\"noopener\">live streaming encoder<\/a> settings matter more here than anywhere else in the chain.<\/p>\n<h3>2. Choose your ingest protocol<\/h3>\n<p>RTMP works and is universally supported by encoders and OBS. SRT handles packet loss better and cuts contribution latency on unreliable networks, which matters when you&#8217;re chasing a 2-second total budget. If your source is remote or on cellular, go with SRT.<\/p>\n<h3>3. Package into CMAF with partial segments<\/h3>\n<p>Use fMP4\/CMAF rather than MPEG-TS so the same segments can feed DASH later. Configure your packager to emit parts and the LL-HLS tags. With ffmpeg, the low latency HLS flags look like this:<\/p>\n<pre><code class=\"language-bash\">ffmpeg -i srt:\/\/0.0.0.0:9000?mode=listener \\\r\n  -c:v libx264 -preset veryfast -tune zerolatency \\\r\n  -g 48 -keyint_min 48 -sc_threshold 0 \\\r\n  -c:a aac -b:a 128k \\\r\n  -f hls \\\r\n  -hls_time 4 \\\r\n  -hls_segment_type fmp4 \\\r\n  -hls_flags independent_segments+delete_segments \\\r\n  -hls_playlist_type event \\\r\n  -master_pl_name master.m3u8 \\\r\n  stream.m3u8<\/code><\/pre>\n<p>That gets you fMP4 segments with a fixed 2-second GOP at 24fps. But ffmpeg&#8217;s HLS muxer doesn&#8217;t emit <code>EXT-X-PART<\/code> tags on its own. You need a packager or media server that implements the LL-HLS spec for true partial segments.<\/p>\n<h3>4. Configure server control and hold-back<\/h3>\n<p>Set <code>PART-TARGET<\/code> to 0.5 seconds and <code>PART-HOLD-BACK<\/code> to 1.5 seconds as a starting point. Advertise <code>CAN-BLOCK-RELOAD=YES<\/code> and set <code>CAN-SKIP-UNTIL<\/code> to at least six times your target duration. Then measure and tighten. Don&#8217;t start aggressive.<\/p>\n<h3>5. Use a video API instead of building the origin<\/h3>\n<p>Partial-segment packaging, blocking request handling, delta updates, and rendition-report generation across an ABR ladder is a serious engineering effort, and keeping it correct as the spec evolves is ongoing work. A <a href=\"https:\/\/liveapi.com\/live-streaming-api\/\" target=\"_blank\" rel=\"noopener\">live streaming API<\/a> hands you the finished pipeline. LiveAPI takes RTMP or SRT ingest, transcodes to an adaptive bitrate ladder up to 4K, and delivers <a href=\"https:\/\/liveapi.com\/blog\/what-is-hls-streaming\/\" target=\"_blank\" rel=\"noopener\">HLS streaming<\/a> output across Akamai, Cloudflare, and Fastly, so you get low latency delivery and global reach without operating packagers or negotiating CDN contracts. Streams are playable in seconds after ingest, and recordings become VOD automatically.<\/p>\n<h3>6. Verify the tags are actually there<\/h3>\n<p>Fetch your playlist and confirm <code>EXT-X-PART<\/code>, <code>EXT-X-PRELOAD-HINT<\/code>, and <code>EXT-X-SERVER-CONTROL<\/code> are present. Then check that a request with <code>_HLS_msn<\/code> actually blocks instead of returning immediately:<\/p>\n<pre><code class=\"language-bash\">curl -s \"https:\/\/your-origin\/live\/index.m3u8\" | grep -E \"EXT-X-(PART|PRELOAD|SERVER)\"\r\n\r\ntime curl -s -o \/dev\/null \"https:\/\/your-origin\/live\/index.m3u8?_HLS_msn=999999&amp;_HLS_part=0\"<\/code><\/pre>\n<p>If that second command returns instantly, blocking reload isn&#8217;t working and you&#8217;re getting standard HLS latency with LL-HLS overhead.<\/p>\n<h3>7. Measure glass-to-glass, not playlist age<\/h3>\n<p>Point a camera at a running millisecond timer, play the stream on the same screen, and photograph both. That difference is the only latency number that means anything to a viewer. Track rebuffer ratio alongside it. Latency you can&#8217;t sustain isn&#8217;t latency you have.<\/p>\n<h2>Player and CDN Support for LL-HLS<\/h2>\n<p>Support is broad in 2026, but versions matter and the CDN side needs deliberate configuration.<\/p>\n<h3>Native Apple playback<\/h3>\n<p>AVPlayer supports LL-HLS natively from iOS 14 and tvOS 14 onward, and it&#8217;s the reference implementation. If your audience skews iOS, this alone justifies choosing LL-HLS over CMAF-CTE.<\/p>\n<h3>hls.js in the browser<\/h3>\n<p><a href=\"https:\/\/liveapi.com\/blog\/hls-js\/\" target=\"_blank\" rel=\"noopener\">hls.js<\/a> added Apple Low-Latency HLS support in v1.0.0, released April 2021. Enable it with <code>lowLatencyMode: true<\/code> in the config. It&#8217;s the default choice for browser playback outside Safari on iOS.<\/p>\n<h3>Shaka Player and ExoPlayer<\/h3>\n<p><a href=\"https:\/\/liveapi.com\/blog\/shaka-player\/\" target=\"_blank\" rel=\"noopener\">Shaka Player<\/a> supports LL-HLS and is actively maintained through its 5.x line, which is the right pick if you serve both HLS and DASH from one player. On Android, <a href=\"https:\/\/liveapi.com\/blog\/exoplayer\/\" target=\"_blank\" rel=\"noopener\">ExoPlayer<\/a> handles LL-HLS through Media3.<\/p>\n<figure class=\"wp-block-table\">\n<table>\n<thead>\n<tr>\n<th>Player<\/th>\n<th>LL-HLS support<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>AVPlayer (iOS\/tvOS)<\/td>\n<td>iOS 14+<\/td>\n<td>Native, reference implementation<\/td>\n<\/tr>\n<tr>\n<td>hls.js<\/td>\n<td>v1.0.0+ (April 2021)<\/td>\n<td>Set <code>lowLatencyMode: true<\/code><\/td>\n<\/tr>\n<tr>\n<td>Shaka Player<\/td>\n<td>v4+, maintained in 5.x<\/td>\n<td>Also covers DASH<\/td>\n<\/tr>\n<tr>\n<td>ExoPlayer \/ Media3<\/td>\n<td>Supported<\/td>\n<td>Android native<\/td>\n<\/tr>\n<tr>\n<td>Safari desktop<\/td>\n<td>Native<\/td>\n<td>Uses the system HLS stack<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/figure>\n<h3>CDN configuration<\/h3>\n<p>Two settings decide whether LL-HLS works at the edge:<\/p>\n<ul>\n<li><strong>Cache key.<\/strong> Add <code>_HLS_msn<\/code>, <code>_HLS_part<\/code>, and <code>_HLS_skip<\/code> to it. Otherwise the CDN treats every blocking request as the same object and serves stale playlists.<\/li>\n<li><strong>Connection timeouts.<\/strong> Allow long-held origin connections, because a blocking request can legitimately sit open for seconds.<\/li>\n<\/ul>\n<p>Most major CDNs support both, but neither is usually the default.<\/p>\n<h3>Managed infrastructure<\/h3>\n<p>Building and operating the origin, packager, and CDN configuration is where most LL-HLS projects stall: six to nine months of infrastructure work before the first viewer. LiveAPI covers that layer with a video encoding API that transcodes on ingest, an embeddable HTML5 player, HLS URLs that drop into OTT platforms like Roku and Apple TV, and pay-as-you-grow pricing tied to stream minutes. You configure ingest and get a playable stream, and protocol choice becomes a delivery preference rather than an infrastructure decision.<\/p>\n<h2>Is Low Latency HLS Right for Your Project?<\/h2>\n<p>LL-HLS fits a specific band of the latency spectrum. Here&#8217;s how to tell whether you&#8217;re in it.<\/p>\n<p><strong>Good fit if:<\/strong><\/p>\n<ul>\n<li>Two to five seconds of delay is acceptable for your use case<\/li>\n<li>You expect thousands to millions of concurrent viewers<\/li>\n<li>Native iOS and smart TV playback matters<\/li>\n<li>Your delivery already runs on HTTP CDNs<\/li>\n<li>You need adaptive bitrate at the live edge<\/li>\n<li>The same content has to work as VOD afterward<\/li>\n<\/ul>\n<p><strong>Not a good fit if:<\/strong><\/p>\n<ul>\n<li>Your product needs sub-second, two-way interaction<\/li>\n<li>Viewers number in the dozens and latency beats cost<\/li>\n<li>You can&#8217;t change CDN cache-key configuration<\/li>\n<li>Your encoder can&#8217;t produce fixed short GOPs<\/li>\n<\/ul>\n<p>If you land in the good-fit column, the remaining question is build versus buy. The protocol is documented and the players support it. The effort is in the origin and the edge, which is exactly the part you can rent.<\/p>\n<h2>Low Latency HLS FAQ<\/h2>\n<h3>What is the delay of low latency HLS?<\/h3>\n<p>LL-HLS typically delivers 2 to 5 seconds of glass-to-glass latency, compared with 10 to 30 seconds for standard HLS. Tuned deployments using 0.5-second parts and a 1.5-second <code>PART-HOLD-BACK<\/code> measure close to 2 seconds. Sub-1.1-second results are documented with 0.2-second parts, at the cost of rebuffer resilience.<\/p>\n<h3>Is LL-HLS better than WebRTC?<\/h3>\n<p>For broadcast to a large audience, yes. LL-HLS scales on ordinary CDNs at flat cost per viewer. For genuine two-way interaction, no. WebRTC reaches 100 to 500 milliseconds but needs signaling, TURN, and media servers that consume resources per participant.<\/p>\n<h3>Does hls.js support low latency HLS?<\/h3>\n<p>Yes. hls.js shipped Apple Low-Latency HLS support in version 1.0.0, released in April 2021. Set <code>lowLatencyMode: true<\/code> in your player config to enable it.<\/p>\n<h3>What is PART-HOLD-BACK?<\/h3>\n<p><code>PART-HOLD-BACK<\/code> is the server-recommended minimum distance from the end of the playlist at which a client should start playing in low-latency mode. The spec requires it to be at least twice the part target duration and recommends at least three times. It&#8217;s the primary lever on your latency.<\/p>\n<h3>Does LL-HLS still need HTTP\/2 push?<\/h3>\n<p>No. HTTP\/2 server push was in Apple&#8217;s original 2019 draft but was removed in 2020 after CDN pushback. The current specification defines only three delivery directives: <code>_HLS_skip<\/code>, <code>_HLS_msn<\/code>, and <code>_HLS_part<\/code>.<\/p>\n<h3>What keyframe interval should I use for LL-HLS?<\/h3>\n<p>Use a fixed 1- or 2-second keyframe interval with scene-change detection disabled. Segments can&#8217;t be shorter than a GOP, and variable GOPs break part alignment across your ABR renditions.<\/p>\n<h3>Does Netflix use HLS or DASH?<\/h3>\n<p>Netflix primarily uses DASH for its on-demand catalog, though it delivers HLS to Apple devices where native playback requires it. Neither is a low latency deployment. VOD has no live edge to chase.<\/p>\n<h3>Can I use low latency HLS with ffmpeg?<\/h3>\n<p>Partly. ffmpeg produces fMP4\/CMAF segments with the fixed short GOPs LL-HLS needs, but its HLS muxer doesn&#8217;t emit <code>EXT-X-PART<\/code> or <code>EXT-X-PRELOAD-HINT<\/code> tags. For true partial segments you need a packager or media server that implements the LL-HLS spec.<\/p>\n<h3>Is low latency HLS the same as low latency streaming?<\/h3>\n<p>No. <a href=\"https:\/\/liveapi.com\/blog\/what-is-low-latency-streaming\/\" target=\"_blank\" rel=\"noopener\">Low latency streaming<\/a> is the general category, covering LL-HLS, CMAF-CTE, WebRTC, SRT, and others. LL-HLS is one specific approach within it, targeting the 2-to-5-second range on HTTP delivery.<\/p>\n<h2>Bringing It Together<\/h2>\n<p>Low latency HLS gives you a 5x latency improvement over standard HLS while keeping everything that made HLS worth using: CDN scale, universal player support, native Apple playback, and adaptive bitrate. Partial segments, blocking playlist reload, preload hints, delta updates, and rendition reports each remove a specific source of delay, and <code>PART-HOLD-BACK<\/code> is the dial you turn to trade latency against stability.<\/p>\n<p>The protocol side is settled and documented. The hard part is the origin and the edge: packaging parts correctly across an ABR ladder, handling held-open requests, and getting cache keys right on every CDN you use.<\/p>\n<p><strong>Ready to ship low latency live video?<\/strong> LiveAPI handles RTMP and SRT ingest, instant adaptive bitrate encoding up to 4K, HLS delivery across Akamai, Cloudflare, and Fastly, and automatic live-to-VOD recording \u2014 launch in days, not months. <a href=\"https:\/\/liveapi.com\/\" target=\"_blank\" rel=\"noopener\">Get started with LiveAPI<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">Reading Time: <\/span> <span class=\"rt-time\">13<\/span> <span class=\"rt-label rt-postfix\">minutes<\/span><\/span> Standard HLS ships live video with 10 to 30 seconds of delay. That&#8217;s fine for a movie. It&#8217;s useless for a sports stream where your viewers hear the neighbors cheer before they see the goal. Low latency HLS closes that gap to roughly 2 to 5 seconds without asking you to abandon the HLS ecosystem [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1305,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_yoast_wpseo_title":"Low Latency HLS (LL-HLS): How It Works and How to Use It %%sep%% %%sitename%%","_yoast_wpseo_metadesc":"Learn what low latency HLS is, how LL-HLS partial segments and blocking playlist reload work, real latency numbers, and how to implement it.","inline_featured_image":false,"footnotes":""},"categories":[13],"tags":[],"class_list":["post-1298","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hls"],"jetpack_featured_media_url":"https:\/\/liveapi.com\/blog\/wp-content\/uploads\/2026\/09\/Video-Player-02.jpg","yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.6.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<meta name=\"description\" content=\"Learn what low latency HLS is, how LL-HLS partial segments and blocking playlist reload work, real latency numbers, and how to implement it.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/liveapi.com\/blog\/low-latency-hls\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Low Latency HLS (LL-HLS): How It Works and How to Use It - LiveAPI Blog\" \/>\n<meta property=\"og:description\" content=\"Learn what low latency HLS is, how LL-HLS partial segments and blocking playlist reload work, real latency numbers, and how to implement it.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/liveapi.com\/blog\/low-latency-hls\/\" \/>\n<meta property=\"og:site_name\" content=\"LiveAPI Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-09T02:48:55+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-09T06:21:33+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/liveapi.com\/blog\/wp-content\/uploads\/2026\/09\/Video-Player-02.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2500\" \/>\n\t<meta property=\"og:image:height\" content=\"1308\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"18 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/liveapi.com\/blog\/#website\",\"url\":\"https:\/\/liveapi.com\/blog\/\",\"name\":\"LiveAPI Blog\",\"description\":\"Live Video Streaming API Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/liveapi.com\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/liveapi.com\/blog\/low-latency-hls\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/liveapi.com\/blog\/wp-content\/uploads\/2026\/09\/Video-Player-02.jpg\",\"width\":2500,\"height\":1308,\"caption\":\"Video Player\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/liveapi.com\/blog\/low-latency-hls\/#webpage\",\"url\":\"https:\/\/liveapi.com\/blog\/low-latency-hls\/\",\"name\":\"Low Latency HLS (LL-HLS): How It Works and How to Use It - LiveAPI Blog\",\"isPartOf\":{\"@id\":\"https:\/\/liveapi.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/liveapi.com\/blog\/low-latency-hls\/#primaryimage\"},\"datePublished\":\"2026-09-09T02:48:55+00:00\",\"dateModified\":\"2026-09-09T06:21:33+00:00\",\"author\":{\"@id\":\"https:\/\/liveapi.com\/blog\/#\/schema\/person\/98f2ee8b3a0bd93351c0d9e8ce490e4a\"},\"description\":\"Learn what low latency HLS is, how LL-HLS partial segments and blocking playlist reload work, real latency numbers, and how to implement it.\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/liveapi.com\/blog\/low-latency-hls\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/liveapi.com\/blog\/#\/schema\/person\/98f2ee8b3a0bd93351c0d9e8ce490e4a\",\"name\":\"govz\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/liveapi.com\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ab5cbe0543c0a44dc944c720159323bd001fc39a8ba5b1f137cd22e7578e84c9?s=96&d=mm&r=g\",\"caption\":\"govz\"},\"sameAs\":[\"https:\/\/liveapi.com\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/posts\/1298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/comments?post=1298"}],"version-history":[{"count":2,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/posts\/1298\/revisions"}],"predecessor-version":[{"id":1306,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/posts\/1298\/revisions\/1306"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/media\/1305"}],"wp:attachment":[{"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/media?parent=1298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/categories?post=1298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/liveapi.com\/blog\/wp-json\/wp\/v2\/tags?post=1298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}