Skip to content

Conversation

@peaBerberian
Copy link
Collaborator

I was lately working on an application relying on the RxPlayer at Canal+, and trying to see how our upcoming thumbnail API ( #1496 ) could be integrated in their projects.

I found out that this application relied only on getWallClockTime for storing the current playback position.
The value returned by this method is basically the current position offseted so it corresponds to the unix timestamp at which the corresponding media data was intended to be broadcasted.

In other words, doing new Date(wallClockTime * 1000) will translate that position into the corresponding date, whereas our getPosition API, returns a more arbitrary timestamp without special meaning, that we will call here the "media position" (it is the actual position advertised by the HTML video element in the page).

Applications like to use the wallClockTime for live contents as this allows to display a seeking bar with the date in an e.g. hours:minutes:seconds format which is much more useful to a final user than a timestamp without any special meaning.
We even also rely on wallClockTime ourselves on the demo page.

However, most other RxPlayer API rely on the media position instead. For example, getAvailablePeriods, getMinimumPosition, getLiveEdge and future thumbnail API all will provide timestamp in the "meaningless" media position format.


Converting from the wallClockTime to the "media position" and vice-versa was awkward before, you basically had to re-call player.getWallClockTime() - player.getPosition() to obtain the difference and thus to convert the wallClockTime you're using in your application into a media position you can use more easily with the RxPlayer API.

Instead, I propose here to add the player.getWallClockOffset() API, which returns that difference in a more explicit way.

You can then do something like:

function compareWithMaximumPosition(wallClockTime) {
  const wallClockOffset = rxPlayer.getWallClockOffset();
  const currentPosition = wallClockTime - wallClockOffset;

  const maximumPosition = rxPlayer.getMaximumPosition();
  const deltaFromMax = maximumPosition - currentPosition;
  console.log(
    `We are ${deltaFromMax} seconds behind the maximum seekable position`,
  );
}

Which makes more sense and seems feels more stable than randomly re-obtaining the same offset by doing:

const wallClockOffset = player.getWallClockTime() - player.getPosition();

Note that we could have added a rxPlayer.toMediaPosition(wallClockTime) method instead, which may be even more easily discoverable, but I found getWallClockOffset more useful and still approachable.

@peaBerberian peaBerberian added this to the 4.3.0 milestone Dec 23, 2024
@peaBerberian peaBerberian added the Priority: 3 (Low) This issue or PR has a low priority. label Dec 23, 2024
@peaBerberian peaBerberian force-pushed the feat/getwallclockoffset branch from 199f964 to 6f029dc Compare January 28, 2025 14:05
@github-actions
Copy link

Automated performance checks have been performed on commit 6f029dc1f30fe02be018efc61cd6d4ba3ae5ce7c with the base branch dev.

Tests results

✅ Tests have passed.

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 19.47ms -> 19.46ms (0.013ms, z: 0.55837) 27.00ms -> 27.00ms
seeking 11.37ms -> 14.73ms (-3.361ms, z: 0.64321) 11.40ms -> 11.40ms
audio-track-reload 26.13ms -> 26.16ms (-0.029ms, z: 0.07877) 38.40ms -> 38.40ms
cold loading multithread 48.75ms -> 47.21ms (1.538ms, z: 11.17500) 70.35ms -> 69.30ms
seeking multithread 11.98ms -> 13.30ms (-1.314ms, z: 0.42041) 10.65ms -> 10.50ms
audio-track-reload multithread 26.12ms -> 25.93ms (0.189ms, z: 3.28502) 38.55ms -> 38.25ms
hot loading multithread 15.43ms -> 15.41ms (0.021ms, z: 1.23150) 22.50ms -> 22.35ms

If you want to skip performance checks for latter commits, add the skip-performance-checks label to this Pull Request.

@peaBerberian peaBerberian modified the milestones: 4.3.0, 4.4.0 Apr 7, 2025
@peaBerberian peaBerberian force-pushed the dev branch 2 times, most recently from 00fc806 to b7216b4 Compare April 15, 2025 18:14
@peaBerberian peaBerberian force-pushed the feat/getwallclockoffset branch 2 times, most recently from 03842b9 to d45a3f2 Compare April 22, 2025 18:27
@github-actions
Copy link

✅ Automated performance checks have passed on commit 9734a312481b126196621e4b5be13bb86055121a with the base branch dev.

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 20.24ms -> 20.41ms (-0.173ms, z: 0.57942) 27.75ms -> 27.90ms
seeking 20.09ms -> 16.79ms (3.296ms, z: 0.05925) 11.40ms -> 11.40ms
audio-track-reload 26.94ms -> 26.95ms (-0.007ms, z: 0.77022) 39.30ms -> 39.30ms
cold loading multithread 48.52ms -> 48.29ms (0.228ms, z: 12.95981) 71.40ms -> 69.90ms
seeking multithread 25.27ms -> 19.32ms (5.947ms, z: 0.87707) 10.50ms -> 10.50ms
audio-track-reload multithread 26.78ms -> 26.65ms (0.138ms, z: 1.37315) 39.30ms -> 39.15ms
hot loading multithread 16.04ms -> 15.88ms (0.164ms, z: 3.15616) 23.25ms -> 23.10ms

@peaBerberian peaBerberian force-pushed the feat/getwallclockoffset branch from d45a3f2 to 621fb0a Compare June 30, 2025 12:40
@github-actions
Copy link

✅ Automated performance checks have passed on commit ab97eaf13773dab78d0aabbc7e8aa8a831281462 with the base branch dev.

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 19.66ms -> 19.86ms (-0.201ms, z: 0.35517) 27.15ms -> 27.15ms
seeking 11.12ms -> 13.76ms (-2.642ms, z: 0.41872) 11.10ms -> 11.10ms
audio-track-reload 25.91ms -> 25.88ms (0.029ms, z: 0.04344) 37.80ms -> 37.80ms
cold loading multithread 46.33ms -> 45.71ms (0.620ms, z: 12.23085) 67.95ms -> 66.75ms
seeking multithread 35.18ms -> 43.86ms (-8.678ms, z: 1.15724) 10.35ms -> 10.25ms
audio-track-reload multithread 25.93ms -> 25.86ms (0.075ms, z: 0.29727) 38.10ms -> 38.10ms
hot loading multithread 15.06ms -> 14.87ms (0.190ms, z: 4.06753) 21.60ms -> 21.45ms

@peaBerberian peaBerberian force-pushed the feat/getwallclockoffset branch from 621fb0a to d8a4701 Compare July 8, 2025 10:44
@github-actions
Copy link

github-actions bot commented Jul 8, 2025

✅ Automated performance checks have passed on commit 1bac8fc44a6fc078e8001473cb52aeccd247c65f with the base branch dev.

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 20.07ms -> 20.47ms (-0.397ms, z: 0.67487) 27.90ms -> 27.75ms
seeking 13.31ms -> 14.66ms (-1.345ms, z: 0.24046) 11.25ms -> 11.25ms
audio-track-reload 26.45ms -> 26.37ms (0.083ms, z: 0.75977) 38.85ms -> 38.70ms
cold loading multithread 47.03ms -> 46.24ms (0.789ms, z: 14.22782) 69.45ms -> 68.10ms
seeking multithread 34.61ms -> 33.87ms (0.738ms, z: 0.65781) 10.35ms -> 10.35ms
audio-track-reload multithread 26.48ms -> 26.46ms (0.026ms, z: 0.40321) 38.85ms -> 38.85ms
hot loading multithread 15.37ms -> 15.30ms (0.072ms, z: 2.41884) 22.35ms -> 22.35ms

Comment on lines +1622 to +1664
getWallClockOffset(): number {
if (this.videoElement === null) {
return 0;
}
if (this._priv_contentInfos === null) {
return 0;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a documentation for this new method?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@peaBerberian peaBerberian force-pushed the feat/getwallclockoffset branch 2 times, most recently from 7c26dd6 to 8cd4088 Compare August 1, 2025 08:59
@github-actions
Copy link

github-actions bot commented Aug 1, 2025

✅ Automated performance checks have passed on commit b3aac7133d1b05e38ed867a8029b7a4136152059 with the base branch dev.

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 20.46ms -> 20.45ms (0.007ms, z: 0.18241) 28.05ms -> 28.05ms
seeking 22.96ms -> 22.27ms (0.687ms, z: 0.35764) 10.35ms -> 10.35ms
audio-track-reload 26.80ms -> 26.63ms (0.161ms, z: 1.59590) 38.85ms -> 38.70ms
cold loading multithread 47.58ms -> 46.78ms (0.803ms, z: 13.37981) 70.05ms -> 68.85ms
seeking multithread 117.23ms -> 127.34ms (-10.109ms, z: 0.99125) 9.75ms -> 9.75ms
audio-track-reload multithread 26.81ms -> 26.84ms (-0.033ms, z: 0.59945) 39.15ms -> 39.30ms
hot loading multithread 16.23ms -> 16.29ms (-0.060ms, z: 1.18770) 23.55ms -> 23.40ms

I was lately working on an application relying on the RxPlayer at Canal+, and
trying to see how our upcoming thumbnail API could be integrated in their
projects.

I found out that this application relied only on `getWallClockTime` for storing
the current playback position.
The value returned by this method is basically the current position
offseted so it corresponds to the unix timestamp at which the corresponding
media data was intended to be broadcasted.

In other words, doing `new Date(wallClockTime * 1000)` will translate that
position into the corresponding date, whereas our `getPosition` API,
returns a more arbitrary timestamp without special meaning, that we will
call here the "media position" (it is the actual position advertised by
the HTML video element in the page).

Applications like to use the `wallClockTime` for live contents as this
allows to display a seeking bar with the date in an e.g.
`hours:minutes:seconds` format which is much more useful to a final user
than a timestamp without any special meaning.
We even also rely on `wallClockTime` ourselves on the demo page.

However, most other RxPlayer API rely on the media position instead.
For example, `getAvailablePeriods`, `getMinimumPosition`, `getLiveEdge`
and future thumbnail API all will provide timestamp in the "meaningless"
media position format.

---

Converting from the `wallClockTime` to the "media position" and
vice-versa was awkward before, you basically had to re-call
`player.getWallClockTime() - player.getPosition()` to obtain the
difference and thus to convert the `wallClockTime` you're using in your
application into a media position you can use more easily with the
RxPlayer API.

Instead, I propose here to add the `player.getWallClockOffset()` API,
which returns that difference in a more explicit way.

You can then do something like:

```js
function compareWithMaximumPosition(wallClockTime) {
  const wallClockOffset = rxPlayer.getWallClockOffset();
  const currentPosition = wallClockTime - wallClockOffset;

  const maximumPosition = rxPlayer.getMaximumPosition();
  const deltaFromMax = maximumPosition - currentPosition;
  console.log(
    `We are ${deltaFromMax} seconds behind the maximum seekable position`,
  );
}
```

Which makes more sense and seems feels more stable than randomly
re-obtaining the same offset by doing:

```js
const wallClockOffset = player.getWallClockTime() - player.getPosition();
```

Note that we could have added a `rxPlayer.toMediaPosition(wallClockTime)`
method instead, which may be even more easily discoverable, but I found
`getWallClockOffset` more useful and still approachable.
@peaBerberian peaBerberian force-pushed the feat/getwallclockoffset branch from 8cd4088 to 45766be Compare August 1, 2025 09:45
@github-actions
Copy link

github-actions bot commented Aug 1, 2025

✅ Automated performance checks have passed on commit 565eb13d8c25d91c37a67b8e3ab1cd81626ecdaf with the base branch dev.

Details

Performance tests 1st run output

No significative change in performance for tests:

Name Mean Median
loading 19.91ms -> 19.98ms (-0.069ms, z: 0.27967) 27.45ms -> 27.45ms
seeking 19.18ms -> 18.50ms (0.682ms, z: 1.95122) 11.10ms -> 10.95ms
audio-track-reload 26.02ms -> 26.32ms (-0.294ms, z: 1.15296) 38.10ms -> 38.10ms
cold loading multithread 46.39ms -> 46.31ms (0.087ms, z: 13.55392) 68.40ms -> 67.20ms
seeking multithread 35.14ms -> 37.12ms (-1.986ms, z: 0.11169) 10.20ms -> 10.20ms
audio-track-reload multithread 25.93ms -> 25.88ms (0.050ms, z: 0.60729) 38.10ms -> 37.95ms
hot loading multithread 15.17ms -> 15.15ms (0.018ms, z: 1.62177) 22.05ms -> 22.05ms

@peaBerberian peaBerberian merged commit 766e446 into dev Aug 5, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Priority: 3 (Low) This issue or PR has a low priority.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants