Skip to content

Commit

Permalink
[Proposal] Add getWallClockOffset API
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
peaBerberian committed Dec 10, 2024
1 parent acd7b46 commit 199f964
Showing 1 changed file with 46 additions and 4 deletions.
50 changes: 46 additions & 4 deletions src/main_thread/api/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1465,16 +1465,58 @@ class Player extends EventEmitter<IPublicAPIEvent> {
if (this._priv_contentInfos === null) {
return this.videoElement.currentTime;
}
const wallClockOffset = this.getWallClockOffset();
const currentTime = this.videoElement.currentTime;
return currentTime + wallClockOffset;
}

/**
* Get value allowing to convert the media position, as returned by
* `getPosition` to a "wall-clock time", as returned by `getWallClockTime`, by
* additioning the first two:
* ```js
* player.getPosition() + player.getWallClockOffset() === player.getWallClockTime();
* ```
*
* As most of the RxPlayer API relies on the media position as returned by
* `getPosition`, you may want to use this method to simplify conversion if
* what you have right now is a wall-clock time. For example:
*
* ```js
* const wallClockTime = player.getWallClockTime();
*
* // This one is expressed as a media position
* const maximumPosition = player.getMaximumPosition();
*
* // convert wall-clock time to a media position
* const currentPosition = wallClockTime - player.getWallClockOffset();
*
* console.log(
* "delay from maximum position, in seconds",
* maximumPosition - currentPosition
* );
* ```
*
* Note that there's nothing guaranteeing that this offset won't evolve over
* time for a given content. You should call this method every time you need
* to perform the conversion.
* @returns {number}
*/
getWallClockOffset(): number {
if (this.videoElement === null) {
return 0;
}
if (this._priv_contentInfos === null) {
return 0;
}

const { isDirectFile, manifest } = this._priv_contentInfos;
if (isDirectFile) {
const startDate = getStartDate(this.videoElement);
return (startDate ?? 0) + this.videoElement.currentTime;
return startDate ?? 0;
}
if (manifest !== null) {
const currentTime = this.videoElement.currentTime;
const ast = manifest.availabilityStartTime ?? 0;
return currentTime + ast;
return manifest.availabilityStartTime ?? 0;
}
return 0;
}
Expand Down

0 comments on commit 199f964

Please sign in to comment.