{"id":13617610,"url":"https://github.com/emarsden/dash-mpd-rs","last_synced_at":"2025-12-29T23:47:46.956Z","repository":{"id":41306566,"uuid":"432687882","full_name":"emarsden/dash-mpd-rs","owner":"emarsden","description":"Rust library for parsing, serializing and downloading media content from a DASH MPD manifest.","archived":false,"fork":false,"pushed_at":"2024-10-29T08:02:54.000Z","size":1016,"stargazers_count":72,"open_issues_count":3,"forks_count":23,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-10-29T09:20:44.881Z","etag":null,"topics":["dash","mpeg","mpeg-dash","rust","streaming-video"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emarsden.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-28T11:02:25.000Z","updated_at":"2024-10-29T08:02:09.000Z","dependencies_parsed_at":"2024-11-06T08:26:53.060Z","dependency_job_id":"455cba96-64e4-4919-8dc0-fa19ac8600a5","html_url":"https://github.com/emarsden/dash-mpd-rs","commit_stats":{"total_commits":267,"total_committers":5,"mean_commits":53.4,"dds":0.1235955056179775,"last_synced_commit":"bab966a0f6ba287d26e1ffc32cbba798a0bbfef7"},"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarsden%2Fdash-mpd-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarsden%2Fdash-mpd-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarsden%2Fdash-mpd-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emarsden%2Fdash-mpd-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emarsden","download_url":"https://codeload.github.com/emarsden/dash-mpd-rs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223621903,"owners_count":17174781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dash","mpeg","mpeg-dash","rust","streaming-video"],"created_at":"2024-08-01T20:01:44.661Z","updated_at":"2025-12-29T23:47:46.951Z","avatar_url":"https://github.com/emarsden.png","language":"Rust","funding_links":[],"categories":["HarmonyOS","Rust","Protocols \u0026 Transport"],"sub_categories":["Windows Manager","DASH Manifest Tools"],"readme":"# dash-mpd\n\nA Rust library for parsing, serializing and downloading media content from a DASH MPD file, as used\nby video services such as on-demand replay of TV content and video streaming services like YouTube.\nAllows both parsing of a DASH manifest (XML format) to Rust structs (deserialization) and\nprogrammatic generation of an MPD manifest (serialization). The library also allows you to download\nmedia content from a streaming server.\n\n[![Crates.io](https://img.shields.io/crates/v/dash-mpd)](https://crates.io/crates/dash-mpd)\n[![Released API docs](https://docs.rs/dash-mpd/badge.svg)](https://docs.rs/dash-mpd/)\n[![CI](https://github.com/emarsden/dash-mpd-rs/workflows/build/badge.svg)](https://github.com/emarsden/dash-mpd-rs/actions/workflows/ci.yml)\n[![Dependency status](https://deps.rs/repo/github/emarsden/dash-mpd-rs/status.svg)](https://deps.rs/repo/github/emarsden/dash-mpd-rs)\n[![Recent crates.io downloads](https://img.shields.io/crates/dr/dash-mpd?label=crates.io%20recent%20downloads)](https://crates.io/crates/dash-mpd)\n[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT)\n\n[DASH](https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP) (dynamic adaptive\nstreaming over HTTP), also called MPEG-DASH, is a technology used for media streaming over the web,\ncommonly used for video on demand (VOD) services. The Media Presentation Description (MPD) is a\ndescription of the resources (manifest or “playlist”) forming a streaming service, that a DASH\nclient uses to determine which assets to request in order to perform adaptive streaming of the\ncontent. DASH MPD manifests can be used both with content encoded as H.264/MPEG and as WebM, and\nwith file segments using either MPEG-2 Transport Stream (M2TS) container format or fragmented MPEG-4\n(also called CFF). There is a good explanation of adaptive bitrate video streaming at\n[howvideo.works](https://howvideo.works/#dash).\n\nThis library provides a serde-based parser (deserializer) and serializer for the DASH MPD format, as\nformally defined in ISO/IEC standard 23009-1:2022 (this is the fifth edition). XML schema files are\n[available for no cost from\nISO](https://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/). The library\nalso provides non-exhaustive support for certain DASH extensions such as the DVB-DASH and HbbTV\n(Hybrid Broadcast Broadband TV) profiles. When MPD files in practical use diverge from the formal\nstandard(s), this library prefers to interoperate with existing practice.\n\nIf the library feature `fetch` is enabled (which it is by default), the library also provides\nsupport for downloading content (audio or video) described by an MPD manifest. This involves\nselecting the alternative with the most appropriate encoding (in terms of bitrate, codec, etc.),\nfetching segments of the content using HTTP or HTTPS requests (this functionality depends on the\n`reqwest` crate) and muxing audio and video segments together.\n\nMuxing (merging audio and video streams, which are often published separately in DASH media streams)\nis implemented by calling an external commandline application, either mkvmerge (from the\n[MkvToolnix](https://mkvtoolnix.download/) suite), [ffmpeg](https://ffmpeg.org/),\n[vlc](https://www.videolan.org/vlc/) or [MP4Box](https://github.com/gpac/gpac/wiki/MP4Box). The\nchoice of external muxer depends on the filename extension of the path supplied to `download_to()`\n(will be `.mp4` if you call `download()`):\n\n- `.mkv`: call mkvmerge first, then if that isn't installed or fails call ffmpeg, then try MP4Box\n- `.mp4`: call ffmpeg first, then if that fails call vlc, then try MP4Box\n- `.webm`: call vlc, then if that fails ffmpeg\n- other: try ffmpeg, which supports many container formats, then try MP4Box\n\nYou can specify a different order of preference for muxing applications using the\n`with_muxer_preference` method on DashDownloader. For example, `with_muxer_preference(\"avi\",\n\"vlc,ffmpeg\")` means that for an AVI media container the external muxer vlc will be tried first,\nthen ffmpeg in case of failure. This method option can be used multiple times to specify options for\ndifferent container types.\n\nIf the library feature `libav` is enabled, muxing is implemented using ffmpeg’s libav library, via\nthe `ac_ffmpeg` crate. This allows the library to work with fewer runtime dependencies. However,\nthese commandline applications implement a number of checks and workarounds to fix invalid input\nstreams that tend to exist in the wild. Some of these workarounds are implemented here when using\nlibav as a library, but not all of them, so download support tends to be more robust with the\ndefault configuration (using an external application as a subprocess).\n\n\n## DASH features supported\n\n- **Multi-period** content. The media in the different streams will be saved in a single media\n  container if the formats are compatible (same resolution, codecs, bitrate and so on) and\n  `concatenate_periods(false)` has not been called on DashDownloader, and otherwise in separate\n  media containers.\n\n- WebVTT/wvtt, TTML, STPP, SRT, tx3g and SMIL **subtitles**, either provided as a single media\n  stream or as a fragmented MP4 stream. Subtitles that are distributed as a single media stream will\n  be saved to a file with the same base name as the requested output file, but with an extension\n  corresponding to the subtitle type (e.g. `.srt`, `.vtt`). Subtitles distributed in WebVTT/wvtt\n  format (either as a single media stream or a fragmented MP4 stream) will be converted to the more\n  standard SRT format using the MP4Box commandline utility (from the [GPAC](https://gpac.io/)\n  project), if it is installed. STPP subtitles (which according to the DASH specifications should be\n  formatted as EBU-TT) will be muxed into the output media container as a `subt:stpp` stream using\n  MP4Box (VLC should be able to read these subtitles), and also converted to a separate `.ttml` file\n  using ffmpeg. If your media player doesn't support STPP/TTML subtitles, you can try using the\n  GPAC media player (available with `gpac -gui`).\n\n- Support for **decrypting** media streams that use MPEG Common Encryption (cenc) ContentProtection.\n  This requires either the `mp4decrypt` commandline application from the [Bento4\n  suite](https://github.com/axiomatic-systems/Bento4/) to be installed ([binaries are\n  available](https://www.bento4.com/downloads/) for common platforms), or the [Shaka\n  packager](https://github.com/shaka-project/shaka-packager) application (binaries for common\n  platforms are available as GitHub releases), or the MP4Box commandline application to be\n  installed. See the `add_decryption_key` function on `DashDownloader`, the\n  `with_decryptor_preference` function on `DashDownloader`, and the\n  [decrypt.rs](https://github.com/emarsden/dash-mpd-rs/blob/main/examples/decrypt.rs) example.\n\n- XLink elements (only with actuate=onLoad semantics), including resolve-to-zero.\n\n- All forms of segment index info: SegmentBase@indexRange, SegmentTimeline,\n  SegmentTemplate@duration, SegmentTemplate@index, SegmentList.\n\n- Media containers of types supported by mkvmerge, ffmpeg, VLC or MP4Box (this includes Matroska,\n  ISO-BMFF / CMAF / MP4, WebM, MPEG-2 TS), and all codecs supported by these applications.\n\n\n\n## Limitations / unsupported features\n\n- We can’t really download content from **dynamic MPD manifests**, that are used for live\n  streaming/OTT TV. This is because we don't implement the clock functionality needed to know when\n  new media segments become available nor the bandwidth management functionality that allows\n  adaptive streaming. Note however that some OTT providers public dynamic manifests for content that\n  is not live (i.e. all media segments are already available), and which we can download in dumb\n  “fast-as-possible” mode. You can use the method `allow_live_streams()` on `DashDownloader` to\n  attempt to download from these “**pseudo-live**” streams. It may also be useful to specify\n  `force_duration(secs)` and to use `sleep_between_requests()` to ensure downloading is not faster\n  than real time.\n\n  An alternative technique is to use the XSLT stylesheet `tests/fixtures/rewrite-drop-dynamic.xslt`\n  to change the `dynamic` attribute to `static` before downloading, which should allow you to\n  download this type of content.\n\n- No support for XLink with actuate=onRequest semantics.\n\n- HLS streaming (m3u8 manifests).\n\n- Microsoft Smooth Streaming.\n\n\n## Priority of different stream preference options\n\nThe library allows you to express a preference ordering for several characteristics of streams in a\nDASH manifest (audio language, video resolution, bandwidth/quality, role label). The list below\nspecifies the order in which these preferences are handled:\n\n- First filter out AdaptationSets in the manifest that do not correspond to our language\n  preference. If not language preference is specified, no filtering takes place. If multiple\n  AdaptationSets match the language preference, they all are passed on to the next stage of\n  filtering.\n\n- Select adaptations according to the role preference. If no role preference is specified, no\n  filtering takes place based on the role labels. If no adaptations match one of our role\n  preferences, no filtering takes place based on the role labels. If at least one adaptation matches\n  one role in the expressed role preference, only the adaptation which is closest to the head of the\n  role preference list is passed on to the next stage of filtering.\n\n- When multiple Representation elements are present, filter them according to any specified quality\n  preference. If no quality preference is specified, no filtering takes place. The filtering is\n  based on the `@qualityRanking` attribute, if it is specified on the Representation elements, and\n  otherwise based on the `@bandwidth` attribute specified. Note that quality ranking may be\n  different from bandwidth ranking when different codecs are used.\n\n- If a video width preference is specified, only select the Representation whose video width is\n  closest to the requested width.\n\n- If a video height preference is specified, only select the Representation whose video height is\n  closest to the requested height.\n\n- If more than one stream remains under consideration after all the preceding steps, select the\n  first stream that appears in the XML of the DASH manifest.\n\n\n## Usage\n\nTo **parse** (deserialize) the contents of an MPD manifest into Rust structs:\n\n```rust\nuse std::time::Duration;\nuse dash_mpd::{MPD, parse};\n\nfn main() {\n    let client = reqwest::blocking::Client::builder()\n        .timeout(Duration::new(30, 0))\n        .build()\n        .expect(\"creating HTTP client\");\n    let xml = client.get(\"https://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-ctv-stereo-en.mpd\")\n        .header(\"Accept\", \"application/dash+xml,video/vnd.mpeg.dash.mpd\")\n        .send()\n        .expect(\"requesting MPD content\")\n        .text()\n        .expect(\"fetching MPD content\");\n    let mpd: MPD = parse(\u0026xml)\n        .expect(\"parsing MPD\");\n    for pi in \u0026mpd.ProgramInformation {\n        if let Some(title) = pi.Title {\n            println!(\"Title: {:?}\", title.content);\n        }\n        if let Some(source) = pi.Source {\n            println!(\"Source: {:?}\", source.content);\n        }\n    }\n    for p in mpd.periods {\n        if let Some(d) = p.duration {\n            println!(\"Contains Period of duration {d:?}\");\n        }\n    }\n}\n```\n\nSee example\n[dash_stream_info.rs](https://github.com/emarsden/dash-mpd-rs/blob/main/examples/dash_stream_info.rs)\nfor more information.\n\n\nTo **generate an MPD manifest programmatically**:\n\n```rust\nuse dash_mpd::{MPD, ProgramInformation, Title};\n\nfn main() {\n   let pi = ProgramInformation {\n       Title: Some(Title { content: Some(\"My serialization example\".into()) }),\n       lang: Some(\"eng\".into()),\n       moreInformationURL: Some(\"https://github.com/emarsden/dash-mpd-rs\".into()),\n       ..Default::default()\n   };\n   let mpd = MPD {\n       mpdtype: Some(\"static\".into()),\n       xmlns: Some(\"urn:mpeg:dash:schema:mpd:2011\".into()),\n       ProgramInformation: vec!(pi),\n       ..Default::default()\n   };\n\n   let xml = mpd.to_string();\n}\n```\n\nSee example [serialize.rs](https://github.com/emarsden/dash-mpd-rs/blob/main/examples/serialize.rs) for more detail.\n\n\n\nTo **download content** from an MPD manifest:\n\n```rust\nuse dash_mpd::fetch::DashDownloader;\n\nlet url = \"https://storage.googleapis.com/shaka-demo-assets/heliocentrism/heliocentrism.mpd\";\nmatch DashDownloader::new(url)\n       .worst_quality()\n       .download().await\n{\n   Ok(path) =\u003e println!(\"Downloaded to {path:?}\"),\n   Err(e) =\u003e eprintln!(\"Download failed: {e:?}\"),\n}\n```\n\nSee example\n[download_bbc.rs](https://github.com/emarsden/dash-mpd-rs/blob/main/examples/download_bbc.rs) for a\nlittle more detail.\n\nAn application that provides a convenient commandline interface for the download functionality is\navailable separately in the [dash-mpd-cli](https://crates.io/crates/dash-mpd-cli) crate.\n\n\n## Installation\n\nAdd to your `Cargo.toml` file:\n\n```toml\n[dependencies]\ndash-mpd = \"0.19.2\"\n```\n\nIf you don’t need the download functionality and wish to reduce code size, use:\n\n```toml\n[dependencies]\ndash-mpd = { version = \"0.19.2\", default-features = false }\n```\n\nWe endeavour to use **semantic versioning** for this crate despite its 0.x version number: a major\nchange which requires users of the library to change their code (such as a change in an attribute\nname or type) will be published in a major release. For a version number `0.y.z`, a major release\nimplies a change to `y`.\n\n\n## Optional features\n\nThe following additive [Cargo\nfeatures](https://doc.rust-lang.org/stable/cargo/reference/features.html#the-features-section) can\nbe enabled:\n\n- `fetch` *(enabled by default)*: enables support for downloading stream content. This accounts for\n  most of the code size of the library, so disable it if you only need the struct definitions for\n  serializing and deserializing MPDs.\n\n- `http2` *(enabled by default)*: enables the `http2` feature on our `reqwest` dependency, which\n  means that HTTP requests will try to establish HTTP/2 (instead of HTTP/1.1) connections if the\n  functionality is advertised by an HTTP server, using the `Upgrade` header.\n\n- `socks` *(enabled by default)*: enables the `socks` feature on our `reqwest` dependency, which\n  provides SOCKS5 proxy support for HTTP/HTTPS requests.\n\n- `compression` *(enabled by default)*: enables the `gzip` feature on our `reqwest` dependency, to\n  enable gzip compression and decompression of HTTP/HTTPS requests.\n\n- `native-tls` *(enabled by default)*: enables the native-tls feature on our `reqwest` dependency,\n  to enable HTTPS requests using the platform's default TLS implementation.\n\n- `rustls-tls`: enable the `rustls-tls` feature on our `reqwest` dependency (use `rustls` instead of\n  system-native TLS). You may need to enable this (and build without `native-tls`) for static linking\n  with the musl-libc target on Linux.\n\n- `libav`: enables linking to ffmpeg as a library for muxing support (instead of calling out to\n  mkvmerge, ffmpeg or vlc as a subprocess), via the `ac-ffmpeg` crate.\n\n- `hickory-dns`: enable the `hickory-dns` feature on our `reqwest` dependency, to use the [Hickory DNS\n  resolver library](https://github.com/hickory-dns/hickory-dns) instead of the system resolver. (This\n  feature was previously named `trust-dns` following the previous name for the Hickory DNS resolver.\n  The old name for the feature is still accepted but is deprecated.)\n\n- `scte35` *(enabled by default)*: enable support for XML elements corresponding to the SCTE-35\n  standard for insertion of alternate content (mostly used for dynamic insertion of advertising).\n\n- `warn_ignored_elements`: if this feature is enabled, a warning will be issued when an XML element\n  present in the DASH manifest is not deserialized into a Rust struct, while parsing the manifest.\n  The default behaviour is to ignore elements for which we have not defined serde deserialization\n  instructions. This feature is implemented with the `serde_ignored` crate.\n\n- `sandbox` (currently only available on Linux): enable the experimental support for security\n  sandboxing our application code and our helper applications on Linux, using the Landlock loadable\n  security module. This functionality also needs to be enabled at runtime by calling the `sandbox`\n  method on `DashDownloader`. The feature restricts access to the filesystem, limiting write access\n  to directories that we will need to write to, limiting exec access to directories where our helper\n  applications and their runtime libraries are located, and limiting read access to directories that\n  the application or helper applications may need to read. It also somewhat restricts network\n  access, preventing binding to a TCP port.\n\n\n## Platforms\n\nThis crate is tested on the following platforms:\n\n- Linux, with default features (muxing using mkvmerge, ffmpeg, vlc or MP4Box as a subprocess) and\n  libav support, on AMD64 and Aarch64 architectures. This is what the author uses, so is the best\n  tested platform.\n\n- MacOS/Aarch64, without the libav feature (problems building the ac-ffmpeg crate against current ffmpeg)\n\n- Microsoft Windows 10 and Windows 11, without the libav feature\n\n- Android 12 on Aarch64 via [termux](https://termux.dev/), without the libav feature. You'll need to\n  install the `rust`, `binutils`, `ffmpeg` and `protobuf` packages.\n\n- FreeBSD/AMD64 and OpenBSD/AMD64, without the libav feature. Note however that some of the external\n  utility applications we use for muxing or decrypting media content are poorly supported on\n  these platforms.\n\n- Solaris 11.4 on AMD64 and Sparc (you will probably need to set `CC` to gcc to build the protobuf-src crate).\n\n\n## Why?\n\nThis library was developed to allow the author to watch a news programme produced by a public media\nbroadcaster whilst at the gym. The programme is published as a DASH stream on the broadcaster’s\n“replay” service, but network service at the gym is sometimes poor. First world problems!\n\n\u003e [!WARNING]\n\u003e The author is not the morality police nor a lawyer, but please note that redistributing media\n\u003e content that you have not produced may, depending on the publication licence, be a breach of\n\u003e intellectual property laws. Also, circumventing DRM may be prohibited in some countries.\n\n\n## License\n\nThis project is licensed under the MIT license. For more information, see the `LICENSE-MIT` file.\n\nPatches and pull requests are welcome.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femarsden%2Fdash-mpd-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femarsden%2Fdash-mpd-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femarsden%2Fdash-mpd-rs/lists"}