Tutorial · DASH · MP4

DASH MPD Downloader: Save .mpd Streams to MP4 in 2026

DASH is not HLS. A .mpd manifest always splits video and audio into separate tracks, uses XML instead of plain text, and can span dozens of quality levels. Here is how to merge everything into a single MP4 with three methods.

By the Vidora team 10 min read

Updated 2026-05-10: Refreshed for the latest DASH detection methods and Vidora extension v2 with 1080p quality cap and automatic audio muxing.

Quick answer

To download a DASH .mpd stream as MP4 in 2026, you parse the manifest XML to find the highest-bitrate video AdaptationSet plus the audio AdaptationSet, fetch all video and audio segments, then mux them together. The Vidora Chrome extension does this automatically with a 1080p quality cap. Alternatively, use ffmpeg with -i for the .mpd URL or yt-dlp which natively understands DASH and merges tracks via ffmpeg under the hood.

Most video downloader guides focus on HLS. DASH gets less coverage even though it powers a significant share of browser video delivery in 2026. The two protocols are cousins: both slice a video into small segments fetched over plain HTTP, both use a manifest to describe the available quality levels, and both separate audio from video in adaptive configurations. But the implementation details differ enough that tools built for .m3u8 playlists often fail silently on .mpd manifests.

This guide covers the three methods that work on DASH streams in 2026 and explains the structural reasons one approach might fail where another succeeds. We focus on legitimate use: archiving your own recordings, saving content you have legally purchased, or downloading streams you have explicit permission to capture. DRM-protected streams are out of scope.

1. Quick context: DASH vs HLS, why .mpd is different

HLS (HTTP Live Streaming) uses .m3u8 playlists, which are plain text files with one URL per line. DASH (Dynamic Adaptive Streaming over HTTP) uses .mpd files, which are XML documents that can be hundreds of lines long and describe multiple Periods, AdaptationSets, Representations, and SegmentTemplates in a nested tree structure.

The most important structural difference for downloaders: DASH always uses separate AdaptationSets for video and audio. A typical .mpd snippet looks like this:

<MPD type="static" mediaPresentationDuration="PT30M">
  <Period>
    <AdaptationSet contentType="video">
      <Representation id="v1" bandwidth="5000000" width="1920" height="1080"
                      codecs="avc1.640028">
        <SegmentTemplate media="video-$Number$.m4s" initialization="video-init.mp4"
                         startNumber="1" duration="4" timescale="1" />
      </Representation>
      <Representation id="v2" bandwidth="2500000" width="1280" height="720" ... />
    </AdaptationSet>
    <AdaptationSet contentType="audio">
      <Representation id="a1" bandwidth="128000" codecs="mp4a.40.2">
        <SegmentTemplate media="audio-$Number$.m4s" initialization="audio-init.mp4"
                         startNumber="1" duration="4" timescale="1" />
      </Representation>
    </AdaptationSet>
  </Period>
</MPD>

A downloader that only follows the video AdaptationSet produces a file with no audio track. A downloader that does not understand SegmentTemplate (as opposed to SegmentList) will miss all the segment URLs entirely. These two failure modes account for the majority of broken DASH downloads.

The other key difference: DASH segments are typically .m4s (fragmented MP4 init + media segments) rather than .ts. The first segment for each track is an initialization segment that contains the codec parameters. Without it, the rest of the segments cannot be decoded.

HLS and DASH also handle encrypted streams differently. HLS uses AES-128 keys declared in the playlist. DASH typically uses CENC (Common Encryption) with Widevine or PlayReady license servers, which is a fully different mechanism. Our guide on encrypted streams covers AES-128 in depth for HLS. For DASH with DRM, the Troubleshooting section below explains what you are up against.

For finding any manifest URL, whether .m3u8 or .mpd, the same DevTools approach works: open the Network tab, filter by the extension or by XHR, press play, and look for the request. Our guide on how to find the m3u8 URL walks through each DevTools step in detail - the same DevTools approach works for .mpd files, just filter for "mpd" instead of "m3u8".

2. Method 1: Browser extension (one click)

A browser extension intercepts network requests from inside your browser session. It sees the same .mpd manifest the player fetches, has access to your session cookies and auth headers, and can parse the manifest client-side before handing the segment URLs to a parallel downloader. For DASH, this solves two problems at once: authentication and manifest parsing.

Step-by-step with Vidora

  1. Install Vidora from the Chrome Web Store. Works on Chrome, Edge, Brave, Opera, Vivaldi, and any Chromium-based browser.
  2. Navigate to the page hosting the video. Press play once so the player fetches the .mpd manifest. Vidora intercepts the request automatically via the webRequest API.
  3. Click the Vidora icon in the toolbar. The popup lists the detected streams. For DASH, Vidora shows available video quality levels and confirms audio is included.
  4. Select your quality (capped at 1080p for most streams) and click Download. Vidora fetches the initialization segment, then all media segments for both video and audio tracks in parallel, and muxes them into a single MP4.

The output uses the original codecs, no re-encoding. Initialization segments are fetched first so the container is valid from the first byte. A 45-minute 1080p DASH stream is typically downloaded and muxed in 3 to 6 minutes on a normal broadband connection.

