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
97 changes: 97 additions & 0 deletions demo/scripts/controllers/ContentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,10 +260,12 @@ function getKeySystemsOption(

@peaBerberian peaBerberian Aug 29, 2025

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

NOTE: The demo is here modified to be able to test quickly the feature, this would probably be scrapped before merging anything

function ContentList({
loadVideo,
preloadVideo,
showOptions,
onOptionToggle,
}: {
loadVideo: (opts: ILoadVideoOptions) => void;
preloadVideo: (opts: ILoadVideoOptions) => void;
showOptions: boolean;
onOptionToggle: () => void;
}): React.JSX.Element {
Expand Down Expand Up @@ -327,6 +329,43 @@ function ContentList({
[loadVideo],
);

/**
* Load the given displayed content through the player.
* @param {Object|null} content
*/
const preloadContent = React.useCallback(
(content: IDisplayedContent) => {
const {
url,
transport,
fallbackKeyError,
fallbackLicenseRequest,
isLowLatency,
drmInfos,
} = content;

getKeySystemsOption(drmInfos ?? [], {
fallbackKeyError: !!fallbackKeyError,
fallbackLicenseRequest: !!fallbackLicenseRequest,
}).then(
(keySystems) => {
preloadVideo({
url: url ?? "",
transport: transport ?? "",
textTrackMode: "html",
lowLatencyMode: isLowLatency,
keySystems,
});
},
() => {
/* eslint-disable-next-line no-console */
console.error("Could not construct key systems option");
},
);
},
[loadVideo],
);

/**
* Load a custom content entered in a custom link.
* @param {string} url
Expand Down Expand Up @@ -362,6 +401,41 @@ function ContentList({
],
);

/**
* Load a custom content entered in a custom link.
* @param {string} url
* @param {Array.<Object>} drmInfos
*/
const preloadUrl = React.useCallback(
(url: string, drmInfos: IDrmInfo[]) => {
getKeySystemsOption(drmInfos, {
fallbackKeyError: !!shouldFallbackOnKeyError,
fallbackLicenseRequest: !!shouldFallbackOnLicenseReqError,
}).then(
(keySystems) => {
preloadVideo({
url: url,
transport: transportType.toLowerCase(),
textTrackMode: "html",
lowLatencyMode: isLowLatencyChecked,
keySystems,
});
},
() => {
/* eslint-disable-next-line no-console */
console.error("Could not construct key systems option");
},
);
},
[
loadVideo,
shouldFallbackOnKeyError,
shouldFallbackOnLicenseReqError,
transportType,
isLowLatencyChecked,
],
);

/**
* Change the content chosen in the list.
* @param {number} index - index in the lsit
Expand Down Expand Up @@ -530,6 +604,22 @@ function ContentList({
}
};

const onClickPreload = () => {
if (contentChoiceIndex === 0) {
const drmInfos = [
{
licenseServerUrl,
serverCertificateUrl,
drm: chosenDRMType,
customKeySystem,
},
];
preloadUrl(currentManifestURL, drmInfos);
} else {
preloadContent(contentsToSelect[contentChoiceIndex]);
}
};

const saveCurrentContent = () => {
const contentToSave: IContentInfo = {
name: contentNameField,
Expand Down Expand Up @@ -766,6 +856,13 @@ function ContentList({
value={String.fromCharCode(0xf144)}
disabled={false}
/>
<Button
className="choice-input-button load-button"
ariaLabel="Preload the selected content now"
onClick={onClickPreload}
value={String.fromCharCode(0x2b07)}
disabled={false}
/>
</div>
</div>
{isCustomContent || (isLocalContent && isSavingOrUpdating) ? (
Expand Down
39 changes: 37 additions & 2 deletions demo/scripts/controllers/Player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,33 @@ function Player(): React.JSX.Element {
}
}, [playerModule]);

const startContent = useCallback(
const preloadContentCallback = useCallback(
(contentInfo: ILoadVideoOptions) => {
let playerMod = playerModule;

// TODO this risks stopping the previous content if instance options
// have been updated
if (playerMod === null || hasUpdatedPlayerOptions) {
setHasUpdatedPlayerOptions(false);
const created = createNewPlayerModule();
if (created === undefined) {
return;
}
created.actions.updateWorkerMode(relyOnWorker);
playerMod = created;
}
preloadContent(playerMod, contentInfo, loadVideoOpts);
},
[
playerModule,
relyOnWorker,
hasUpdatedPlayerOptions,
createNewPlayerModule,
loadVideoOpts,
],
);

const startContentCallback = useCallback(
(contentInfo: ILoadVideoOptions) => {
let playerMod = playerModule;
if (playerMod === null || hasUpdatedPlayerOptions) {
Expand Down Expand Up @@ -287,7 +313,8 @@ function Player(): React.JSX.Element {
<section className="video-player-section">
<div className="video-player-content">
<ContentList
loadVideo={startContent}
loadVideo={startContentCallback}
preloadVideo={preloadContentCallback}
showOptions={showOptions}
onOptionToggle={onOptionToggle}
/>
Expand Down Expand Up @@ -380,4 +407,12 @@ function loadContent(
playerModule.actions.load(Object.assign({}, contentInfo, loadVideoOpts));
}

function preloadContent(
playerModule: IPlayerModule,
contentInfo: ILoadVideoOptions,
loadVideoOpts: ILoadVideoSettings,
) {
playerModule.actions.preload(Object.assign({}, contentInfo, loadVideoOpts));
}

export default Player;
34 changes: 34 additions & 0 deletions demo/scripts/modules/player/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ export interface IPlayerModuleState {
onAudioTracksNotPlayable: "continue" | "error";
onVideoTracksNotPlayable: "continue" | "error";
playbackRate: number;
preloads: Array<{
url: string | undefined;
id: string;
}>;
/** Try to play contents in "multithread" mode when possible. */
relyOnWorker: boolean;
/** Currently playing a content in "multithread" mode. */
Expand Down Expand Up @@ -204,6 +208,7 @@ const PlayerModule = declareModule(
onAudioTracksNotPlayable: "error",
onVideoTracksNotPlayable: "error",
playbackRate: 1,
preloads: [],
relyOnWorker: false,
useWorker: false,
subtitle: undefined,
Expand Down Expand Up @@ -297,6 +302,35 @@ const PlayerModule = declareModule(
state.update("relyOnWorker", enabled);
},

preload(arg: ILoadVideoOptions) {
const contentInfo = player.preloadVideo(
Object.assign(
{
mode: state.get("relyOnWorker") ? "auto" : "main",
textTrackElement,
transportOptions: { checkMediaSegmentIntegrity: true },
},
arg,
) as ILoadVideoOptions,
);
const preloads = state.get("preloads");
preloads.push({
id: contentInfo.id,
url: arg.url,
});
state.update("preloads", preloads);
},

loadPreload(preloadId: string) {
player.startPreload(preloadId);
const preloads = state.get("preloads");
const index = preloads.findIndex((p) => p.id === preloadId);
if (index >= 0) {
preloads.splice(index, 1);
}
state.update("preloads", preloads);
},

load(arg: ILoadVideoOptions) {
dettachVideoThumbnailLoader();
player.loadVideo(
Expand Down
Loading
Loading