All posts
StreamingHLS15 Oct 2026 · 3 min read

DASH and HLS side by side

Take one HLS master playlist and one DASH MPD for the same video and put them next to each other. They say almost the same thing. Both list a ladder of renditions, both point at short segments, both leave the choice of rung to the player. The difference is the shape of the document, and that shape decides what each format is good at.

One hierarchy, two ways to write it

HLS is flat and line-based. A master playlist is a list of #EXT-X-STREAM-INF entries, each carrying BANDWIDTH (required) and usually RESOLUTION (optional) and followed by the URL of a media playlist. Each media playlist is a list of #EXTINF durations and segment URLs. Two levels, plain text.

DASH is a tree in XML. The root MPD holds one or more Period elements, a Period holds AdaptationSet elements, and an AdaptationSet holds Representation elements. The levels narrow the choice in order: a Period in time, an AdaptationSet by kind of content (video, or audio in one language), a Representation by bitrate. bandwidth lives on the Representation because it describes one encoded rung.

HLS                          DASH
master.m3u8                  manifest.mpd
  #EXT-X-STREAM-INF            Period
    720p.m3u8                    AdaptationSet (video)
    360p.m3u8                      Representation 720p
                                   Representation 360p
                                 AdaptationSet (audio)
                                   Representation aac

The audio line is where the layouts diverge. HLS ties audio to video with #EXT-X-MEDIA groups, DASH gives audio its own AdaptationSet. Same idea, different place to look for it.

Templates instead of lists

An HLS media playlist names every segment. A DASH Representation's segments are usually described by a template instead: a SegmentTemplate, often set on the AdaptationSet, with a URL pattern holding $RepresentationID$ and $Number$ (or $Time$) and, unless a SegmentTimeline is used, a duration. The player works out segment 37 by substituting, without being told. For streams where segment lengths vary, a SegmentTimeline lists runs of segments as start, duration and repeat count. The lab's inspector annotates each of these elements when you hover it, including the case where a repeat count of -1 means "until the next entry or the end of the Period".

There is also SegmentList, which lists every URL explicitly like an HLS playlist does. The lab's own note on it says it is simple and that the MPD grows with the content.

CMAF is why you can stop choosing

The real cost of supporting both used to be that DASH wanted fragmented MP4 while HLS, until it added fMP4 in 2016, meant MPEG-TS in practice. CMAF settled the container: an init segment with ftyp and moov carrying the codec configuration, then media segments made of moof and mdat pairs. HLS accepts fMP4 segments, so one set of files on the CDN can sit behind an .m3u8 and an .mpd at once. Only the manifests differ, and they are small. That holds for clear content. Encrypted content needs the same scheme (cbcs) for both formats, otherwise you encrypt and store separate copies.

The same split gives you low latency. A CMAF segment can be cut into chunks, each its own moof and mdat, delivered with chunked transfer while the segment is still being written. In LL-DASH the MPD announces segments early with availabilityTimeOffset. LL-HLS reaches for the same chunks through partial segments. The Low-Latency DASH lesson's example command uses 2 s segments with a fragment every 0.5 s (-frag_duration 0.5) and a 3 s -target_latency.

Periods are a DASH habit

HLS expresses a break in continuity with #EXT-X-DISCONTINUITY. DASH makes it structural. A new Period is a new timeline with its own AdaptationSets, which suits ad insertion and encoder restarts: a programme Period, a short ad Period with its own ladder and segment length, and the programme again. Events ride alongside, either in an EventStream in the MPD or in emsg boxes inside segments, which is how a SCTE-35 cue announces a break. A period-continuity property tells the player that a Period continues the media timeline of an earlier one, so it can skip the reset.

The DASH Lab has a stream preset for exactly this, a DASH-IF test stream that starts a new Period every minute. The guided step for it asks you to watch init segments get fetched again, the segment counter reset, and a Period switch line show up in the Log tab. The other tabs beside it are MPD, Segments, Boxes and FFMPEG, and the MPD tab has a Diff view that highlights lines that changed since the last fetch, which is how you see a live manifest move.

The lab plays public test streams in your browser. Reading a manifest is the quickest way to learn what a player will do, and the multi-period one is where I would start.