Skip to content

v3.33.0

Compare
Choose a tag to compare
@peaBerberian peaBerberian released this 24 Jan 16:39

Release v3.33.0 (2024-01-24)

πŸ” Overview

The v3.33.0 is now available on npm.

It is planned to be the last main v3 release now that the official v4.0.0 is around the corner and became our main focus (a v4.0.0-rc1 will be published just after this one), yet is still contains its share of improvements and bug fixes:

  • DASH: To better support retro-compatible Dolby Vision content, the scte214:supplementalCodecs is now handled. Concerned contents will be advertised under a Dolby Vision codec for compatible devices, or the retro-compatible codec for those who aren't
  • A new getLivePosition method and fromLivePosition startAt option have been added, mainly for advanced ad-switching usages.
  • subtitles: the tts:lineHeight TTML attribute was not properly applied, it is now fixed
  • subtitles: A rare occurence of blinking subtitles could arise, especially on low-latency contents. This also has been fixed.
  • Add the possibility of setting another keySystems option on the reload API.
  • Several fixes on issues that could arise when doing API calls after reaching the last playable position of a content.
  • DEBUG_ELEMENT: Undecipherable and unsupported codecs are now announced in the debug element
  • Multiple other minor fixes and improvements linked to ad-switching, checking of codec support, and low-memory handling.

πŸ“‘ Changelog

