dash.js

Open Source Media Player

Seamless and reliable DASH streaming on any browser-based device

View onGitHub
5506
1728

Sponsors

Trusted by the industry leaders

Latest updates from GitHub

parseXml: optimize DASH SegmentTimeline <S> parsing**Is your feature request related to a problem? Please describe.** Yes. Large DASH live DVR manifests block the main thread during parsing. This issue is about the XML parser project [`@svta/cml-xml`](https://github.com/streaming-video-technology-alliance/common-media-library/tree/main/libs/xml), not about changing dash.js itself. dash.js is only the workload used to measure the problem. On an XL synthetic manifest (50 Periods x 4 AdaptationSets x 500 `S` entries, about 102k XML nodes), the full dash.js manifest parse takes about 40 ms on an M1. The XML parser alone takes about 30.5 ms of that total, or 62%. About 98% of the nodes in these manifests are `SegmentTimeline` `<S>` entries. They are simple self-closing nodes with only integer attributes like `t`, `d`, `r`, and `k`, but they still go through the full generic parsing path. **Describe the solution you'd like** Add a specialized fast path in `parseXml()` for self-closing DASH `SegmentTimeline` `<S>` nodes. The proposed implementation should happen in [`@svta/cml-xml`](https://github.com/streaming-video-technology-alliance/common-media-library/tree/main/libs/xml), inside `parseXml()`. **Expected behavior** - detect `<S ... />` nodes while parsing - parse `t`, `d`, `r`, and `k` directly as integers - skip `unescapeHtml()` for numeric attributes - avoid unnecessary generic attribute parsing work for these nodes - reuse a shared empty `childNodes` array for self-closing nodes when safe - preserve the current output shape In a synthetic benchmark, a specialized eager parser for `<S>` nodes reduced the XML parsing cost from about 39.8 ms to about 19.1 ms on the XL manifest, a reduction of about 52% (`~2.1x` faster). **Describe alternatives you've considered** - Lazy parsing of `SegmentTimeline.S` Rejected. These entries are typically consumed immediately after manifest parsing for duration calculation, segment counting, and segment lookup. - A local XML parser variant inside dash.js Rejected. A local clone was slower than the current `@svta/cml-xml` implementation in synthetic benchmarks. - A downstream dash.js optimization in `DashParser.processNode()` Useful, but secondary. For example, replacing `arrayNodes.indexOf()` with `Set.has()` helps, but the main bottleneck is still `cmlParseXml()`. **Additional context** **Example hot-case nodes** ```xml <S t="123456" d="180000" /> <S d="180000" r="14" /> <S d="180000" r="-1" k="3" /> ``` **Reproduction** ```bash node test/bench-manifest-parsing.mjs node test/bench-parsexml.mjs ``` **Real public live DVR example** - `https://livesim2.dashif.org/livesim2/segtimeline_1/tsbd_21600/testpic_2s/Manifest.mpd` - verified on March 10, 2026 - `timeShiftBufferDepth="PT6H"` - about 170 KB - about 5402 literal `<S>` nodes in the fetched MPD **Larger multi-period variant** - `https://livesim2.dashif.org/livesim2/segtimeline_1/tsbd_21600/periods_60/continuous_1/testpic_2s/Manifest.mpd` - `timeShiftBufferDepth="PT6H"` - about 901 KB - 361 periods - about 5942 literal `<S>` nodes in the fetched MPD **Why this matters for users** - on desktop, `39.8 ms -> 19.1 ms` still means about 52% less XML parsing work on the main thread - on lower-end Smart TV / STB class hardware, that same reduction can translate to roughly 100-200 ms less blocking per manifest refresh - on live DVR streams, this cost repeats on every manifest update cycle, so users can experience recurring UI hitching rather than a one-time delay **Environment used for the measurements above** - dash.js v5.2.0 - [`@svta/cml-xml`](https://github.com/streaming-video-technology-alliance/common-media-library/tree/main/libs/xml) 1.0.1 **What would make this complete** - no observable output change for current consumers - measurable improvement on large DASH manifests with dense `SegmentTimeline` - no regression on non-DASH XML inputs - benchmark or test coverage proving both correctness and performance Opened by PascalThuet22 hours ago
DVBSelector: last BaseURL never selected with equal weights (off-by-one in weighted random)##### Environment - [x] The MPD passes the DASH-IF Conformance Tool on https://conformance.dashif.org/ - [x] The stream has correct Access-Control-Allow-Origin headers (CORS) - [x] There are no network errors such as 404s in the browser console when trying to play the stream - [x] The issue observed is not mentioned on https://github.com/Dash-Industry-Forum/dash.js/wiki/FAQ - [x] The issue occurs in the latest reference client on http://reference.dashif.org/dash.js/ and not just on my page * Link to playable MPD file: `samples/advanced/mpds/basic-cmcd-config.mpd` (3 BaseURLs, no `dvb:weight`) — remove the `<ContentSteering>` element to expose the bug (Content Steering overrides DVB selection) * Dash.js version: 5.2.0 (development branch) * Browser name/version: all (logic bug, not browser-specific) * OS name/version: all ##### Steps to reproduce 1. Load an MPD with 2+ `<BaseURL>` elements at the same priority, without `dvb:weight` (defaults to 1) and without `<ContentSteering>` 2. Observe which CDN is selected across multiple sessions > **Note:** `samples/advanced/mpds/basic-cmcd-config.mpd` has 3 BaseURLs without `dvb:weight` but uses Content Steering, which overrides DVB selection and masks the bug. ##### Observed behavior The last BaseURL in a weighted group is never selected. `DVBSelector.js` line 114: ```javascript rn = Math.floor(Math.random() * (totalWeight - 1)); ``` `Math.random()` returns `[0, 1)`, so `Math.floor(Math.random() * totalWeight)` already produces `[0, totalWeight-1]`. The extra `- 1` shrinks the range and excludes the last CDN. **Example : 2 equal-weight CDNs** (most common multi-CDN setup): `totalWeight = 2`, `cumulWeights = [1, 2]`: ``` rn = Math.floor(Math.random() * 1) = always 0 → always cdn-a, cdn-b never selected ``` ##### Console output ``` No error — the bug is silent. ``` ##### Expected behavior Each BaseURL selected with probability proportional to its weight (RFC 2782). With equal weights: ~50/50 for 2 CDNs, ~33/33/33 for 3 CDNs. Opened by PascalThuet3 days ago
[DASH] MEDIA_ERR_DECODE when manifest transitions from dynamic to static (live-to-VOD)Description: When a DASH manifest transitions from type="dynamic" (live) to type="static" (VOD), VHS detects excessive audio segment downloading and blacklists all available playlists, resulting in a fatal MEDIA_ERR_DECODE with no recovery path. Steps to Reproduce: Load a DASH stream with type="dynamic" (live stream) Wait for the manifest to transition to type="static" (VOD/live-to-VOD) Audio segments are repeatedly re-downloaded Player throws fatal error Expected Behavior: Automatically re-parse manifest as VOD Resume playback without fatal error Actual Behavior Excessive audio segment downloading detected. Switching to playlist 0-placeholder-uri-0. Playback cannot continue. No available working or supported playlists. MediaError { code: 3, message: 'Playback cannot continue...' } Opened by rakeshLogituit6 days ago

More news on

Contributors