Commit Graph

2733 Commits

Author SHA1 Message Date
Andy(김규회) c3d82bea1d feat(ABR): Monitor dropped frames to influence decisions (#9918)
Close https://github.com/shaka-project/shaka-player/issues/745

The ratio is checked periodically, and when the threshold is exceeded,
the current stream is 'disableStream' if possible, and a new decission
is taken

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
Co-authored-by: Matthias Van Parijs <matvp91@gmail.com>
2026-04-09 11:37:13 +02:00
Marc-Antoine 14821c30fb fix: Correctly extract file extension from URLs with dots in query params (#9946)
### Description

Fixes #9945 

The `getExtension` function (rewritten for performance in #9816) scans
the URI right-to-left, encountering dots in query parameter values (e.g.
hostnames like `app.example.com`, filenames like `en.vtt`) before
finding the `?` delimiter. This causes incorrect extension detection,
breaking MIME type resolution for URLs with signed parameters or other
query strings containing dots.

**Fix:** Split the single right-to-left scan into two passes:
1. **Left-to-right:** find the first `?` or `#` to establish the path
boundary
2. **Right-to-left:** scan backward within the path portion only,
looking for `.` or `/`

This preserves the lightweight character-scanning approach from #9816
without reintroducing the `goog.Uri` dependency.

**New test cases added:**
- Dots in query parameter values
(`?host=app.example.com&signature=abc.def`)
- Signed URLs with encoded paths and filenames in query strings
- Hostname-like values in query parameters (`?origin=cdn.example.co.uk`)
- No path extension with dotted query values (`/stream?file=video.mp4` →
`""`)
- Dots in fragment identifiers (`#t=1.5`)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:11:03 -07:00
Antonio Díaz Correa 93290d27a0 fix(StreamingEngine): correct variable reference in discardReferenceByBoundary_() (#9943)
## Description

fix: wrong variable reference in `discardReferenceByBoundary_()` causing
VIDEO_ERROR on HLS live streams
### What this fixes
`discardReferenceByBoundary_()` in `lib/media/streaming_engine.js` has a
wrong variable reference: when processing `newCodec` the code reads
`lastInitRef.mimeType` instead of `initRef.mimeType`.

This means `newCodec` is always identical to `oldCodec`, so the guard
that prevents unnecessary resets (`discard = false`) never fires when
`crossBoundaryStrategy === KEEP`.
 
As a result, every HLS discontinuity of timestamps, codecs, or encoding
parameters forces a MediaSource reset.
On live streams with server-side DAI, the repeated forced resets corrupt
the SourceBuffer and crash the player with VIDEO_ERROR (error code
3016).

This is a regression introduced in 5.x. Shaka 4.x did not have this
issue.
                  
### Fix

One-line change in `lib/media/streaming_engine.js`:
   
```diff                                                                                                                                                                                                                                                                                                     
  const newCodec = MimeUtils.getNormalizedCodec(
-     MimeUtils.getCodecs(lastInitRef.mimeType));
+     MimeUtils.getCodecs(initRef.mimeType));
```
   
With this fix `KEEP` correctly compares the codec of the outgoing init
segment against the codec of the incoming one. When they match
MediaSource is kept, and when they differ it is reset, which is the
intended behavior.
                  
### How to reproduce
                  
1. Play an HLS live stream with server-side DAI that generates
`EXT-X-DISCONTINUITY` tags at ad boundaries, like FAST channels.
2. Use default Shaka config, do not override `crossBoundaryStrategy`,
default is `KEEP`.
3. Wait for an ad to be triggered.
4. Player crashes with `VIDEO_ERROR` / error code 3016. No network
errors. All segment fetches return 200/206.
2026-04-08 11:13:02 +02:00
Wojciech Tyczyński e2cf6a1724 chore: Replace PublicPromise with Promise.withResolvers (#9925)
Stop using `shaka.util.PublicPromise` and replace it with modern
`Promise.withResolvers()` API, that is [widely implemented
already](https://caniuse.com/wf-promise-withresolvers).

Polyfill is already included by Closure Compiler:
https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/js/es6/promise/withResolvers.js

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-04-07 16:11:29 +02:00
Álvaro Velad Galván 845b6bd197 fix: Properly clone nested cues and CueRegion in Cue.clone() (#9940) 2026-04-07 12:16:44 +02:00
Álvaro Velad Galván 0522d0b1dc feat(MSF): Make subscribe filter type configurable (#9941) 2026-04-07 10:47:23 +02:00
Álvaro Velad Galván ad0b45d2ed test: Fix cast UI tests (#9938)
Bug introduced in
https://github.com/shaka-project/shaka-player/pull/9904
2026-04-06 20:26:06 +02:00
Wojciech Tyczyński 6509d9b7ac chore: Remove rarely used Functional methods (#9928) 2026-04-02 18:43:37 +02:00
Álvaro Velad Galván 8230cddecd test: Fix Object.hasOwn in old devices (#9913)
Original commit:
https://github.com/shaka-project/shaka-player/commit/586ce0636e730e29b0057e7dcfd1a87c40208299
2026-03-30 13:35:51 +02:00
Sakura501 586ce0636e chore(Demo): demo assetBase64 prototype pollution to DOM XSS (#9906)
## Summary

This PR fixes a demo asset parsing and configuration merge vulnerability
where a
malicious `assetBase64` payload could abuse `__proto__`, `constructor`,
or
`prototype` keys to pollute object prototypes and later reach DOM XSS
gadgets in
Shaka Player Demo.

## Vulnerability details

The vulnerable path was:

1. `demo/main.js` reads attacker-controlled `assetBase64` from the URL
hash.
2. `demo/common/asset.js` copies `extraConfig` into a player config
object with
   `for..in`, which allows dangerous magic keys to be applied.
3. `lib/util/config_utils.js` merges config objects with another
`for..in`
   traversal and no explicit rejection of `__proto__`, `constructor`, or
   `prototype`.
4. The resulting prototype pollution can be turned into DOM XSS when
later demo
   UI rebuild paths consume inherited properties.

## Fix approach

This change hardens both the demo entry point and the shared merge
utility:

- `demo/common/asset.js`
  - filter dangerous keys when copying `extraConfig`
  - restrict `toJSON()` and `fromJSON()` to own properties only
- prevent dangerous keys from being serialized into or restored from
saved demo
    assets
- `lib/util/config_utils.js`
  - switch config merging from `for..in` to `Object.keys()`
  - explicitly reject `__proto__`, `constructor`, and `prototype`

## Regression coverage

Added tests that verify:

- dangerous `extraConfig` keys do not alter the generated player config
- inherited demo asset properties are not serialized into JSON
- dangerous keys are ignored when parsing saved assets back into demo
objects
- inherited magic keys are not traversed during config merges

## Verification

- `python3 build/test.py --quick --filter 'Demo|ConfigUtils' --browsers
ChromeHeadless`
- `python3 build/check.py`
2026-03-30 10:40:10 +02:00
MultiViewer 5717432206 feat(ui): add customTrackLabel callback for overriding track labels (#9904)
## Summary
- Adds a `customTrackLabel` callback to the UI configuration that allows
overriding track labels for both audio and text tracks
- The callback receives the default label (or `null` if the language was
unrecognized), the track object, and a type string (`'audio'` or
`'text'`)
- Returning a string overrides the label; returning falsy keeps the
default behavior

Fixes #9821

## Example usage
```javascript
ui.configure({
  customTrackLabel: (defaultLabel, track, type) => {
    if (track.language === 'fx') return 'Sound Effects';
    return null; // use default
  }
});
```

## Test plan
- Added integration tests verifying label override, null for
unrecognized languages, type argument, and fallback behavior
- Tests pass in both compiled and uncompiled modes

## AI Disclosure
As highlighted in the new `AGENT-ATTRIBUTION.md`, I've added Claude as a
co-author of the commit as I made use of it during this PR.

Signed-off-by: F1 MultiViewer <f1multiviewer@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-29 14:18:06 -07:00
Ivan 2c8cfd20f3 perf(TS): Eliminate per-PES wrapper array allocations in parse loop (#9883)
This PR reduces GC pressure during MPEG-TS segment parsing - it replaces
nested PES packet arrays with a flat array plus a PES-start index,
eliminating per-PES inner array allocations and avoiding spread-operator
overhead when concatenating packets - reduces allocations, hence reduces
GC pressure on low-end devices during long livestreams
2026-03-26 10:03:32 +01:00
Álvaro Velad Galván 76d655bed6 perf(MSF): Improve compatibility with the draft-14 (#9895)
More types of messages are now supported than before. 
SubscribeError handling has been improved.
A new error has been added when no catalog.
Existing messages have been reviewed to eliminate inconsistencies in the
migration from draft-11 to draft-14 support.
Fix log levels
2026-03-26 09:46:40 +01:00
Ivan c86ce869c3 perf(media): replace filter calls in SegmentIndex with binary search (#9880)
This PR replaces `Array.filter` calls in
`SegmentIndex.merge()`,`mergeAndEvict()`, and `evict()` with more
efficient alternatives. The key addition is `binarySearch` helper: it
repeatedly checks the midpoint and discards half the array each time.
The idea is the same as `Array.findIndex` but exploiting the sorted
order to skip most of the work. `merge()` and `evict()` use this to find
their truncation/expiry boundary; `mergeAndEvict()` uses a simple
forward scan that stops at the first valid reference since stale refs
are always bunched at the front. This is done to reduce iteration during
playback (especially livestream with DVR)

- no big new array creations by default - we don't create one when for
example there is nothing to evict
- fewer comparisons — binary search finds the cutoff without scanning
the whole array
- slice just copies the kept elements and that's it
2026-03-25 10:00:52 +01:00
Álvaro Velad Galván c03026f64c feat(UI): Add mediaSession.allowAutoPiP config (#9885)
See:
https://developer.chrome.com/blog/automatic-picture-in-picture-initiated-by-the-browser
2026-03-24 13:22:27 +01:00
Gaurav Mahendroo a62e87b351 fix: Call endOfStream when no data available close to duration (#9866)
When playback reaches near the end of the presentation but no buffer
exists and no segment reference is found, the player continuously
retries without properly detecting end-of-stream, preventing the ended
event from firing.

When close to end (timeUntilEnd < oneMicrosecond) with no buffer and no
segment reference, immediately mark as end-of-stream instead of retrying
indefinitely. Also propagate the endOfStream state to embedded CEA text
streams when the video stream reaches end.
2026-03-24 11:09:09 +01:00
Álvaro Velad Galván 6805b55769 feat(ABR): Inform the ABR whether the stream is low latency or not (#9882)
Our ABR doesn't use it, but it's useful for custom implementations.

Related to https://github.com/shaka-project/shaka-player/issues/9872
2026-03-24 09:22:55 +01:00
gmamzn 45a86cacd5 fix(HLS): Prevent infinite manifest update delay (#9867)
During a variant switch in HLS live content, shaka may take ~1 second to
create a new segment index (due to network calls). During this window,
the number of active streams temporarily drops to zero. When update()
runs in this state, lastTargetDuration_ gets set to Infinity because
there are no active streams to reduce it. This causes
getUpdatePlaylistDelay_() to return Infinity, so
updatePlaylistTimer_.tickAfter(Infinity) is called, effectively stopping
manifest updates forever.

Fix this with two guards:
1. In update(): return early when there are no active streams, before
setting lastTargetDuration_ to Infinity.
2. In onUpdate_(): if finalDelay is Infinity or NaN, use a 1-second
fallback delay instead of scheduling with a non-finite value.
2026-03-23 10:20:59 +01:00
gmamzn 12f7296c6c fix: Increase tolerance for duplicate segment detection (#9865)
In HLS, the segment iterator can add or remove segments rapidly, causing
the same segment to reappear with a slightly different start time. The
existing duplicate detection used a 1ms tolerance, but some streams
exhibit timing inaccuracies between 1ms and 2ms, causing the same
segment to be downloaded twice. This leads to AV sync issues because the
duplicate segment shifts the buffer by one segment duration.

Increase the tolerance from 1ms to 2ms to cover these cases.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-03-20 16:46:41 +01:00
gmamzn dd5b2dab21 fix(HLS): Add support for DTS and DTS-HD audio codec variants (#9863)
Add DTS (dts), DTS-HD (dtsh), DTS Digital Surround (dtsc), DTS Express
(dtse), and DTS:X (dtsx) to AUDIO_CODEC_REGEXPS using a single merged
regex /^dts[cehx]?$/.

Include regression tests for all new codec variants.
2026-03-20 16:01:02 +01:00
Ivan c9f8057f9a perf(DASH): loop over adaptation sets using the partition method (#9862) 2026-03-20 15:45:57 +01:00
gmamzn d15a0702ac fix(util): Add support for MPEG-2 video codec (#9860)
Add /^mp2v/ regex to VIDEO_CODEC_REGEXPS so that guessCodecsSafe
correctly recognizes MPEG-2 video codec strings. Without this, manifests
containing mp2v codec identifiers would fail codec detection, preventing
playback of MPEG-2 video content.

Includes regression tests verifying mp2v is recognized as a video codec
and not misidentified as audio.
2026-03-20 14:09:43 +01:00
Álvaro Velad Galván ea95befa54 feat(Ads): Add ad-interstitial-preloaded event (#9853)
Close: https://github.com/shaka-project/shaka-player/issues/9849
2026-03-20 10:52:20 +01:00
Álvaro Velad Galván b9abb399bb fix(LCEVC): Fix multi-period VOD support (#9837)
A new integration test has been added.
The use of `stream` within `stream` in `periods.js` has been refactored
to simplify management and avoid duplicates.

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-03-19 10:07:14 +01:00
Julian Domingo 941d165c87 fix: Prevent live stream infinite buffering when isAudioMuxedInVideo is present (#9835)
Fixes https://github.com/shaka-project/shaka-player/issues/9836
2026-03-18 21:08:07 -07:00
Álvaro Velad Galván 268fb19719 feat(UI): Add showMenusOnTheRight config (#9838)
Close https://github.com/shaka-project/shaka-player/issues/9833
2026-03-18 13:17:24 +01:00
Álvaro Velad Galván 0c0a47c8d6 fix(MSF): Use bigint natively (#9826)
Many relays use large numbers and with the current implementation it
doesn't always work.

See Closure's limitations here:
https://github.com/google/closure-compiler/wiki/BigInt-support
2026-03-14 10:51:09 +01:00
Andy(김규회) ef6c1fe804 feat(Demo): offer UI configuration in the demo app (#9807)
There is a UI configuration option that cannot be set in the demo app
unless you open the JS console and manually call configure(), and we
have added a new UI section to the demo configuration panel to
congratulate the features.

In this section, options were displayed in
shaka.extern.UICconfiguration, such as Boolean, numeric, numeric,
drop-down, enum, text string, comma-separated text input, and array. It
also covered overlapping objects such as seekBarColors, mediaSession,
and shortcuts.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-03-11 13:20:12 +01:00
Álvaro Velad Galván 87ac4cb67a fix(Ads): Improvements to the use of ASSET-LIST on devices with single-element video support (#9810)
Co-authored-by: Theodore Abshire <TheodoreAbshire@Gmail.com>
2026-03-11 11:03:40 +01:00
Gábor Balogh 1c83a69481 perf(DASH): Add period caching to speed up manifest parsing (#9353)
Adds period caching to speed up manifest parsing. The aim of this
feature is to improve parsing of length multi-period DASH manifests on
low power devices.
2026-03-11 10:03:10 +01:00
Álvaro Velad Galván 3f4339dbe2 fix(Ads): Fix ended detection when using supportsMultipleMediaElements = false (#9798)
The use of relative URLs in ASSET-LIST is also resolved.

Fixes https://github.com/shaka-project/shaka-player/issues/9797
2026-03-09 13:34:59 +01:00
Álvaro Velad Galván a2726808b3 test: Fix missing getStreamingRetryParameters in tests (#9805) 2026-03-09 10:25:35 +01:00
Álvaro Velad Galván c92c3bddba feat(DASH): Add json format support (#9788)
This initial support is complete but not efficient, as it involves
conversion to XML and normal processing. It should only be used for
testing purposes. Improved support will be added in the future.

Tested with https://github.com/Dash-Industry-Forum/dash-json-schema

Note: This is only added to the experimental build.
2026-03-09 09:52:06 +01:00
Álvaro Velad Galván 90f59213bb fix: Honors streaming.retryParameters for segments (#9796)
Fixes https://github.com/shaka-project/shaka-player/issues/9787
2026-03-06 20:23:25 +01:00
Andres Felipe Losada Luna b61a368b5d feat: add emsgregions, timelineregions, timelineregions as public functions for easy ID3 parsing (#9786)
Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-03-06 11:16:44 -08:00
vlazh 2e732b5392 feat: Add clampAppendWindowToDuration option (#9699)
Fixes #9674
2026-03-06 11:04:00 +01:00
Romualdas Paskevicius d4b05bff62 test(LCEVC): Add Scalable dual-track LCEVC integration tests (#9792)
### Description

Add Scalable dual-track LCEVC integration tests
2026-03-06 10:06:45 +01:00
gmamzn 5b81f70eb0 fix(tXml): Return default value for a missing attribute (#9734)
If the attribute does NOT exist, getAttribute(name) on an element return
an empty string. Empty string '' is not equivalent to 'null'. As a
result 'defaultValue' is not returned, which leads to playback related
issues.
2026-03-02 10:54:20 -08:00
Álvaro Velad Galván 70441a3366 fix(Ads): Fix getting uri of InsertPresentation and ReplacePresentation (#9766)
This changed in one of the last drafts before the final version, so we
have to support both in case someone still implements the draft.
2026-02-26 16:31:40 +01:00
Álvaro Velad Galván e3781c493b feat(DASH): Enable automatic XLink processing with fast detection and performance improvements (#9764)
This PR modernizes and optimizes XLink handling in the DASH parser by
removing the legacy flag-based behavior and replacing it with a
standards‑aligned, fast, and deterministic workflow. The changes improve
performance on large MPDs, simplify configuration, and ensure correct
XLink expansion according to DASH/XLink rules.

XLink processing is now automatically enabled only when needed. If the
MPD contains no XLinks, the parser skips processXlinks entirely.
2026-02-26 14:05:32 +01:00
Álvaro Velad Galván 7a32fa2e4d fix: Handle ID3 EMSG duration according to AOM spec (#9757)
Fixes https://github.com/shaka-project/shaka-player/issues/9753
2026-02-24 16:37:07 +01:00
Álvaro Velad Galván 04c5b104cf fix(HLS): Fix timing of EMSG boxes when using HLS (#9744)
Shaka Player was interpreting EMSG timestamps using the wall-clock
reference of the playlist's initial load, which caused EMSG events to
fire at incorrect times. In HLS, however, the `emsg` timing fields
(`presentation_time` / `presentation_time_delta`) are defined relative
to the segment’s local timescale.

This change normalizes EMSG timestamps using the segment’s `startTime`,
aligning them with Shaka’s internal timeline. As a result, EMSG events
are now triggered at the correct playback time regardless of when the
playlist was first loaded.
2026-02-23 17:30:50 +01:00
Gary Katsevman 8b86ba5f06 fix: delay appending vtt subtitles depending on presence of discontinuity sequence and timestamp offset (#9676)
This PR changes the way that timestamp offsets are stored in the media
source engine. Instead of a single value, it now has a map of values.
For DASH, it should contain a single value, which is the last timestamp
offset available. For HLS, it'll keep track of the timestamp offsets per
discontinuity sequence. If content is appended and we don't yet have a
timestamp offset for that discontinuity sequence number, it'll defer
creating the cues until the timestamp offset is set, otherwise, the
times for the cues may not be correct.

Fixes #9470
2026-02-23 17:23:09 +01:00
Álvaro Velad Galván e59b8b40a7 feat(HLS): Add chapter images (#9738)
Spec:
https://developer.apple.com/documentation/http-live-streaming/providing-javascript-object-notation-json-chapters
2026-02-20 15:04:12 +01:00
Álvaro Velad Galván 88c65c6bbf chore: Reduce the internal complexity of the chapters (#9737)
Instead of saving chapter titles as a URL, they are now saved as a
metadata section that can be expanded in the future.
2026-02-20 11:38:33 +01:00
Andy(김규회) c7368024ae feat: Select default track by a list of preferences (#9542)
I went ahead and implemented the full structured preference system that
was discussed in
https://github.com/shaka-project/shaka-player/issues/1591.
Instead of just expanding languages to arrays, I replaced all 14
individual preference fields with 3 structured arrays:

```tsx
  preferredAudio (language, role, label, channelCount, codec, spatialAudio)
  preferredText (language, role, format, forced)
  preferredVideo (label, role, codec, hdrLevel, layout)
```

Each array entry works as an AND filter - so you can say things like "I
want Korean with 5.1 surround, but if not available, English is fine
too":

```tsx
player.configure('preferredAudio', [
  {language: 'ko', channelCount: 6},
  {language: 'ko'},
  {language: 'en'},
]);
```

<img width="1728" height="965" alt="image"
src="https://github.com/user-attachments/assets/7b088150-139b-475e-bdba-5bc77dd4e524"
/>

**Config** - Replaced the 14 individual fields with 3 arrays of typed
preference objects (AudioPreference, TextPreference, VideoPreference).
The old fields still work at runtime with a deprecation warning, so
existing apps won't break immediately.

**Demo** - The demo config UI now shows inline expandable preference
lists instead of flat text inputs. You can add/remove entries and
configure each field per entry. URL hash serialization was updated to
use JSON format, with legacy param fallbacks preserved.
2026-02-20 10:12:08 +01:00
Álvaro Velad Galván ab09d4dcd7 fix: Do not update the player position with negative playback rates if the video is paused (#9732) 2026-02-20 10:01:37 +01:00
Álvaro Velad Galván 992f2158e5 chore: Remove shaka.media.IClosedCaptionParser interface (#9731) 2026-02-20 09:58:09 +01:00
Álvaro Velad Galván 6826ffa311 feat(CEA): Implement raw CEA-608 packet extraction (#9730)
This format is generated by Apple's HLS tools.
2026-02-19 11:45:18 +01:00
Álvaro Velad Galván 56ac70d44a perf(S2T): Improve SpeechToText code (#9718)
Avoid race conditions when using Translator API.
Avoid unnecessary DOM mutations.
Separate responsibilities in the code.
2026-02-17 10:07:29 +01:00