Skip to content

Commit

Permalink
refactor: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
amtins committed Feb 28, 2024
1 parent 1ee1686 commit 9ab8fb8
Show file tree
Hide file tree
Showing 7 changed files with 1,108 additions and 963 deletions.
39 changes: 39 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@
src: 'urn:rts:video:14683290',
type: 'srgssr/urn'
},
_endDate: {
label: 'Block reason end date',
src: 'urn:rts:video:10894367',
type: 'srgssr/urn'
},
_externalSubtitles: {
label: 'Remote text tracks',
src: 'urn:swi:video:48864812',
type: 'srgssr/urn'
},
};

// Expose Pillarbox and player in the window object for debugging
Expand Down Expand Up @@ -83,6 +93,35 @@
src: urn,
type: "srgssr/urn",
});

player.on('loadeddata', () => {
player?.textTracks()?.getTrackById('srgssr-chapters')?.addEventListener("cuechange", () => {
const [cue] = Array.from(player?.textTracks()?.getTrackById('srgssr-chapters')?.activeCues);
if (!cue) return;

console.log('%cChapter', 'background-color: blue', JSON.parse(cue.text).title);

const chapter = JSON.parse(cue.text);
player.titleBar.update({
title: chapter.title,
description: chapter.description
});
});

player?.textTracks()?.getTrackById('srgssr-blocked-segments')?.addEventListener("cuechange", () => {
const [cue] = Array.from(player?.textTracks()?.getTrackById('srgssr-blocked-segments')?.activeCues);
if (!cue) return;

console.log('%cBlock reason', 'background-color: red', JSON.parse(cue.text).blockReason);
});

player?.textTracks()?.getTrackById('srgssr-intervals')?.addEventListener("cuechange", () => {
const [cue] = Array.from(player?.textTracks()?.getTrackById('srgssr-intervals')?.activeCues);
if (!cue) return;

console.log('%cInterval', 'background-color: green', JSON.parse(cue.text).type);
});
});
</script>
</body>

Expand Down
9 changes: 6 additions & 3 deletions src/dataProvider/model/MediaComposition.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class MediaComposition {
*
* @returns {Array} array of sources
*/
// eslint-disable-next-line max-lines-per-function
getMainResources() {
const resourceList = this.getResourceList();

Expand All @@ -197,13 +198,14 @@ class MediaComposition {
),
blockReason: this.getMainChapter().blockReason,
blockedSegments: this.getMainBlockedSegments(),
chapterImageUrl: this.getMainChapterImageUrl(),
chapters: this.getChapters(),
vendor: this.getMainChapter().vendor,
drmList: resource.drmList,
dvr: resource.dvr,
eventData: this.getMainChapter().eventData,
id: this.getMainChapter().id,
imageCopyright: this.getMainChapter().imageCopyright,
intervals: this.getMainTimeIntervals(),
live: resource.live,
mediaType: this.getMainChapter().mediaType,
mimeType: resource.mimeType,
Expand All @@ -212,10 +214,11 @@ class MediaComposition {
streaming: resource.streaming,
streamOffset: resource.streamOffset,
subtitles: this.getFilteredExternalSubtitles(),
intervals: this.getMainTimeIntervals(),
title: this.getMainChapter().title,
tokenType: resource.tokenType,
url: resource.url,
urn: this.chapterUrn
urn: this.chapterUrn,
vendor: this.getMainChapter().vendor,
}));
}

