HLS and DASH Ladders for Owned Players
Brand sites still ship one 1080p MP4. A six-rung HLS and DASH ladder, aligned keyframes, CMAF, and loudness so the owned player matches the social encode.
Brand sites still drop a single 1080p MP4 into a video tag and then wonder why phones rebuffer. An owned player is a streaming surface. It needs a bitrate ladder, aligned keyframes, CMAF fragments, and a loudness target, the same way a social encode needs a spec.
Social platforms re-encode whatever you give them. Your site plays what you ship. That is the whole difference, and it is why a ladder on the brand player is not optional polish. It is the encode.
One 1080p MP4 is not a player
A 1080p progressive MP4 is a reasonable mezzanine child for download, for a desktop on office wifi, and for a producer who wants to "just put it on the page." It is a poor default for a phone on a cell network. The player has one rung to pick. It cannot step down. It rebuffers, or it never starts.
HLS (HTTP Live Streaming) and MPEG-DASH are how a player is given a choice: a ladder of bitrates and resolutions, described by a playlist (HLS) or an MPD (DASH), with the player switching rungs as bandwidth changes. The HLS authoring specification for Apple devices is the named document for the HLS side. DASH is ISO/IEC 23009-1. You do not need two sets of media files.
Picking the right format for each platform is the social-and-aspect-ratio version of this decision. This article is the owned-player version: same show, multiple rungs, one origin.
Do not confuse this with a Reels spec. Instagram Reels encoding is an ingest envelope the app will re-encode. An owned player will not save you. If you ship one file, that is the file.
A six-rung ladder from a named spec
Apple's HLS authoring specification, section 1.25, publishes example bitrate variants. It is one possible set, not a law, and the appendix is explicit that codec, encoder, resolution, frame rate, and content all move the number. Generated footage with a grain pass is harder to encode than a talking head. Start from the table, then watch the high rung on a phone.
A six-rung ladder taken from Apple's 16:9 H.264 examples, dropping the duplicate 768×432 and the extra 720p:
| Rung | Resolution | Video bitrate (kbps) | Frame rate |
|---|---|---|---|
| 1 | 416×234 | 145 | ≤ 30 fps |
| 2 | 640×360 | 365 | ≤ 30 fps |
| 3 | 768×432 | 730 | ≤ 30 fps |
| 4 | 960×540 | 2,000 | Same as source |
| 5 | 1,280×720 | 3,000 | Same as source |
| 6 | 1,920×1,080 | 6,000 | Same as source |
That is H.264/AVC. If you also offer HEVC, Apple's spec wants SDR still present for backward compatibility, and the HEVC rungs sit beside the AVC ones rather than replacing the bottom of the ladder.
Keep the aspect ratio identical across rungs. The ladder is not the place to mix 16:9 and 9:16. If the owned player needs a vertical crop, encode a second ladder from a vertical mezzanine, which is the same argument as generate vertical natively or reframe afterwards.
Apple's VOD rule on peaks: for VOD content, the peak bit rate SHOULD be no more than 200 percent of the average bit rate. Constraint that in the encoder. A grainy generated shot will want the average up before it wants the peak up; raising the peak without moving the average is how you get a ladder that looks good in Mediainfo and still falls apart on a phone.
Resolution on the top rung should match the sequence, not an upscale you invented for the player. If the show is 1080p, rung 6 is 1080p. A 720p generation does not become a 1080p rung without an upscale you have already decided to pay for.
The browser-side video file size calculator will not build a ladder, but it will stop you guessing whether six rungs fit on the origin before you encode them.
Aligned keyframes and CMAF
Switching rungs only works if the pictures line up.
Closed GOP, aligned IDR. Every rung uses the same GOP duration, and every fragment starts with an IDR. Two seconds is a working default: at 25fps that is a keyframe every 50 frames; at 24fps, every 48. A player can only switch at a fragment boundary. If rung 6 has a keyframe where rung 3 does not, the switch stalls or shows a freeze.
Same frame rate across the video rungs you expect to switch between. Apple allows different variants to use different frame rates. For an owned brand player, do not. Mix 25 and 30 and the cadence pops at every switch, which is the same defect frame rate mismatches cause in a timeline. Versely timelines default to 25fps. Encode the ladder at the sequence rate.
CMAF fragments, one set of files. CMAF (Common Media Application Format, ISO/IEC 23000-19) packages fMP4 fragments that both HLS media playlists and a DASH MPD can point at. You encode once. Safari can play the HLS presentation natively. dash.js or a DASH-capable player can play the same fragments from the MPD. Dual packaging as transport-stream HLS plus a separate DASH encode is how you pay twice and drift.
Audio as its own rendition. Apple's authoring spec puts stereo AAC in a band of 32–160 kbps. One stereo AAC-LC rendition is enough for a brand film. Do not build a six-rung audio ladder. Keep audio in a separate CMAF track so a video-rung switch does not re-initialise the sound.
Encode from the mezzanine, not from a social MP4. A ladder made from an already-compressed 8-bit 4:2:0 file is six rungs of the same artefacts.
Audio loudness on the owned stream
The owned player will not loudness-normalise for you the way some social apps do on ingest. What you mix is what plays next to the rest of the site, and next to the last video the viewer watched.
Mix to a documented target and put it in the delivery note. EBU R 128 is the broadcast document: programme loudness −23.0 LUFS, true peak at or below −1 dBTP, with the standard's own tolerances. For short-form, R 128 s1 is the supplement. If the site is not a broadcaster, you can still mix to R128 and be able to say which number you hit. Community-measured platform figures such as "−14 LUFS for YouTube" are not a substitute for a published target; loudness normalization is the longer version of that distinction.
True peak stays at or below −1 dBTP regardless of the integrated number. AAC after a hot mix is how you pass a loudness meter and still clip in the player.
Do the loudness pass on the mezzanine mix, then encode every rung from that mix. Do not loudness-correct the 1080p rung and forget the 540p. They share audio, so they share the mix, which is another reason audio lives in its own rendition.
A ship checklist for the owned player:
- Mezzanine locked: picture legal, grain set, mix at the stated LUFS and dBTP.
- Six video rungs from the table, same aspect, same frame rate, closed GOP, IDR on a two-second cadence, peak ≤ 2× average.
- One stereo AAC rendition, 32–160 kbps as Apple bounds it.
- CMAF fragments. HLS playlist plus DASH MPD pointing at the same files.
- Play the bottom rung on a phone radio and the top rung on desktop. Confirm the switch is invisible. Confirm the mix is not quiet next to the rest of the site.
The Versely editor will not package HLS. Assemble the cut there, export once (the editor's preview: true pass is 480p with a short per-user cooldown; the charged export is the source), transcode to a mezzanine, then run the ladder from that file. A single 1080p MP4 on the site is the step this whole article exists to retire.
FAQ
Do I need both HLS and DASH if Safari plays HLS natively?
You need HLS for Safari. You need DASH or HLS-via-MSE for a lot of the rest of the web. CMAF is how those are one encode. Shipping only HLS is defensible if you have tested the actual browsers on the brand's traffic. Shipping only a progressive MP4 is not the same defence.
Can I offer four rungs instead of six?
Yes, if you keep the bottom and the top. Dropping the 234p and 360p rungs is how a phone on a bad cell never starts. Dropping 1080p is how a desktop looks soft. A four-rung ladder of 360 / 540 / 720 / 1080 is a known compromise. A two-rung ladder of 1080 and 720 is the original problem with extra steps.
Should grain change the bitrates in the table?
It can, because grain is expensive to encode. Apple's table is a starting point and the appendix says content is one of the things that moves the number. If the 1080p rung shows smeared texture on a phone, raise that rung's average before you raise the peak. Do not invent a multiplier. Measure that encode.
Does this replace platform-specific social encodes?
No. Reels, Shorts, TikTok, and YouTube still get the files those ingest specs ask for. The owned player gets the ladder. They share a mezzanine. They do not share an encode.