Features

  • Add getLivePosition RxPlayer method [#1300]
  • Add startAt.fromLivePosition loadVideo option [#1300]
  • Add the possibility to set a new keySystems option on the reload API [#1308]

Bug fixes

  • Fix subtitles "blinking" in some specific conditions, especially with some DASH low-latency contents [#1314]
  • DASH: Fix Period overlap resolution logic for when the first Period is removed [#1311]
  • TTML: Fix handling of the tts:lineHeight attribute [#1320]
  • Fix import of the LOCAL_MANIFEST experimental feature
  • Avoid very rarely skipping segments which initially were too big to be pushed due to memory limitations [#1323]
  • Fix issue arising when using track APIs at the exact last possible position of a Period with no consecutive Period [#1337]
  • Starting at the end (through a startAt loadVideo option) or reloading at the end led to the restart of the content [#1338]
  • DRM/Safari: also perform Safari DRM work-arounds when the page is launched from the dock [#1351, #1356]

Other improvements

  • DASH: rely on SCTE214 supplementalCodecs instead of codecs if it's supported to better support backward compatible Dolby Vision contents [#1307]
  • DASH: Provide better support of the availabilityTimeOffset attribute [#1300]
  • DEBUG_ELEMENT: Add unsupported and undecipherable bitrates to the debug element [#1321]
  • DEBUG_ELEMENT: update buffer graph maximum size so it becomes more readable for lengthy contents [#1316]
  • DEBUG_ELEMENT: always synchronize inventory of segments before rendering it [#1317]
  • Remove remaining RxPlayer dependency removing possibility of some application-side bundling errors [#1312]
  • Add exception to text Garbage collection logic to avoid unnecessarily reload text segments frequently [#1325]
  • Avoid logging too much the buffer's content when our debugging UI or the demo is used [#1341]
  • Demo: Fix reporting of live position in demo page [#1313]

About it being the last "main v3 release"

As we've reached a point where we plan to release the first official v4.0.0 release, we also plan to make v4 releases our main focus when new features and improvements are added. As such, a v4.0.0-rc1 release should be released just after this release. If our large-scale tests go well, it will become the first v4.0.0 release.

This do not mean that the v3 will become unsupported. It should still receive bug fixes yet:

  1. It will not be the version installed by default through npm / yarn, which will be the v4 instead once the official v4.0.0 version is released.
    The idea will be to set the npm legacy-v3 tag for newer v3 releases, so an rx-player v3 may be installed through something like: npm install rx-player@legacy-v3.

  2. When planning new improvements, we now will implement it on the v4 first, and only backport it to the v3 if it is simple enough with few risks to break.

  3. As more and more applications will rely on the v4 (we already "convinced" many at Canal+ to do so), we will progressively become more aware of issues when they concern the v4 and less about v3 issues.

DASH supplementalCodecs handling

We recently had some issues trying to play Dolby Vision content on LG TVs where the device would not play at all, due to a discrepancy between the video codec announced by the RxPlayer (which did not make mention of Dolby Vision), and the Dolby Vision data actually pushed to the video buffer.

This was because the media stream we've tested make usage of a smart trick: as the Dolby Vision video data was backward-compatible to regular HDR for devices not supporting Dolby Vision, two codecs were actually announced in the content's MPD (the DASH's Manifest file, which list available tracks and qualities):

  • The much more compatible HDR codec, as a codecs attribute (e.g. in a <Representation> or <AdaptationSet> element in the MPD) like expected
  • The Dolby Vision codec, as a scte214:supplementalCodecs property, that we did not process until now

repsupcodec
Screenshot: Content of a DASH MPD with both a codecs property and a supplementalCodecs property in the <Representation> element

The RxPlayer previously only relied on the codecs property (so here not the Dolby Vision video codec) when interacting with lower-level media API.
Though the HDR codec was compatible to the video data, it was actually expected by some Dolby Vision-capable device that the Dolby Vision codec should have been relied on when creating video buffers.

However, if we did rely on the Dolby Vision codec instead through those API, devices which do not handle Dolby Vision video content would not have been able to play the content as just "regular" HDR video data, for them it would have been Dolby Vision, which they do not know how to decode.

So we chose to put a little more intelligence in the RxPlayer, when there is a scte214:supplementalCodecs property (let's call the corresponding codec property the "supplemental codec"):

  • If the supplemental codec is supported by the current device (we can know that through the MediaSource.isTypeSupported API, we consider it to be the actual "codec" of the corresponding video data.
  • If it is not supported, we rely on the codecs instead, just like we did before

suppcodec
Flowchart: How the RxPlayer will decide whether to rely on a scte214:supplementalCodecs or a codecs attribute in a DASH MPD.

This also means that API communicating about video codecs, like the getVideoTrack method, may now actually indicate the "supplemental codec" through their codec property, where it always corresponded in DASH to the corresponding codecs attribute instead).
This should in most case not lead to any change in your application as this is mainly a lower-level detail about a Representation (a.k.a. media quality).

getLivePosition method and startAt.fromLivePosition option

Some applications at Canal+ relying on the RxPlayer make use of "ad-switching" technologies.
Basically, the idea is to replace ads present in a source stream by targeted ads.

There are multiple techniques to implement this, yet for DASH they generally rely on its concept of Periods.
In the MPD (DASH's Manifest file), each of those ads would be defined in a different <Period> element, which is a time-delimited division of the content with its own media tracks and qualities.

multiperiods
Schema: Exemple of a schema representing a DASH multi-Period live content, with an ad break where each Period corresponds to a single Ad.

Another effect of ad-switching is that the server may know in advance which ad should be served to a user.

Let's for example consider a user which plays a live content. That user now encounters an ad-switched ad break at 11:04 AM, which will end 5 minutes later, at 11:09 AM.
Though it is still 11:04, the server already knows which ads it's going to serve to that user from 11:04 to 11:09 (those ads are targeted and already scheduled), so it may want to already announce them in the MPD even though most of those ads are meant to be played in the future.
In turn, the RxPlayer may want to load in advance that new data (reducing the risks of rebuffering comparatively to just loading until the live position) while preventing the user to play further than the "live position" (which is here still 11:04).

livemaxdiff
Schema: Illustration of the aforementioned example, where future ads are already announced and loaded in advance. We can see that the maximum position the RxPlayer will load is much further than the live position we usually want the user to play.

Because in that situation. there may be a difference between the maximum reachable position (here the end of the ad break at 11:09 AM) returned by the getMaximumPosition method and the intended live position (here 11:04 AM) relatively to which the user should probably be playing (note: the RxPlayer doesn't enforce that: the initial position is relative to the live position but the user could then technically seek further than it if the application lets him/her do it), we added the getLivePosition method to let applications know about the latter.

Likewise, we added the startAt.fromLivePosition loadVideo option allowing to set an initial playback position relative to the "live position". Previously that role was filled by start.fromLastPosition but that option is only relative to the maximum position, which now might be very different.

The getLivePosition method is documented here and the startAt loadVideo option here.

Note however that the RxPlayer will only make a live position "guess" when there's an explicit clock that has been communicated to it, either through an <UTCTiming> element in the MPD, or through a serverSyncInfos option.
In other situations, the RxPlayer will infer the live position from various heuristics, including the last position reachable in the Manifest.

Possibility to set a new keySystems when calling reload

In the v3.23.0, we added the reload API allowing to re-load the last loaded content at the last played position.
The idea was to allow an application to reload a since-stopped or failed content with the same options than it was loaded with.

2024-01-24.12-30-31.mp4

Video: action of reloading on the demo page. We can see that we restart back roughly from the same position.

Previously, the reload API had an optional argument, which only allowed to update a reloading position, and to indicate whether the content should auto-play after the reload. The idea was that if you needed to set more options, you would generally prefer to rely on the more powerful loadVideo method instead.

However, it turned out that the most frequent issues we encounter in production are DRM-related, and that many of those can be avoided by setting another DRM configuration.
The main example would be low-level issues we encounter with Microsoft PlayReady SL3000 (hardware-based DRM) that we do not encounter when relying on PlayReady SL2000 (software-based DRM). In many cases, it's not even possible to guess in advance that SL3000 would fail: those problems are generally linked to PlayReady low-level implementation issues.

Specifically for those cases, we decided to add a keySystems property to the reload API, allowing you to reload the last content at its last played position with an updated DRM configuration. This keySystems property follows the exact same syntax than the one for a loadVideo call, and as such is documented at the same location, here.

This new feature thus allows to "reload" right away a content when encountering unexpected but known DRM issues on a given device, improving the quality of experience for the final user.

Multiple minor DEBUG_ELEMENT improvements

We added in v3.30.0 the DEBUG_ELEMENT experimental feature to allow the display of a RxPlayer overlay relying on its internal metadata to provide debugging information. We found it very useful when debugging and so we made some improvements to it in this version.

The most important is that now, undecipherable video and audio qualities are signaled by adding an E! string after the corresponding bitrate in the vb (for "Video Bitrates") and ab (for "Audio Bitrates") parts of the debug element:
encrypted2
Screenshot: The RxPlayer experimental DEBUG_ELEMENT as it can be seen when playing a content on https://www.canalplus.com. Here we can see that both the 3400000 and 4500000 video bitrates are linked to undecipherable video contents (they are followed by E!). Consequently we will not be able to play them.

Likewise, unsupported codecs are signaled by adding an U! string after the corresponding quality's bitrate (note that a quality can both be undecipherable and in an unsupported codec, in which case both E! and U! might be present).

We made other cosmetic changes on this debug element, such as ensuring that the "buffer graphs" are readable (by e.g. limiting their scale if the content is very long) and always up-to-date.