v4.0.0
Release v4.0.0 (2024-02-21)
Quick Links:
π API documentation
-
β― Demo
-
π Migration guide from v3
- π Overview
- π Changelog
- About the v3
- A more flexible track API
- Improved Representation selection
- The new
MULTI_THREAD
experimental feature - More expressive decryption options
- A new player state:
"FREEZING"
π Overview
It's finally time for the official v4.0.0
release with the v4 now becoming our default focus and the default major version when installing the RxPlayer through package managers relying on the npm registry (npm / yarn / pnpm etc.).
If you relied on the 4.0.0-rc.2
before, this release is a quasi-exact copy of that version, with only a minor fix for the representationListUpdate
event - which was previously never triggered.
Because previous v4 beta and release candidate release notes already listed the new features available in v4 in comparison to v3, this release note will only summarize v4 features we consider to be the most important. They already all have been presented in one of the previous release notes.
To migrate from a v3 RxPlayer to a v4 one, you can rely on our migration guide, which lists every API that changed in that major version.
π Changelog
We decided to compile the full v4 changelog into one (instead of splitting and associating it to the various beta and release candidates they have been initially available in).
This lead to an enormous changelog for the v4. To avoid polluting this release note we will just redirect you to our CHANGELOG.md
file, here.
About the v3
We will mainly only add bug fixes and small improvements from now on to the now legacy v3.x.x
versions so it stays stable and usable for people not having time yet to do the switch to the v4.
As such, it should still work as expected, but new features probably won't be added to it, unless you provide the contribution and test cases for it yourself through pull requests.
However, we do recommend you to switch to v4 instead, and not hesitate to open an issue if you find an API change to be unclear or undesirable for your usage.
A more flexible track API
Note: this feature was already presented in the v4.0.0-beta.0
release note.
One of the focus of this new major release was to improve the RxPlayer API on DASH multi-Period contents - which are contents with various set of AdaptationSets (tracks) and Representations (qualities) depending on the time period.
The RxPlayer's previous track API (e.g. setAudioTrack
and getAvailableAudioTracks
) only allowed to get the list and update the track for the currently-playing Period.
// Example setting the first english audio track for the current Period if found
const availableAudioTracks = rxPlayer.getAvailableAudioTracks();
const englishAudioTrack = availableAudioTracks.find((track) => {
return track.language === "eng";
});
if (englishAudioTrack !== undefined) {
rxPlayer.setAudioTrack(englishAudioTrack.id);
}
Now, using the track API this way still works with the same result, but it is also possible to get and set the available tracks for any Period on the content.
// Get the list of Periods currently considered by the RxPlayer:
const availablePeriods = rxPlayer.getAvailablePeriods();
// Get the list of available audio tracks for a given period
const tracks = rxPlayer.getAvailableAudioTracks(availablePeriods[0].id);
// Set an audio track for that Period
rxPlayer.setAudioTrack({
trackId: tracks[0].id,
periodId: availablePeriods[0].id,
});
The new tracks API also let you to choose a behavior when switching from an old to any new track (e.g.: reloading, switching in place with a potential rebuffering or seamlessly) through a new switchingMode
property and also allow to rewind a little (and let you set by how much) in cases where you want to give back some context (for example when switching the audio track to another language).
Last but not least, it is also possible to restrict the Representations (a.k.a. qualities) played under that new track, this will be described in the next chapter.
Some of those features have been described in our "Selecting a Track" tutorial. To have complete informations, you can also refer to our API documentation
Improved Representation selection
Note: this feature was already presented in the v4.0.0-beta.0
release note.
Previous RxPlayer versions only allowed to specify allowed Representation(s) (i.e. qualities) by using bitrate-oriented API.
For example you could call setVideoBitrate
, setMaxVideoBitrate
and setMinVideoBitrate
to either choose a Representation (the first one) or to reduce the ranges of Representations to choose from (the latter two).
In real-life, you might instead want to select Representation(s) based on other criterias. In some more complex use cases, you might only want to allow Representations with a specific codec
property. Both of those were not always possible with the previous API.
We chose to remediate to those issues in the v4 by providing a new API for Representation selection: the "Representation locking" family of API.
For example, the lockVideoRepresentations
method allows to select which Representation for the current video track are allowed to play, the regular RxPlayer's adaptive logic then picking its choice between them, as usual. To lock a single Representation in place, you can just communicate a single Representation's id
to that method:
// Example only playing the Representation with the lowest height in the
// current video track
const videoTrack = rxPlayer.getVideoTrack();
if (videoTrack !== null && videoTrack !== undefined) {
const lowestHeight = videoTrack.representations.sort((a, b) => {
// Put `undefined` heights at the end of the resulting array
if (a.height === undefined) {
return 1; // Put `a` after `b`
} else if (b.height === undefined) {
return -1; // Put `b` after `a`
}
// Sort ascending
return a.height - b.height; // Put the higher height after
})[0]; // Select the lowest one
if (lowestHeight !== undefined) {
// Only play the lowest anounced height
rxPlayer.lockVideoRepresentations([lowestHeight.id]);
}
}
There is a lot more to know on this API, see the lockVideoRepresentations
/ lockAudioRepresentations
documentation page to see all that is can do.
We rely on this new API to display a better quality selection in our demo page for example:
Screenshot: our new demo page now allows a user to select a video quality based on its height and/or the wanted bitrate, thanks to this new API.
We also chose to remove the previous bitrate-related API to simplify the general API of the RxPlayer, considering that its behavior can be completely replaced by the new "Representation locking" methods.
Information on how to make the switch is present in its own page in our migration guide
The new MULTI_THREAD
experimental feature
Note: this feature was already presented in the v4.0.0-rc.1
release note.
This major release also brings the possibility of running most of the RxPlayer main logic in a WebWorker, letting your application to run concurrently with it. This has potentially large positive impacts on performance and adaptive streaming stability (e.g. keeping a stable high video quality).
This new behavior is totally optional and has to be enabled through specific APIs.
The RxPlayer is also able to automatically detect when multithreading is not possible (very old devices), to go back in the regular monothreading mode instead.
Running the RxPlayer without a WebWorker (the default):
+-------------------------------------------------------------------------------+
| Main thread (also running the UI) |
| |
| +------------------+ +----------------------+ +----------------------+ |
| | Application | --> | RxPlayer Main [1] | -> | RxPlayer Core [2] | |
| +------------------+ +----------------------+ +----------------------+ |
+-------------------------------------------------------------------------------+
Running with a WebWorker:
+----------------------------------------------------+
| Main thread (also running the UI) |
| |
| +------------------+ +----------------------+ |
| | Application | ---> | RxPlayer Main [1] | |
| +------------------+ +----------------------+ |
+--------------------------------------|-------------+
| (messages)
+--------------------------------------|-------------+
| WebWorker V |
| +----------------------+ |
| | RxPlayer Core [2] | |
| +----------------------+ |
+----------------------------------------------------+
[1] RxPlayer Main: Exposes an API to the application, performs some high-level
media monitoring, handles content decryption, displays text tracks and interacts
with web API that are only usable in the main thread.
[2] RxPlayer Core; Loads and parses the Manifest as well as media segments that
will be be played. Also monitors what's being played and will be played to
ensure a smooth playback.
Schema: Here is some high level schema of how the RxPlayer would roughly work without and with a WebWorker.
There's many things to say about this new feature and we encourage you to check if it improves the experience on your application.
Everything should be detailed in its API documentation, here.
More expressive decryption options
Note: this feature was already presented in the v4.0.0-beta.0
release note.
We added and updated several decryption-related options, allowing to be more flexible in expressing how to play encrypted contents.
onKeyOutputRestricted
/ onKeyInternalError
Two string properties imitating the already there onKeyExpiration
API have been added:
-
onKeyOutputRestricted
: allows to indicate the behavior the RxPlayer should have when encountering the"output-restricted"
MediaKeyStatus, like fallbacking to another quality or stopping with an error (the default) -
onKeyInternalError
: allows to indicate the behavior the RxPlayer should have when encountering the"internal-error "
MediaKeyStatus, like here also fallbacking to another quality or stopping with an error (the default)
Because it allows more powerful configuration than the previous fallbackOn
option, the latter has been removed.
persistentState
/ distinctiveIdentifier
The v4.0.0
major release adds two string properties to the keySystems
option of loadVideo
:
-
persistentState
: Indicate if the CDM should be able to persist state. It actually reflects theMediaKeySystemConfiguration
property of the same name, taking the same possible values. -
distinctiveIdentifier
: Indicate if the CDM can or even should use distinctive identifiers. Here also, this property reflects theMediaKeySystemConfiguration
property of the same name.
Because, they allow the easy replacement of respectively the persistentStateRequired
and of the distinctiveIdentifierRequired
boolean properties of keySystems
, both of those have been removed.
videoCapabilitiesConfig
/ audioCapabilitiesConfig
Two keySystems
properties videoCapabilitiesConfig
and audioCapabilitiesConfig
now allow to configure respectively the videoCapabilities
and audioCapabilities
properties of the asked MediaKeySystemConfiguration
.
Relatively powerful, this option allows to configure the asked codecs, robustnesses or both.
Like the other ones presented here, this option provokes the removal of the less powerful videoRobustnesses
and audioRobustnesses
undocumented options.
A new player state: "FREEZING"
Note: this chapter was first written for the v4.0.0-beta.0
release note.
A new player state (gettable either through the playerStateChange
event or the getPlayerState
method) has been added: "FREEZING"
.
It's important to note that this new new state does not characterize a new behavior, it only put a better word onto a specific problematic playback state. Previously, it was either reported as a "BUFFERING"
, "SEEKING"
, or even "PLAYING"
state depending on the situation.
This state appears when playback is temporarily stuck in place, though in opposition to the more usual "BUFFERING"
and "SEEKING"
state, this is not due to buffer starvation but to another, generally unknown, factor. As such, it can in most cases be considered just like a "BUFFERING"
state in your application (e.g. by displaying a spinner on top of the media element) but it may be logged differently to help you pinpoint playback issues.
Screenshot: A "FREEZING"
state can be treated just like a "BUFFERING"
one, here with a spinner on top of the video.
Under that state, which is generally much rarer than a "BUFFERING"
state for example, the RxPlayer will try various tricks to try to un-freeze playback. If they become too frequent or if those tricks don't work, it might be an issue worth investigating.