Trade-offs

3. Method 2: ffmpeg with input piping

ffmpeg has supported DASH input since version 3.x and can parse .mpd manifests natively. You point it at the manifest URL the same way you would point it at an .m3u8. The difference is what happens internally: ffmpeg reads the XML, selects the best Representation in each AdaptationSet it finds, downloads all segments in sequence, and muxes them into the output container.

The minimal command

ffmpeg -i "https://cdn.example.com/manifest.mpd" -c copy output.mp4

The -c copy flag is critical: it tells ffmpeg to mux the segments without re-encoding. The output keeps the original bitrate, the process finishes in download time rather than CPU time, and there is no quality loss.

Selecting a specific quality level

By default ffmpeg picks the highest bitrate. To cap at a specific resolution, use -vf with a scale filter - but this forces a re-encode. For quality selection without re-encoding, the cleaner approach is to extract the specific Representation URL from the .mpd manually and use yt-dlp's format selection (covered in Method 3).

The realistic command (for streams that require auth)

If the .mpd URL is behind a session or requires a Referer, capture both from DevTools and pass them to ffmpeg:

ffmpeg \
  -headers $'Referer: https://source.example.com/\r\nCookie: session=abc123\r\n' \
  -i "https://cdn.example.com/manifest.mpd" \
  -c copy \
  output.mp4

Note that for DASH, the -headers flag applies to the manifest request and to all subsequent segment requests. ffmpeg propagates the headers through the entire download chain.

When ffmpeg is the right choice

For DASH specifically, converting m3u8 to mp4 and converting an .mpd to MP4 use the same ffmpeg flag - the protocol handler is different internally but the user command is identical. The comparison with HLS is covered in our convert m3u8 to mp4 guide.

4. Method 3: yt-dlp with --merge-output-format mp4

yt-dlp is a command-line downloader that understands DASH natively. For sites it supports directly, it handles manifest discovery, format selection, segment downloading, and muxing automatically. For generic DASH URLs it can pass through to ffmpeg. It is the fastest option when it works and the most feature-rich for format selection.

Basic usage for a supported site

yt-dlp --merge-output-format mp4 "https://example.com/watch?v=VIDEO_ID"

yt-dlp selects the best available format (combining the best video stream and the best audio stream from separate DASH AdaptationSets), downloads them in parallel, and invokes ffmpeg to mux the result into an MP4.

Selecting a specific quality cap

# Download the best video up to 1080p, merged with best audio
yt-dlp -f "bestvideo[height<=1080]+bestaudio" \
       --merge-output-format mp4 \
       "https://example.com/watch?v=VIDEO_ID"

Using yt-dlp with a raw .mpd URL

For generic DASH streams (not a site yt-dlp recognizes), pass the .mpd URL directly:

yt-dlp --merge-output-format mp4 \
       --add-header "Referer:https://source.example.com/" \
       "https://cdn.example.com/manifest.mpd"

yt-dlp vs ffmpeg for DASH

5. Comparison table (HLS vs DASH approaches)

DASH and HLS share a lot of tooling but differ in key behaviors. Here is a side-by-side for the three methods across both protocols:

Criterion Browser extension
(HLS + DASH)
ffmpeg
(HLS + DASH)
yt-dlp
(HLS + DASH)
Setup time2 minutes15 minutes10 minutes
Auth / cookiesAutomatic (session)Manual (-headers)--cookies-from-browser
Audio + video muxYes (transparent)Yes (automatic with -c copy)Yes (requires ffmpeg)
HLS AES-128 encryptedYesYesYes
DASH CENC/Widevine DRMNoNoNo
Quality selectionVia popup listAuto (highest) or manual-f format selector
Batch supportManualShell script--batch-file
No re-encodingYes (default)Yes (with -c copy)Yes (default)
Private stream supportYesYes (with captured headers)Partial

For casual downloads from a browser, the extension wins on convenience. For batch work or scripting, ffmpeg and yt-dlp are more practical. For DASH streams behind a login that neither ffmpeg nor yt-dlp can authenticate against, the browser extension is the only option that works without exporting session cookies manually.

If the stream you are trying to capture is HLS rather than DASH, the same principles apply - see our HLS downloader Chrome extension guide and the free m3u8 downloader tools overview for the HLS-specific landscape.

6. Troubleshooting (separate tracks, codec mismatch, DRM)

Silent output - no audio track

The downloader only fetched the video AdaptationSet. With ffmpeg, this happens when a custom script grabs individual Representation URLs instead of the full .mpd. Fix: pass the .mpd URL directly to ffmpeg, not individual .m4s segment URLs. With yt-dlp, use bestvideo+bestaudio format selection. With Vidora, audio muxing is handled automatically.

Codec mismatch - video and audio are out of sync

The video and audio AdaptationSets have different segment durations or different timescales. This is a manifest authoring bug on the server side. In ffmpeg, you may need to add -async 1 or -af aresample=async=1000 to resync. If the drift is large, report it as a stream issue rather than a downloader issue.

Initialization segment missing - video plays but looks corrupted

