Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src/main_thread/api/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import {
toVideoRepresentation,
toAudioRepresentation,
} from "../../manifest";
import type { IThumbnailTrackMetadata } from "../../manifest/types";
import type { IPlaybackObservation } from "../../playback_observer";
import MediaElementPlaybackObserver from "../../playback_observer/media_element_playback_observer";
import type {
Expand Down Expand Up @@ -865,6 +866,11 @@ class Player extends EventEmitter<IPublicAPIEvent> {
width: Math.floor(t.width / t.horizontalTiles),
height: Math.floor(t.height / t.verticalTiles),
mimeType: t.mimeType,
start: t.start,
end: t.end,
thumbnailDuration: t.tileDuration,
thumbnailsPerSegment: t.horizontalTiles * t.verticalTiles,
lastThumbnailTime: this._getLastThumbnailTime(t),
};
});
}
Expand Down Expand Up @@ -3573,6 +3579,48 @@ class Player extends EventEmitter<IPublicAPIEvent> {
this.trigger("error", formattedError);
}
}

/**
* For the given track, returns the position in seconds that will
* correspond to the currently last reachable thumbnail, or `undefined` if
* unknown.
*
* That position may then be passed to the `rxPlayer.renderThumbnail()` method.
*
* @param {Object} metadata
* @returns {number|undefined}
*/
private _getLastThumbnailTime(metadata: IThumbnailTrackMetadata): number | undefined {
if (metadata.start === undefined || metadata.tileDuration === undefined) {
return;
}

const maximumPosition = this.getMaximumPosition() ?? undefined;
if (maximumPosition === undefined) {
return;
}

const thumbnailsPerSegment = metadata.horizontalTiles * metadata.verticalTiles;

/** Amount of seconds a segment of thumbnails span. */
const segmentDuration = metadata.tileDuration * (thumbnailsPerSegment ?? 1);

/**
* Seconds at the end of the content for which a thumbnail has not yet been
* generated.
*/
const secondsWithoutThumbnailYet =
(maximumPosition - metadata.start) % segmentDuration;

/**
* Position that will lead to the last available thumbnail being requested.
*/
const maxThumbnailTime =
Math.min(maximumPosition - secondsWithoutThumbnailYet, metadata.end ?? Infinity) -
metadata.tileDuration;

return maxThumbnailTime;
}
}
Player.version = /* PLAYER_VERSION */ "4.4.0";

Expand Down
58 changes: 58 additions & 0 deletions src/public_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,64 @@ export interface IThumbnailTrackInfo {
* `image/jpeg` or `image/png`.
*/
mimeType: string | undefined;
/**
* Starting `position` the first thumbnail of this thumbnail track applies to,
* if known.
*/
start: number | undefined;
/**
* Ending `position` the last thumbnail of this thumbnail track applies to,
* if known.
*/
end: number | undefined;
/**
* Individual thumbnails may be technically part of "segments" containing
* multiple consecutive thumbnails each.
*
* `thumbnailsPerSegment` is the number of `thumbnails` each segments have.
*
* For example you could have stored on the server a segment which is a grid
* of 2 x 3 (2 horizontal rows and 3 vertical columns) thumbnails, which the
* RxPlayer will load at once then "cut" the right way when calling
* `renderThumbnail`. In that example, `thumbnailsPerSegment` would be set to
* `6` (2*3).
*
* Note that the last segment of a content may contain less thumbnails as
* anounced here depending on the duration of the content.
*
* You may want to rely on this information alongside `thumbnailDuration` to
* construct a list of available thumbnails and/or of available segments of
* thumbnails.
*/
thumbnailsPerSegment: number | undefined;
/**
* When loaded, thumbnails are part of so-called "segments" which may contain
* either a single thumbnail or a grid of them (@see `thumbnailsPerSegment`).
*
* This `thumbnail` property indicates a duration in seconds each thumbnail
* apply to.
* You can multiply that value with `thumbnailsPerSegment` to get the amount
* of time each segment applies to.
*
* Set to `undefined` either the duration is unknown or if the duration
* depends from segment to segments.
*
* For example, with a `start` set to `10`, an `end` set to `26`, a
* `thumbnailsPerSegment` set to `2` and a `tileDuration` set to
* `3`, there should be 3 segments, each with 2 thumbnails of 3 seconds each:
* 1. A segment of 2 thumbnails for the seconds: 10-16
* (The first thumbnail in that segment for 10-13, the second for 13-16)
* 2. A segment of 2 thumbnails for the seconds: 16-22
* (The first thumbnail in that segment for 16-19, the second for 19-22)
* 3. A segment of 2 thumbnails for the seconds: 22-26 (the end)
* (The first thumbnail in that segment for 22-25, the second for 25-26)
*/
thumbnailDuration: number | undefined;
/**
* The time the current last thumbnail avaiable for that track applies to,
* in seconds.
*/
lastThumbnailTime: number | undefined;
}

/**
Expand Down
Loading