#video #streaming #mpd #dash #mpeg

dash-mpd

Parse and fetch an MPD manifest for MPEG-DASH or WebM-DASH media streaming

10 unstable releases (3 breaking)

Uses new Rust 2021

new 0.4.5 Jul 2, 2022
0.4.3 May 16, 2022
0.4.2 Mar 19, 2022
0.3.0 Dec 28, 2021
0.1.0 Nov 28, 2021

#44 in Video

Download history 60/week @ 2022-03-15 27/week @ 2022-03-22 9/week @ 2022-03-29 15/week @ 2022-04-05 6/week @ 2022-04-12 8/week @ 2022-04-19 46/week @ 2022-04-26 46/week @ 2022-05-03 133/week @ 2022-05-10 49/week @ 2022-05-17 47/week @ 2022-05-24 110/week @ 2022-05-31 26/week @ 2022-06-07 12/week @ 2022-06-14 9/week @ 2022-06-21 27/week @ 2022-06-28

86 downloads per month
Used in dash-mpd-cli

MIT license

125KB
2K SLoC

dash-mpd

A Rust library for parsing and downloading media content from a DASH MPD file, as used by video services such as on-demand replay of TV content and video streaming services like YouTube.

Crates.io Released API docs CI Dependency status LICENSE

DASH (dynamic adaptive streaming over HTTP), also called MPEG-DASH, is a technology used for media streaming over the web, commonly used for video on demand (VOD) services. The Media Presentation Description (MPD) is a description of the resources (manifest or “playlist”) forming a streaming service, that a DASH client uses to determine which assets to request in order to perform adaptive streaming of the content. DASH MPD manifests can be used both with content encoded as MPEG and as WebM. There is a good explanation of adaptive bitrate video streaming at howvideo.works.

This library provides a serde-based parser for the DASH MPD format, as formally defined in ISO/IEC standard 23009-1:2019. XML schema files are available for no cost from ISO. When MPD files in practical use diverge from the formal standard, this library prefers to interoperate with existing practice.

The library also provides experimental support for downloading content (audio or video) described by an MPD manifest. This involves selecting the alternative with the most appropriate encoding (in terms of bitrate, codec, etc.), fetching segments of the content using HTTP or HTTPS requests (this functionality depends on the reqwest crate) and muxing audio and video segments together.

If the library feature libav is enabled, muxing support (combining audio and video streams, which are often separated out in DASH streams) is provided by ffmpeg’s libav library, via the ac_ffmpeg crate. Otherwise, muxing is implemented by calling ffmpeg as a subprocess. The ffmpeg commandline application implements a number of checks and workarounds to fix invalid input streams that tend to exist in the wild. Some of these workarounds, but not all, are implemented here when using libav as a library, so download support tends to be more robust with the default configuration (using ffmpeg as a subprocess).

DASH features supported

  • VOD (static) stream manifests
  • Multi-period content
  • XLink elements (only with actuate=onLoad semantics), including resolve-to-zero
  • All forms of segment index info: SegmentBase@indexRange, SegmentTimeline, SegmentTemplate@duration, SegmentTemplate@index, SegmentList
  • Media containers of types supported by ffmpeg or VLC (this includes ISO-BMFF / CMAF / MP4, WebM, MPEG-2 TS)

Limitations / unsupported features

  • Dynamic MPD manifests, that are used for live streaming/OTT TV
  • Encrypted content using DRM such as Encrypted Media Extensions (EME) and Media Source Extension (MSE)
  • Subtitles (eg. WebVTT and TTML streams)
  • XLink with actuate=onRequest

Usage

use std::time::Duration;
use dash_mpd::{MPD, parse};

fn main() {
    let client = reqwest::blocking::Client::builder()
        .timeout(Duration::new(10, 0))
        .gzip(true)
        .build()
        .expect("Couldn't create reqwest HTTP client");
    let xml = client.get("http://rdmedia.bbc.co.uk/dash/ondemand/testcard/1/client_manifest-events.mpd")
        .header("Accept", "application/dash+xml,video/vnd.mpeg.dash.mpd")
        .send()
        .expect("Requesting MPD content")
        .text()
        .expect("Fetching MPD content");
    let mpd: MPD = parse(&xml)
        .expect("parsing MPD");
    if let Some(pi) = mpd.ProgramInformation {
        if let Some(title) = pi.Title {
            println!("Title: {:?}", title.content);
        }
        if let Some(source) = pi.Source {
            println!("Source: {:?}", source.content);
        }
    }
    for p in mpd.periods {
        if let Some(d) = p.duration {
            println!("Contains Period of duration {:?}", d);
        }
    }
}

The experimental support for downloading content from an MPD manifest:

use dash_mpd::fetch::DashDownloader;

let url = "https://storage.googleapis.com/shaka-demo-assets/heliocentrism/heliocentrism.mpd";
match DashDownloader::new(url)
       .worst_quality()
       .download()
{
   Ok(path) => println!("Downloaded to {:?}", path),
   Err(e) => eprintln!("Download failed: {:?}", e),
}

An application that provides a commandline interface for this library is available separately in the dash-mpd-cli crate.

Installation

Add to your Cargo.toml file:

[dependencies]
dash-mpd = "0.4"

Platforms

This crate is tested on the following platforms:

  • Linux, with default features (ffmpeg or vlc as a subprocess) and libav support
  • MacOS, only with default features (problems building the ac-ffmpeg crate against current ffmpeg)
  • Microsoft Windows 10, only with default features
  • Android 11 on Aarch64 via termux (you'll need to install the rust, binutils and ffmpeg packages)

License

This project is licensed under the MIT license. For more information, see the LICENSE-MIT file.

Dependencies

~5–15MB
~328K SLoC