Dash-Industry-Forum/dash.js: the reference MPEG DASH player in JavaScript
A reference client implementation for the playback of MPEG DASH via Javascript and compliant browsers.
At a glance
- What is it?
- The DASH Industry Forum's client implementation for DASH playback, from a two line quickstart to the segment scheduling logic a production player needs.
- Who is it for?
- dash.js is the piece of infrastructure that sits between a packager and the browser APIs nobody wants to reimplement. The quickstart is genuinely three lines, and everything above that line is the accumulated result of making MSE and EME behave across real browsers: media source handling, buffer management, adaptation logic, DRM licence requests and a sample set that doubles as documentation.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 19 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three lines of JavaScript and a CDN script tag
The quickstart in the README is a complete HTML page, and the interesting part is how little of it is dash.js. You create a player, point it at a video element, and hand it a manifest URL:
<script src="https://cdn.dashjs.org/latest/modern/umd/dash.all.min.js"></script>
<script>
(function () {
var url = "https://dash.akamaized.net/envivio/EnvivioDash3/manifest.mpd";
var player = dashjs.MediaPlayer().create();
player.initialize(document.querySelector("#videoPlayer"), url, true);
})();
</script>The third argument to initialize is the autoplay flag, and the URL is a plain MPD rather than HLS. That is the whole contract, which is the point of a reference implementation: nothing about the calling code is specific to dash.js.
The dependency story is worth stating plainly because it determines where your effort goes. dash.js does not implement a media stack. It requires a browser with Media Source Extensions and Encrypted Media Extensions, which is exactly what the README says in its opening paragraph. The hard problems of parsing MPD XML, scheduling segment downloads, choosing representations and managing buffer levels are all in this library; decoding and playback are the browser's job.
Two build targets and two entry points in package.json
The package manifest names the npm package `dashjs` at version 5.2.2, requires Node 20 or newer, and declares itself as an ES module. The exports map is the detail that matters for anyone integrating it, because it defines two separate entry points and several module formats for each.
The `.` entry resolves to `dash.all.min.js`, which is the full build including the Smooth Streaming parser, and it serves `import`, `browser`, `script`, `require` and a default. The `./mss` entry resolves to `dash.mss.min.js`, the same package without Smooth Streaming support. So a project that has no need for MSS can take a smaller bundle by importing the subpath, and a project that loads dash.js from a script tag gets the UMD build automatically.
Build output is split into a modern and a legacy flavour, produced together by the default build script, which runs the modern and legacy webpack builds concurrently. The individual scripts are available separately as `build-modern` and `build-legacy`, both of which run a prebuild step first. `build:dist` goes further and runs a TypeScript compile with `tsc` before both webpack builds, and `ci:verify` chains a clean, the compile, the tests and the lint into one command.
For a maintainer, the dev loop is `npm run dev`, which compiles and then runs webpack in watch mode against `build/webpack/modern/webpack.modern.dev.cjs`. Documentation has its own tooling: `npm run doc` generates jsdoc into `docs/jsdoc`, while `docs:dev`, `docs:build` and `docs:preview` run a VitePress site from `docs/site`.
The samples directory doubles as the feature documentation
There are 25 sample directories, and reading their names is the fastest way to see what the library covers. The list starts with the obvious ones: `samples/abr/` for adaptation logic, `samples/buffer/` for buffer behaviour, `samples/captioning/` for subtitles, `samples/drm/` for protected content, `samples/hevc/` for codec coverage, `samples/live-streaming/`, `samples/low-latency/` and `samples/multiperiod/` for the live and multi-segment cases that break naive players.
The less obvious directories are the interesting ones. `samples/cmcd/` exists because Common Media Client Data is now a first-class feature, `samples/lcevc/` covers layered enhancement video coding, `samples/network-interceptor/` lets you observe or rewrite every request the player makes, and `samples/multiperiod/` handles manifests where the timeline is split across periods with different adaptation sets. There are also `samples/module-builds/` and `samples/modules/` for people assembling the player from individual modules rather than taking the all-in bundle.
Two hosted entry points are published: a Reference Player and the samples index. The reference player at reference.dashif.org is the one to open first, because it exposes every setting in a user interface rather than requiring you to write code to try them. Browser coverage is handled through BrowserStack and LambdaTest, which the README lists under what the project is tested with. That matters for a player library in a way it would not for most projects, since the failure modes are browser-specific.
Version 5.2 added CMCD v2, certurl and FairPlay
Three tagged releases tell you what direction the project is moving. Version 5.2.1 came on 2026-08-17 and reads as a polish release: a `hybridSwitchBufferTime` setting for switching between BOLA and throughput rules, remaining adaptation sets added to the capability event, scrub bar and timeline changes for on-demand content when an MPD transitions from dynamic to static, initial track filtering by codec string, an external certificate URL for FairPlay, and a current timestamp on the control bar progress bar. Its bugfixes include a repair so SourceBuffers are not reused across periods when `changeType` is unavailable, and a fix for quality switching on L3D-DASH streams.
Version 5.2.0, from 2026-05-28, is the substantive one. It adds comprehensive support for CMCD version 2, built on the `@svta/cml-cmcd` library's CmcdReporter so reporting is centralised rather than scattered, adds support for the `certurl` element, and adds Apple FairPlay Streaming DRM support. It also introduces a new reference UI and a `limitBitrateByPortalMinimum` setting to stop bitrate limiting from going too far.
Version 5.1.1, from 2025-12-23, is smaller: re-adding inline events after a seek, an offset applied to gap jumps that is configurable through settings, saving content steering information from the manifest so it survives an MPD update that drops it, and unit tests for the content steering, catchup and gap controllers. The shape of these lists is a good description of what breaks in DASH playback: seek behaviour, gap jumps, and state that disappears on manifest refresh.
What the repository root says about how the project works
The root of the tree is worth reading as a map of the project's conventions. There is `index.js` and `index_mediaplayerOnly.js`, the two bundle entry points that correspond to the full build and the media-player-only variant. There is `index.d.ts`, which is what the exports map points its `types` field at, so TypeScript consumers get declarations from the package rather than from a separate types package.
Then there are the files that show where the project's attention goes. `AGENTS.md` and `CLAUDE.md` sit at the root, which tells you coding conventions are documented for automated agents as well as people. `llms.txt` is the newer convention for machine-readable project context. `eslint.config.mjs` is the flat-config lint setup, and `.browserslistrc` is what decides which browsers the legacy build targets. `tsconfig.json` is there even though the source is JavaScript, because the build compiles types.
The rest is ordinary: `src/`, `test/`, `samples/`, `docs/`, `build/`, `contrib/`, `externals/`, and `githook.cjs` for git hooks. The default branch is `development`, which is worth knowing before you open a pull request. The repository is not archived, the last push was 2026-09-17, and 180 open issues on a project this size is a healthy backlog rather than a warning sign, given how much of the work is browser-specific behaviour reports.
How this compares to the HLS path
The comparison people actually make is against an HLS player, usually hls.js, and the honest framing is that these solve different halves of the problem. dash.js only plays MPEG DASH. It does not parse m3u8 playlists. If your content catalogue is HLS, this library is not a candidate, and the reverse is true for the HLS-only players.
What DASH gives you over HLS is in the manifest. MPD is XML and can describe multiple adaptation sets explicitly, which makes multi-audio and multi-language tracks, and per-track capability signalling, easier to reason about. The capability event, which version 5.2.1 extended to cover the remaining adaptation sets in the manifest, is exactly the mechanism for that: the player tells you what it can decode, and you filter tracks against it rather than hardcoding a track list.
Where HLS wins is deployment simplicity, because HLS plays natively in Safari without JavaScript, while DASH needs the player library in every browser. For a service shipping to a mixed device population, the usual answer is to encode both formats from the same packager and hand HLS to the devices that do not want a player.
Inside DASH itself, dash.js is the reference: the Dash Industry Forum maintains it, which means its behaviour tends to track the specification rather than one company's roadmap. The cost of that neutrality is that it implements more than any single deployment needs, which is why the `dash.mss.min.js` subpath and the module build samples exist.
Editorial conclusion
dash.js is the piece of infrastructure that sits between a packager and the browser APIs nobody wants to reimplement. The quickstart is genuinely three lines, and everything above that line is the accumulated result of making MSE and EME behave across real browsers: media source handling, buffer management, adaptation logic, DRM licence requests and a sample set that doubles as documentation. If you are evaluating it, the most useful things to read are the ABR samples directory, the DRM samples, and the release notes for the version you would pin, because the version lines move fast and v5.2.0 was a large one with CMCD version 2 support. Start from the CDN quickstart to confirm playback works, then read the usage documentation on dashif.org for settings and events, and use the reference player as the map for what the library can actually be asked to do.
Frequently asked questions
What is a dash player?
A dash player is a client that plays MPEG DASH content by reading an MPD manifest, fetching media segments itself and feeding them into the browser through Media Source Extensions. dash.js is the reference implementation of that idea in JavaScript, maintained by the Dash Industry Forum, and it requires a browser that supports both MSE and EME.
What is DASH video streaming and how does it work?
DASH is a streaming standard built around an MPD manifest that describes the available representations as separate video and audio adaptation sets. The player parses that XML, measures throughput, and requests segments at a quality it picks. dash.js implements the client side of this, using the browser's Media Source Extensions for playback and Encrypted Media Extensions for DRM.
Does dash.js support Smooth Streaming?
Yes, through a separate build. The package exports a `./mss` subpath that resolves to `dash.mss.min.js`, a version without the Smooth Streaming parser, while the default entry includes it. A project with no MSS content can import the smaller bundle and skip that code entirely.
What Node version does dash.js need?
Node 20 or newer. The package manifest declares that engine requirement, and the build pipeline uses TypeScript compilation alongside webpack, so an older Node will fail before you reach the browser code.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/dash-industry-forum-dash-js)