Dodge module for dash.js
Defend your own catalog with the opt-in dash.js module.
Just want to use Dodge? See install. New to video fingerprinting? Start with learn.
What it is
Dodge exists to stop a passive network observer from identifying a video by the sequence of segment sizes it produces on the wire; see how video fingerprinting works for the attack and threat model & security for what a defense does and doesn't hide. That is the reason behind most of the design choices below, strict mode in particular.
Dodge is implemented as an opt-in module in dash.js, as dash.dodge.js. It is auto-detected at attachView() time, loaded as a separate script, and wired in via overrides registered through mediaPlayer.extend(). Ordinary dash.js playback is unchanged when Dodge is not loaded; when it is, behavior depends on the source URL.
The module is purely client-side. No server or network infrastructure changes are required beyond hosting a JSON configuration file (extended manifest) in place of, or alongside, an ordinary MPD. The extended manifest specifies cycles, Dodge's generalized download unit, which replace ordinary segment downloads.
Operating modes
| Scripts loaded | Source URL | Result |
|---|---|---|
dash.all.min.js only | Plain MPD | Standard DASH, unchanged |
dash.all.min.js + dash.dodge.min.js | Plain MPD | Standard DASH, graceful degradation (configurable via strict mode settings) |
dash.all.min.js + dash.dodge.min.js | Extended manifest | Dodge defense active |
There are no API changes to make. You pass an extended manifest URL instead of an MPD URL, and Dodge uses the existing MediaPlayer.initialize() interface.
Quick start (integration)
<script src="dash.all.min.js"></script>
<script src="dash.dodge.min.js"></script>
<script>
var player = dashjs.MediaPlayer().create();
player.initialize(
document.querySelector("#videoPlayer"),
"content.exmfst.json",
true
);
</script> Extended manifests
An extended manifest is a JSON file that wraps the original MPD and adds per-representation cycle download schedules. ManifestLoader detects the JSON format, validates it using the DefenseRegistry singleton, and extracts the embedded MPD for DashParser processing. The defense schedules are stored separately, in DefenseRegistry, and consulted by the DashHandler override during playback.
Extended manifests contain a number of stream entries. Each stream's label matches a representation ID from the MPD, and streams can optionally be scoped to a period index. Cycles in the data array specify a segment index and an optional range for partial downloads. Two flags control what happens to the downloaded data: buffer controls when pending data is buffered for playback (nothing is ever buffered unless the defense designer explicitly sets the buffer flag), and padding marks cycles that are used as cover traffic and should be discarded. Padding can also be downloaded after playable content (trailing padding) to extend a video's apparent duration as seen by network observers.
The Dodge module introduces two features beyond the paper:
- The
bufferfield on data cycles can be an array of segment indices (e.g.,"buffer": [0, 1]) for selective buffering. Pending data is held until the cycle with the buffer array completes, then all listed indices are buffered together. - Both data cycles and init cycles may carry a
qualityfield (a representation ID string or numeric index) to fetch from a different representation in the same adaptation set. On data cycles, this lets defenses conceal a segment's size by substituting a smaller (or larger) version from an alternate quality level. On init cycles, it selects which representation's init segment is fetched and stored. Downloading multiple init segments per stream is often necessary for playback of alternate representations.
For the full format reference, see extended manifest format.
Strict mode
The dodge.strictMode setting prevents accidental undefended playback. The four levels trade safety for flexibility. 'representation' is the default and is suitable for many use cases, while 'manifest' or 'max' is recommended where the presence of a defense is critical. Disabling strict mode entirely is possible but strongly discouraged: representations present in the embedded MPD but not covered in the extended manifest's streams array would be downloaded without any defense.
| Level | Behavior |
|---|---|
'representation' (default) | Blocks undefended fragmented representations when an extended manifest is active; plain DASH still works. |
'manifest' | Same as 'representation' and refuses to play if the source URL is not an extended manifest (no vanilla MPDs). |
'max' | Same as 'manifest' and also rejects manifests containing thumbnails, non-fragmented text, or XLink references. |
false | Always falls back to vanilla dash.js (not recommended for production). |
Dodge does not disable DRM, CMCD, DVB reporting, or content steering, since these features are important in the streaming ecosystem. The nor/nrr fields are suppressed in CMCD requests (everything else is preserved); Dodge logs warnings when these features are used in strict mode so the defense designer can verify their behavior in context. Init segment caching should likely not be enabled and is off by default.
For the full validation rules, see extended manifest format → strict mode. strictMode is one of several options; for the complete settings reference, see settings reference.
Tests and quality
The module includes unit tests covering ABR rule management, cycle-based downloading, the mock buffer state during the trailing phase, random-walk scheduling, and URL/request padding. A REQUIREMENTS.md traceability index maps each requirement to the test cases that cover it. Existing dash.js tests are unaffected.
Functional tests go a step further. They use Karma, Mocha, and Chai to play real CDN-hosted video through the module in a headless browser, checking behavior end to end: defense activation, cycle-by-cycle traffic (segment index, byte range, buffer directive, padding flag), the mock buffer, quality overrides, strict mode enforcement, multi-period transitions, and seeking during defended playback.
Bundle impact
dash.all.min.js grows by 3.1 KiB. The only additions to the base player are the small hooks and stubs needed for override registration. The Dodge module itself lives entirely in dash.dodge.min.js (70.0 KiB), which is loaded only when opted into. Build times are effectively unchanged.
Source
The module's source lives in the dash.js repository (src/dodge/), licensed under BSD-3-Clause by the DASH Industry Forum, the same license as the rest of dash.js. Integration is currently being reviewed in pull request #5021.
For discussion of the dash.js module's development, use the dash.js Google Group.