The downloader skipped the initialization segment (usually named init.mp4 or video-init.mp4) and started with media segments directly. Without the init segment, the decoder has no codec configuration. Use a DASH-aware tool (ffmpeg, yt-dlp, Vidora) that fetches init segments first. Manually downloading .m4s files via wget and concatenating them without the init segment always fails.

403 Forbidden on segment requests after manifest loads

The segment URLs are signed or require a Referer that ffmpeg is not sending. Add -headers with the correct Referer and any required token. With yt-dlp, use --add-header. The browser extension inherits all headers automatically from the active session.

DASH DRM - encrypted stream, nothing works

If the .mpd contains a <ContentProtection> element referencing a Widevine (edef8ba9-79d6-4ace-a3c8-27dcd51d21ed) or PlayReady scheme, the stream is CENC-encrypted with a hardware-backed DRM. No open-source tool decrypts this legally. This is different from the AES-128 encryption used in some HLS streams (which is covered in our encrypted m3u8 guide). The segments you download will be encrypted blobs that no player can open without the license server key material.

Live DASH vs VOD DASH

A live DASH manifest has type="dynamic" instead of type="static". There is no mediaPresentationDuration and segments are continuously added. ffmpeg can record live DASH by following the manifest in a loop (the same way it handles live HLS). Vidora handles VOD DASH streams. For live capture of HLS, our live HLS stream capture guide covers the recording approach, which applies to live DASH as well with the same ffmpeg flags.

7. Frequently asked questions

What is a .mpd file?

A .mpd file (Media Presentation Description) is an XML manifest used by the DASH protocol. It describes all available video and audio quality levels, the segment URLs for each, and timing information. It is to DASH what a .m3u8 playlist is to HLS. Opening a .mpd in a text editor shows XML with AdaptationSet, Representation, and SegmentTemplate elements. The file itself contains no video data - it is a roadmap that tells the player where to find every chunk. For the HLS equivalent, see our M3U8 explainer.

Why does DASH split video and audio into separate streams?

DASH uses separate AdaptationSets for video and audio so each can adapt independently. The player can drop from 1080p to 720p without interrupting audio, or switch audio language without touching video. This is more efficient than replicating the audio track across every video quality level. For downloaders, it means you must explicitly fetch and mux both tracks. Any script that grabs individual .m4s segment URLs from only the video Representation will produce a silent output file.

Can I download DASH streams with ffmpeg?

Yes. ffmpeg has native DASH support. Run ffmpeg -i https://cdn.example.com/manifest.mpd -c copy output.mp4 and ffmpeg parses the XML, fetches the highest-bitrate video and audio streams, downloads all segments in order, and muxes them into a single MP4 without re-encoding. Add -headers to pass authentication cookies or a Referer if the CDN requires them. ffmpeg is also how you would convert m3u8 to mp4 - the flag syntax is identical.

Why does my DASH download have no audio?

The downloader fetched only the video AdaptationSet and ignored the audio one. This happens most often with scripts that enumerate individual Representation URLs instead of passing the full .mpd to a DASH-aware tool. Fix: use ffmpeg with the .mpd URL directly, yt-dlp with bestvideo+bestaudio format selection, or Vidora which muxes both automatically. If audio is still missing, check whether the audio codec (sometimes EC-3/Dolby) is unsupported by your player rather than absent from the file.

Are DASH streams DRM-protected?

Some are, some are not. DASH is a delivery protocol - DRM is an optional encryption layer applied on top. A .mpd that contains a <ContentProtection> element referencing Widevine or PlayReady is DRM-protected. The encrypted segments you download are unplayable without the license server's key material, which is only accessible inside a hardware-backed Trusted Execution Environment. No open-source tool decrypts these legally. Many DASH streams (conference recordings, self-hosted webinars, non-DRM courses) have no ContentProtection element and can be downloaded freely with the methods above. Bunny.net CDN-hosted streams, for example, often use DASH or HLS without DRM - see our Bunny.net video downloader guide for more detail.

What is the difference between DASH and HLS in practice for downloading?

Both use small HTTP segments, both separate audio from video in adaptive streams, and both are supported by ffmpeg and yt-dlp. The practical differences: (1) DASH manifests are XML and more verbose, so custom parsers fail more often. (2) DASH segments are typically .m4s (fragmented MP4) rather than .ts, and require an init segment. (3) DASH encryption (CENC/Widevine) is harder to work around than HLS AES-128 encryption. For most use cases the tooling is interchangeable. Compare the two protocol approaches in our convert m3u8 to mp4 guide.

About the author

RGC Digital LLC builds Vidora, a Pro video downloader Chrome extension for Vimeo, Bunny.net, HLS streams, DASH streams, and MP4. Based in Albuquerque, NM. We write about video tooling, streaming protocols, and Chrome extension engineering.

Related guides

V

Vidora Engineering

Vidora is built and maintained by RGC Digital LLC, a team of engineers who have been working on browser-based HLS, DASH and MP4 video extraction since 2024. We test every method we publish on real streams from Vimeo, Bunny.net, Wistia, Apple HLS samples, AES-128 encrypted CDNs, and generic DASH manifests.