video-ad-sdk
Version:
VAST/VPAID SDK that allows video ads to be played on top of any player
68 lines (67 loc) • 2.56 kB
JavaScript
import { linearEvents } from '../../../../tracker';
import { formatProgress } from '../../progress/formatProgress';
const { progress } = linearEvents;
const secondsToMilliseconds = (seconds) => seconds * 1000;
const isPercentage = (offset) => {
const percentageRegex = /^\d+(\.\d+)?%$/g;
return percentageRegex.test(offset) && !isNaN(parseFloat(offset));
};
const isValid = ({ offset, uri }) => {
const offsetIsValid = typeof offset === 'number' || Boolean(offset && isPercentage(offset));
const uriIsValid = typeof uri === 'string' && uri.length > 0;
return offsetIsValid && uriIsValid;
};
const PERCENTAGE_FACTOR = 100;
const offsetToMs = (offset, durationInMs) => {
if (typeof offset === 'number') {
return offset;
}
return (parseFloat(offset) / PERCENTAGE_FACTOR) * durationInMs;
};
export const onProgress = ({ videoElement }, callback, { progressEvents = [] } = {}) => {
const { duration } = videoElement;
const durationInMs = secondsToMilliseconds(duration);
let playedMs = 0;
let previousCurrentTime = secondsToMilliseconds(videoElement.currentTime);
let pendingEvents = progressEvents
.filter(isValid)
.map(({ offset, uri }) => ({
offset: offsetToMs(offset, durationInMs),
uri
}));
const progressHandler = () => {
const { currentTime } = videoElement;
const delta = Math.abs(currentTime - previousCurrentTime);
playedMs += secondsToMilliseconds(delta);
previousCurrentTime = currentTime;
const { stillPending, toCall } = pendingEvents.reduce((accumulator, event) => {
const { offset } = event;
if (typeof offset === 'number' && playedMs >= offset) {
accumulator.toCall.push(event);
}
else {
accumulator.stillPending.push(event);
}
return accumulator;
}, {
stillPending: [],
toCall: []
});
pendingEvents = stillPending;
toCall.forEach(({ uri }) => {
callback(progress, {
contentplayhead: formatProgress(playedMs),
progressUri: uri
});
});
if (pendingEvents.length === 0) {
videoElement.removeEventListener('timeupdate', progressHandler);
}
};
if (pendingEvents.length > 0) {
videoElement.addEventListener('timeupdate', progressHandler);
}
return () => {
videoElement.removeEventListener('timeupdate', progressHandler);
};
};