Commit Graph

1386 Commits

Author SHA1 Message Date
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 f8abc76dcf docs: Fix NO_VIDEO_ELEMENT doc on v5 (#9697) 2026-02-11 13:16:48 +01:00
Andy(김규회) d98169bc25 feat(EME): Add retryLicensing() and failureCallback for manual license retry (#9638)
So basically, when a license request fails (eg. network Error, server
down whatever), apps can now retry from scratch by calling
`player.retryLicensing()`. This was tricky to implement because of EME
spec limitations: `generateRequest()` can only be called once per
session. So if it fails, it would be stuck.

So I close the old session and create a brand new one with the same
`initData`

> Will Video element throw an error during this process?

we were worried that closing the session would leave the video without
keys for a brief moment, potentially triggering errors. But in practice,
the transition is fast enough( I added a 0.1s delay for CDM clean up)
and the video element handles it gracefully

> Will new encrypted event fire? If not, will it limit this feature?

The encrypted event only fires when the browser first encounters
encrypted content. When we close and recreate a session, the content is
already loaded, so no new event

Solutions: In `CreateSession()` metadata store `initData` and
`initDataType` in the session metadata when the session is first
created. So when `retryLicensing()`is called, we just grab the stored
data and pass it to `generateRequest()` on the new session. No need to
wait for an `encrypted` event at all.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-02-05 14:12:30 +01:00
Álvaro Velad Galván c200219fa2 test: Fix UI tests on SmartTVs (#9660)
Tests fixed:

```
  UI Customization
    ✗ big buttons only created when configured [Safari 3.0 (Tizen 3.0)]
	Error: Expected 1 to be 0.
	    at <Jasmine>
	    at Function.confirmElementMissing (test/test/util/ui_utils.js:70:29 <- test/test/util/ui_utils.js:139:31)
	    at _callee6$ (test/ui/ui_customization_unit.js:86:13 <- test/ui/ui_customization_unit.js:152:21)
	    at tryCatch (node_modules/@babel/polyfill/dist/polyfill.js:6473:40)
  UI
    controls
      controls-button-panel
        ✗ has default elements [Safari 3.0 (Tizen 3.0)]
	Error: Expected 1 to be 0.
	    at <Jasmine>
	    at Function.confirmElementMissing (test/test/util/ui_utils.js:70:29 <- test/test/util/ui_utils.js:139:31)
	    at _callee15$ (test/ui/ui_unit.js:425:19 <- test/ui/ui_unit.js:506:27)
	    at tryCatch (node_modules/@babel/polyfill/dist/polyfill.js:6473:40)

```
2026-02-05 07:09:13 +01:00
Álvaro Velad Galván bd167c3744 feat: Add listenMulti and listenOnceMulti to shaka.util.EventManager (#9652)
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-02-03 21:49:35 +01:00
Álvaro Velad Galván 6fc70622eb chore: Change frameRate from string to number in shaka.media.SegmentUtils.BasicInfo (#9627)
Related to https://github.com/shaka-project/shaka-player/pull/9626
2026-01-29 17:13:20 +01:00
Álvaro Velad Galván 674e71d064 fix(Ads): Harden MediaTailorAdManager state and cuepoint handling (#9619)
This change improves MediaTailor ad handling by:
- Deduplicating cue points to avoid repeated ad markers
- Guarding ad break listener setup to prevent event duplication
- Cleaning up ad state more defensively on stop/end
- Improving static resource caching and tracking robustness

These fixes prevent duplicate events, listener leaks, and inconsistent
ad playback during manifest updates and polling.

---------

Co-authored-by: Theodore Abshire <TheodoreAbshire@Gmail.com>
Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-01-29 12:39:14 +01:00
Álvaro Velad Galván 793749a6e2 perf: Minor performance optimizations in TXml text processing and root lookup (#9622)
- Avoid repeated split() when matching expected root element names
- Improve text content concatenation to reduce string allocations
- Remove unnecessary Array.from() usage when checking text-only children
2026-01-28 19:08:09 +01:00
Álvaro Velad Galván a1b5ffa510 chore: Remove unused params in shaka.util.Mp4BoxParsers (#9615) 2026-01-27 17:52:14 +01:00
Álvaro Velad Galván d452350d57 feat!: Remove shaka.util.XmlUtils (#9616)
It is removed because there is no longer any dependency on it anywhere
in the code.
2026-01-27 17:52:00 +01:00
Álvaro Velad Galván 71af24f82b feat: Only disallow SourceBuffer.changeType on PlayReady when using Edge browser (#9603)
More info in
https://chromium-review.googlesource.com/c/chromium/src/+/4577759 and
https://issues.chromium.org/issues/40261162

According to the source code and empirical testing, SMOOTH is supported
with clear content and Widevine, but not with PlayReady.
2026-01-26 12:12:53 +01:00
Andy(김규회) eac68c7ea0 feat(EME): Add manual and automatic license renewal API (#9589)
Widevine's CDM handles renewal automatically, but FairPlay and PlayReady
require manual
`session.update()` calls to renew licenses before they expire.
Previously, developers had to access internal APIs like
`getDrmEngine().activeSessions_` which only works in debug builds - not
ideal for production use.
Based on the discussion in #9505, this PR implements both Option A and
Option C:
**Option A - Manual renewal API:**
```js
player.renewLicense(); // all sessions
player.renewLicense(sessionId); // specific session
 ``` 
  **Option C - Automatic renewal with config:**
```js
player.configure({
drm: {
renewalIntervalSec: 600
}
});
player.addEventListener('licenserenewal', (event) => {
console.log('License renewed:', event.newSessionMetadata,
event.oldSessionMetadata);
  });
```
This way, developers can choose automatic renewal, manual control, or
both depending on their use case.
Under the hood, FairPlay sends a 'renew' message via session.update(),
while PlayReady re-creates the session. Widevine just dispatches the
event since the CDM already handles everything.
2026-01-26 11:49:26 +01:00
Wojciech Tyczyński 482117f6c8 fix(ContentWorkarounds): Insert PSSH boxes for fake init encryption (#9600)
Related to #8048

Some platforms (i.e. NOS STB) are not able to play encrypted content
without PSSH boxes in init segments. This PR addresses it by adding PSSH
boxes with actual data if we have it.
2026-01-26 10:15:39 +01:00
Wojciech Tyczyński 5c05132772 feat!: Use shared logic for MediaError details (#9594) 2026-01-22 20:50:32 +01:00
Álvaro Velad Galván 4c945af650 feat(MSF): Add support for custom namespaces via config (#9586) 2026-01-22 14:00:12 +01:00
Álvaro Velad Galván 5ee77799f5 chore: Remove unused code (#9584) 2026-01-21 14:08:36 +01:00
Woody Hill 66b0c74a01 fix: parseHDLR for Apple QuickTime hdlr box compatibility (#9577)
Apple QuickTime places a manufacturer field ('appl') immediately after
the handler type ('soun'), causing readTerminatedString() to incorrectly
read 'sounappl' instead of 'soun'. This breaks Opus fMP4 audio playback
for content packaged with Apple tools.

Replace null-terminated string parsing with fixed-length byte reading to
extract exactly 4 bytes for the handler type.

Closes #9576

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-01-20 12:59:31 +01:00
Wojciech Tyczyński 9af54837c7 chore: Mp4Generator - make segmentInfos array optional (#9569) 2026-01-17 04:44:03 +01:00
Álvaro Velad Galván e96442c409 feat: Add new config to allow stop fetching new segments on pause (#9567)
Close https://github.com/shaka-project/shaka-player/issues/9386
2026-01-16 07:37:08 +01:00
Álvaro Velad Galván e5d9471fa5 feat(HLS): Add AES-256-GCM support (#9562)
More info in:
https://datatracker.ietf.org/doc/draft-pantos-hls-rfc8216bis/19/ and
https://mailarchive.ietf.org/arch/msg/hls-interest/85CoeMS9O2zRoMff_Xx_WgCukJg/
2026-01-15 14:18:02 +01:00
Álvaro Velad Galván bdfd028088 feat(HLS): Support chapters on Live and custom config to add it (#9561)
Co-authored-by: Theodore Abshire <TheodoreAbshire@Gmail.com>
2026-01-15 09:47:11 +01:00
Álvaro Velad Galván ef361ed039 feat: Add MoQT draft-14 + WARP/MSF draft-1 experimental support (#9409)
Spec: https://datatracker.ietf.org/doc/draft-ietf-moq-transport/14/
Spec: https://datatracker.ietf.org/doc/draft-ietf-moq-warp/01/

Note: this is experimental and not included in the default builds

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2026-01-14 09:27:10 +01:00
Andy(김규회) 05b09728c7 perf: Use Map.getOrInsert/getOrInsertComputed native methods (#9546)
Added polyfills for `Map.getOrInsert()` and
`Map.getOrInsertComputed()` from the TC39 upsert proposal and refactor
the codebase to use them.
These methods replace the common "check if key exists, then set default"
pattern with a single atomic operation. This improves code readability
and eliminates redundant map lookups throughout the player.

---------

Co-authored-by: Álvaro Velad Galván <ladvan91@hotmail.com>
2026-01-13 10:57:25 +01:00
Wojciech Tyczyński 1c18dea798 chore: Remove encrypted property from StreamInfo (#9547)
Simplify interface a bit
2026-01-07 15:03:11 +01:00
Álvaro Velad Galván 909655f4eb feat: Add configurationchanged event (#9531) 2025-12-19 16:35:35 +01:00
Álvaro Velad Galván c6e6082bc2 feat: Allow override subtitle position (#9522)
Close https://github.com/shaka-project/shaka-player/issues/9521

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2025-12-19 13:38:33 +01:00
Álvaro Velad Galván d5be5d6f45 feat!: Text displayers should receive a shaka.Player pointer (#9515)
Related to https://github.com/shaka-project/shaka-player/issues/9301
2025-12-17 10:11:00 +01:00
Álvaro Velad Galván 86bfea08aa feat!: Move speech to text to the accessibility section in config (#9507) 2025-12-16 12:37:44 +01:00
Álvaro Velad Galván 1ace441355 feat: Handle forced subtitles automatically by default (configurable) (#9497)
Close https://github.com/shaka-project/shaka-player/issues/9489

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2025-12-16 09:40:58 +01:00
Álvaro Velad Galván 687f0ee26e feat(ABR): Remove abr.removeLatencyFromFirstPacketTime config (#9496)
Close https://github.com/shaka-project/shaka-player/issues/9475
2025-12-12 10:30:17 +01:00
Matthias Van Parijs 73ee27bf17 feat!: Remove autoShowText and simplify initial text track selection (#9435)
This is the first step in a series of efforts to simplify how we handle
text tracks internally.

The purpose of `autoShowText` has always felt a bit unclear. It was
originally added because Shaka wasn't flexible enough when choosing an
initial text track. I don't think we should try to handle every possible
scenario for initial text track selection. Instead, we should respect
`config.preferredTextLanguage` and let the application decide if it
needs more granular control. Apps can already do this easily with
`getTextTracks()` and `selectTextTrack(track)`.

Ultimately, I'd like to move toward a simpler API where either a text
track is selected or none is. If nothing is selected, we shouldn't
stream any text at all.

See https://github.com/shaka-project/shaka-player/issues/9301 for extra
context.
2025-12-12 09:41:15 +01:00
Joey Parrish a84c6b53c3 fix: Do not exclude time to first byte from measurements by default (#9476)
`removeLatencyFromFirstPacketTime: true` causes time to first byte to be
excluded from throughput measurements, greatly inflating bandwidth
estimates by as much as 2x. This causes elevated rebuffering rates.

Measurements were taken on various Cast models, as well as Chrome on
Linux. In all cases, bandwidth estimates after 60 seconds of 4K Sintel
with the flag set to `true` were about 2x what they would be with the
flag set to `false`.

It appears that time to first byte is excluded from all requests, rather
than just the first segment as is implied by the config docs. It's also
unclear to me, at least, what this was supposed to accomplish, even if
only applied to one segment. For now I'm neither removing nor attempting
to fix the feature, until we can discuss the original thinking behind
it.

As an emergency fix, because the default behavior was so problematic,
this changes the default to `false`. Applications that know better than
me still have the option to set it explicitly to `true` for now.

See issue #9475, which will stay open until we decide what to do with
this flag and its implementation.
2025-12-06 09:50:32 -08:00
Álvaro Velad Galván 215404911f perf: Prefer Uint8Array's {to,from}{Base64,Hex} methods (#9472)
Close: https://github.com/shaka-project/shaka-player/issues/9469
2025-12-05 09:21:09 +01:00
Álvaro Velad Galván 8d7a15b2be fix: Fix exception reading audio-only content (#9465)
Fixes https://github.com/shaka-project/shaka-player/issues/9458
2025-12-03 11:13:12 -08:00
Álvaro Velad Galván f6905035d9 feat(Ads): Allow configure interstitial preload ahead time (#9464) 2025-12-03 11:27:25 +01:00
Álvaro Velad Galván 35f187ee0c fix: text track active property when using src= (#9462)
This is necessary because NativeTextDisplayer and UITextDisplayer work
differently.

---------

Co-authored-by: Wojciech Tyczyński <tykus160@gmail.com>
2025-12-03 11:22:56 +01:00
Álvaro Velad Galván 2c1ab30d71 fix: Avoid audio streams filtering and use AdaptationSetCriteria instead (#9457)
This is part to remove dontChooseCodecs config in the future.
2025-12-03 10:31:38 +01:00
Joey Parrish 4d99357bbe chore: Clean up and comment stream filtering (#9453)
In chooseCodecsAndFilterManifest, there was a real lack of comments. So
first and foremost, this adds comments.

Second, group IDs for audio & video streams were made by concatenating
various properties, but without delimiters, so there may have been a
possibility for collisions. This adds delimiters in the group ID
construction.

Third, streams are already sorted by bandwidth before we start grouping
them, so the grouping code for audio & video doesn't need to check
`stream.bandwidth < previousStream.bandwidth`. This should always be
true.

Fourth, the video stream sorting conditions were too nested and hard to
read. This flattens those out in a way that makes them easier to
understand.

Finally, because we're always only allowing one codec per group,
skipping a stream due to `!supportsSmoothSwitch` makes no sense. We're
only ever adding streams to our filter list when their codecs match
what's already in the group. So the check on `supportsSmoothSwitch` is
removed.
2025-12-02 09:11:28 +01:00
Álvaro Velad Galván 2a454911c9 fix(FairPlay): Fix FairPlay compatibility with DASH (#9436)
This creates an initdata for FairPlay if one is not defined, which is
what happens in DASH when there is no PSSH
2025-11-26 12:12:53 +01:00
absidue 888f6d3e13 fix: text track active property with SRC_EQUALS load mode (#9418)
This fixes the `active` property on text tracks returned by
`Player#getTextTracks()` still being `true` after calling
`Player#selectTextTrack(null)` when the load mode is `SRC_EQUALS`, this
was also causing the text track selector to still show the text track as
selected after clicking `Off`.

The text track selector UI issue is only a problem on the main branch
(v5.0) as #9048 hasn't been released in any of the release branches yet.
2025-11-21 23:14:06 +01:00
Gábor Balogh 219c733015 fix(DASH): Memory leak on DASH streams (#9369)
Fixes https://github.com/shaka-project/shaka-player/issues/9368
2025-11-21 09:55:00 +01:00
Álvaro Velad Galván 9ff4134dee chore: Update shaka.media.SegmentUtils.BasicInfo to include drmInfos info (#9402)
Co-authored-by: Theodore Abshire <TheodoreAbshire@Gmail.com>
2025-11-18 11:44:03 +01:00
Álvaro Velad Galván db14699b22 chore: Make public the codec regexps (#9399)
This is useful for being able to use regular expressions elsewhere in
the code without having to duplicate them.
2025-11-17 15:13:44 +01:00
Dan Rossi d79d001093 feat: Add a bufferAppending event (#9377)
Close #9328
2025-11-14 13:23:36 +01:00
Álvaro Velad Galván 643e2c8b62 feat!: Simplify shaka.ads.AdManager interface (#9357) 2025-11-06 13:29:42 +01:00
Constanza Dibueno ac2d390807 feat(CMCDv2): Response Received (#9362) 2025-11-06 10:10:20 +01:00
Álvaro Velad Galván c920ecd4fa chore: Move createSegmentRequest to shaka.net.NetworkingUtils (#9363) 2025-11-05 21:05:49 +01:00
Álvaro Velad Galván e85b648ef0 feat!: Remove MSS support (#9329)
Related to https://github.com/shaka-project/shaka-player/issues/9321
2025-11-04 20:06:44 +01:00
Álvaro Velad Galván 856cb53768 fix: Fix default modifyCueCallback config (#9322) 2025-10-31 12:37:21 +01:00
Romualdas Paskevicius 3143505f1d fix(UI): Support non-square pixels in getResolutionLabel_ (#9300)
The changes in this PR add support for non-square pixels, e.g. SAR value
of 2:1 (or any other) to the Resolution Selection Menu.

Currently, some contents can be falsely detected as portrait video by
getResolutionLabel_, e.g. a 960x1080p content with a SAR value of 2:1
would be detected as portrait and have its width and height swapped by
getResolutionLabel_. However it is a landscape content: the horizontal
pixels would be stretched to display a horizontal video.
2025-10-29 12:04:02 +01:00