Expand Down
182 changes: 123 additions & 59 deletions src/middleware/srgssr.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,18 @@ class SrgSsr {
*
* @returns {undefined|Boolean}
*/
static blockingReason(player, blockReason, srcMediaObj) {
if (!blockReason) return;
static blockingReason(player, srcMediaObj) {
if (!srcMediaObj.mediaData.blockReason) return;

const message = player.localize(blockReason);
const message = player.localize(srcMediaObj.mediaData.blockReason);

SrgSsr.error(player, {
code: MediaError.MEDIA_ERR_ABORTED,
message,
metadata: { errorType: blockReason, src: srcMediaObj },
metadata: {
errorType: srcMediaObj.mediaData.blockReason,
src: srcMediaObj
},
});

return true;
Expand Down Expand Up @@ -416,6 +419,110 @@ class SrgSsr {
return resource || resources[0];
}

/**
* Get the source media object.
*
* @param {import('video.js/dist/types/player').default} player
* @param {Object} srcObj
*
* @returns {Promise<Object>} - The composed source media data.
*/
static async getSrcMediaObj(player, srcObj) {
const { src: urn, ...srcOptions } = srcObj;
const { mediaComposition } = await SrgSsr.getMediaComposition(
urn,
SrgSsr.dataProvider(player)
);
const mainResources = await SrgSsr.composeMainResources(
mediaComposition
);
const mediaData = SrgSsr.getMediaData(mainResources);

return SrgSsr.composeSrcMediaData(srcOptions, mediaData);
}

/**
* Handles the middleware's current time function.
* - If the current time is between the start and end of a blocked segment,
* the blocked portion will be skipped.
*
* _Note_: This function should disappear as soon as this behavior is
* supported on the packaging side.
*
* @param {import('video.js/dist/types/player').default} player
* @param {number} currentTime
*
* @returns {number}
*/
static handleCurrentTime(player, currentTime) {
const blockedSegmentEndTime = SrgSsr
.getBlockedSegmentEndTime(player, currentTime);

if (Number.isFinite(blockedSegmentEndTime)) {
player.currentTime(blockedSegmentEndTime);

return blockedSegmentEndTime;
}

return currentTime;
}

/**
* Handles the middleware's set current time function.
* - Modify the current time if the value is between the start and end of a
* blocked segment.
*
* _Note_: This function should disappear as soon as this behavior is
* supported on the packaging side.
*
* @param {import('video.js/dist/types/player').default} player
* @param {number} currentTime
*
* @returns {number}
*/
static handleSetCurrentTime(player, currentTime) {
const blockedSegmentEndTime = SrgSsr
.getBlockedSegmentEndTime(player, currentTime);

return Number
.isFinite(blockedSegmentEndTime) ? blockedSegmentEndTime : currentTime;
}

/**
* Handles the middleware's set set source function.
*
* This function allows to:
* - resolve a URN into media that can be played by the player
* - initialize media playback tracking
* - update the title bar
* - handle blocking reasons
* - add remote subtitles
*
* @param {import('video.js/dist/types/player').default} player
* @param {number} currentTime
*
* @returns {number}
*/
static async handleSetSource(player, srcObj, next) {
try {
const srcMediaObj = await SrgSsr.getSrcMediaObj(player, srcObj);

SrgSsr.srgAnalytics(player);
SrgSsr.updateTitleBar(player, srcMediaObj);
SrgSsr.updatePoster(player, srcMediaObj);

if (SrgSsr.blockingReason(player, srcMediaObj)) return;

SrgSsr.addTextTracks(player, srcMediaObj);

return next(null, srcMediaObj);
} catch (error) {
if (SrgSsr.dataProviderError(player, error)) return;

return next(error);
}
}

/**
* SRG SSR analytics singleton.
*
Expand Down Expand Up @@ -447,10 +554,10 @@ class SrgSsr {
* @param {import('../dataProvider/model/MediaComposition.js').default} mediaComposition
* @param {Image} imageService
*/
static updatePoster(player, mediaComposition, imageService = Image) {
static updatePoster(player, { mediaData }, imageService = Image) {
player.poster(
imageService.scale({
url: mediaComposition.getMainChapterImageUrl(),
url: mediaData.chapterImageUrl,
})
);
}
Expand All @@ -461,73 +568,30 @@ class SrgSsr {
* @param {import('video.js/dist/types/player').default} player
* @param {import('../dataProvider/model/MediaComposition.js').default} mediaComposition
*/
static updateTitleBar(player, mediaComposition) {
static updateTitleBar(player, { mediaData }) {
if (!player.titleBar) return;

player.titleBar.update({
title: mediaComposition.getMainChapter().vendor,
description: mediaComposition.getMainChapter().title,
title: mediaData.vendor,
description: mediaData.title,
});
}

/**
* Middleware to resolve SRG SSR URNs into playable media.
*
* @param {import('video.js/dist/types/player').default} player
* @param {Image} imageService
*
* @returns {Object}
*/
/* eslint-disable max-lines-per-function */
static middleware(player, imageService = Image) {
static middleware(player) {
return {
currentTime: (currentTime) => {
const blockedSegmentEndTime = SrgSsr
.getBlockedSegmentEndTime(player, currentTime);

if (Number.isFinite(blockedSegmentEndTime)) {
player.currentTime(blockedSegmentEndTime);
}

return blockedSegmentEndTime ?? currentTime;
},
setCurrentTime: (currentTime) => {
return SrgSsr
.getBlockedSegmentEndTime(player, currentTime) ?? currentTime;
},
/* eslint max-statements: ["error", 20]*/
setSource: async (srcObj, next) => {
try {
const { src: urn, ...srcOptions } = srcObj;
const { mediaComposition } = await SrgSsr.getMediaComposition(
urn,
SrgSsr.dataProvider(player)
);
const mainResources = await SrgSsr.composeMainResources(
mediaComposition
);
const mediaData = SrgSsr.getMediaData(mainResources);
const srcMediaObj = SrgSsr.composeSrcMediaData(srcOptions, mediaData);

SrgSsr.srgAnalytics(player);
SrgSsr.updateTitleBar(player, mediaComposition);
SrgSsr.updatePoster(player, mediaComposition, imageService);

if (SrgSsr.blockingReason(player, mediaData.blockReason, srcMediaObj))
return;

SrgSsr.addRemoteTextTracks(player, mediaData.subtitles);
SrgSsr.addChapters(player, mediaData.urn, mediaData.chapters);
SrgSsr.addBlockedSegments(player, mediaData.blockedSegments);
SrgSsr.addIntervals(player, mediaData.intervals);

return next(null, srcMediaObj);
} catch (error) {
if (SrgSsr.dataProviderError(player, error)) return;

return next(error);
}
},
currentTime: (currentTime) =>
SrgSsr.handleCurrentTime(player, currentTime),
setCurrentTime: (currentTime) =>
SrgSsr.handleSetCurrentTime(player, currentTime),
setSource: async (srcObj, next) =>
SrgSsr.handleSetSource(player, srcObj, next),
};
}
}
Expand Down
Loading

0 comments on commit 9ab8fb8

Please sign in to comment.