Add pre-roll ads
change ad macro url rework video.js load logic fix autoplay and retry errors yeet player.ended error fix another race condition fix another error message add allowPreRoll restrictions fix some lint issues remove annoying lint rule remove video.js lazy loading more linting fixes
This commit is contained in:
parent
0de6be77de
commit
b777669a7e
7 changed files with 316 additions and 83 deletions
|
@ -35,6 +35,7 @@
|
||||||
"object-curly-spacing": 0,
|
"object-curly-spacing": 0,
|
||||||
"one-var": 0,
|
"one-var": 0,
|
||||||
"prefer-promise-reject-errors": 0,
|
"prefer-promise-reject-errors": 0,
|
||||||
|
"promise/param-names": 0,
|
||||||
"react/jsx-indent": 0,
|
"react/jsx-indent": 0,
|
||||||
"react/jsx-no-comment-textnodes": 0,
|
"react/jsx-no-comment-textnodes": 0,
|
||||||
"react-hooks/exhaustive-deps": "warn",
|
"react-hooks/exhaustive-deps": "warn",
|
||||||
|
|
|
@ -60,6 +60,8 @@
|
||||||
"remove-markdown": "^0.3.0",
|
"remove-markdown": "^0.3.0",
|
||||||
"source-map-explorer": "^2.5.2",
|
"source-map-explorer": "^2.5.2",
|
||||||
"tempy": "^0.6.0",
|
"tempy": "^0.6.0",
|
||||||
|
"videojs-contrib-ads": "^6.9.0",
|
||||||
|
"videojs-ima": "^1.11.0",
|
||||||
"videojs-logo": "^2.1.4"
|
"videojs-logo": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Created by xander on 6/21/2021
|
||||||
|
import videojs from 'video.js';
|
||||||
|
import 'videojs-ima';
|
||||||
|
const VERSION = '0.0.1';
|
||||||
|
|
||||||
|
const macroUrl =
|
||||||
|
'https://vast.aniview.com/api/adserver61/vast/?AV_PUBLISHERID=60afcbc58cfdb065440d2426&AV_CHANNELID=60b354389c7adb506d0bd9a4&AV_URL=[URL_MACRO]&cb=[TIMESTAMP_MACRO]&AV_WIDTH=[WIDTH_MACRO]&AV_HEIGHT=[HEIGHT_MACRO]&AV_SCHAIN=[SCHAIN_MACRO]&AV_CCPA=[CCPA_MACRO]&AV_GDPR=[GDPR_MACRO]&AV_CONSENT=[CONSENT_MACRO]&skip=true&skiptimer=5&usevslot=true&hidecontrols=false';
|
||||||
|
|
||||||
|
const defaults = {
|
||||||
|
adTagUrl: macroUrl,
|
||||||
|
debug: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const Component = videojs.getComponent('Component');
|
||||||
|
const registerPlugin = videojs.registerPlugin || videojs.plugin;
|
||||||
|
|
||||||
|
class AniviewPlugin extends Component {
|
||||||
|
constructor(player, options) {
|
||||||
|
super(player, options);
|
||||||
|
|
||||||
|
// Plugin started
|
||||||
|
if (options.debug) {
|
||||||
|
this.log(`Created aniview plugin.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// To help with debugging, we'll add a global vjs object with the video js player
|
||||||
|
window.aniview = player;
|
||||||
|
|
||||||
|
this.player = player;
|
||||||
|
|
||||||
|
const google = window.google;
|
||||||
|
|
||||||
|
player.ima({
|
||||||
|
// adTagUrl: macroUrl,
|
||||||
|
id: 'ad_content_video',
|
||||||
|
vpaidMode: google.ima.ImaSdkSettings.VpaidMode.INSECURE,
|
||||||
|
adTagUrl:
|
||||||
|
'https://vast.aniview.com/api/adserver61/vast/?AV_PUBLISHERID=60afcbc58cfdb065440d2426&AV_CHANNELID=60b354389c7adb506d0bd9a4',
|
||||||
|
});
|
||||||
|
|
||||||
|
// this.player.ads();
|
||||||
|
// const serverUrl = this.player.ads.adMacroReplacement(macroUrl);
|
||||||
|
// this.log(serverUrl);
|
||||||
|
|
||||||
|
// request ads whenever there's new video content
|
||||||
|
player.on('contentchanged', () => {
|
||||||
|
// in a real plugin, you might fetch your ad inventory here
|
||||||
|
player.trigger('adsready');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Plugin event listeners
|
||||||
|
player.on('readyforpreroll', (event) => this.onReadyForPreroll(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
onReadyForPreroll(event) {
|
||||||
|
this.player.ads.startLinearAdMode();
|
||||||
|
|
||||||
|
// play your linear ad content
|
||||||
|
// in this example, we use a static mp4
|
||||||
|
this.player.src('kitteh.mp4');
|
||||||
|
|
||||||
|
// send event when ad is playing to remove loading spinner
|
||||||
|
this.player.one('adplaying', () => {
|
||||||
|
this.player.trigger('ads-ad-started');
|
||||||
|
});
|
||||||
|
|
||||||
|
// resume content when all your linear ads have finished
|
||||||
|
this.player.one('adended', () => {
|
||||||
|
this.player.ads.endLinearAdMode();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
log(...args) {
|
||||||
|
if (this.options_.debug) {
|
||||||
|
console.log(`Aniview Debug:`, JSON.stringify(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
videojs.registerComponent('recsys', AniviewPlugin);
|
||||||
|
|
||||||
|
const onPlayerReady = (player, options) => {
|
||||||
|
player.aniview = new AniviewPlugin(player, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the plugin.
|
||||||
|
*
|
||||||
|
* @function plugin
|
||||||
|
* @param {Object} [options={}]
|
||||||
|
*/
|
||||||
|
const plugin = function (options) {
|
||||||
|
this.ready(() => {
|
||||||
|
onPlayerReady(this, videojs.mergeOptions(defaults, options));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin.VERSION = VERSION;
|
||||||
|
|
||||||
|
registerPlugin('aniview', plugin);
|
||||||
|
|
||||||
|
export default plugin;
|
|
@ -13,8 +13,13 @@ import hlsQualitySelector from './plugins/videojs-hls-quality-selector/plugin';
|
||||||
import recsys from './plugins/videojs-recsys/plugin';
|
import recsys from './plugins/videojs-recsys/plugin';
|
||||||
import qualityLevels from 'videojs-contrib-quality-levels';
|
import qualityLevels from 'videojs-contrib-quality-levels';
|
||||||
import isUserTyping from 'util/detect-typing';
|
import isUserTyping from 'util/detect-typing';
|
||||||
|
import 'videojs-contrib-ads';
|
||||||
|
import 'videojs-ima';
|
||||||
|
// import aniview from './plugins/videojs-aniview/plugin';
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV !== 'production';
|
const isDev = process.env.NODE_ENV !== 'production';
|
||||||
|
const macroUrl =
|
||||||
|
'https://vast.aniview.com/api/adserver61/vast/?AV_PUBLISHERID=60afcbc58cfdb065440d2426&AV_CHANNELID=60b354389c7adb506d0bd9a4&AV_URL=[URL_MACRO]&cb=[TIMESTAMP_MACRO]&AV_WIDTH=[WIDTH_MACRO]&AV_HEIGHT=[HEIGHT_MACRO]&AV_SCHAIN=[SCHAIN_MACRO]&AV_CCPA=[CCPA_MACRO]&AV_GDPR=[GDPR_MACRO]&AV_CONSENT=[CONSENT_MACRO]&skip=true&skiptimer=5&usevslot=true&hidecontrols=false';
|
||||||
|
|
||||||
export type Player = {
|
export type Player = {
|
||||||
on: (string, (any) => void) => void,
|
on: (string, (any) => void) => void,
|
||||||
|
@ -54,6 +59,7 @@ type Props = {
|
||||||
adUrl: ?string,
|
adUrl: ?string,
|
||||||
claimId: ?string,
|
claimId: ?string,
|
||||||
userId: ?number,
|
userId: ?number,
|
||||||
|
allowPreRoll: ?boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
type VideoJSOptions = {
|
type VideoJSOptions = {
|
||||||
|
@ -78,7 +84,7 @@ const VIDEO_JS_OPTIONS: VideoJSOptions = {
|
||||||
responsive: true,
|
responsive: true,
|
||||||
controls: true,
|
controls: true,
|
||||||
html5: {
|
html5: {
|
||||||
hls: {
|
vhs: {
|
||||||
overrideNative: !videojs.browser.IS_ANY_SAFARI,
|
overrideNative: !videojs.browser.IS_ANY_SAFARI,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -190,6 +196,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
adUrl,
|
adUrl,
|
||||||
claimId,
|
claimId,
|
||||||
userId,
|
userId,
|
||||||
|
allowPreRoll,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [reload, setReload] = useState('initial');
|
const [reload, setReload] = useState('initial');
|
||||||
|
@ -321,7 +328,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
// clashes if we add a new button in the future.
|
// clashes if we add a new button in the future.
|
||||||
// (2) We'll have to get 'makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)'
|
// (2) We'll have to get 'makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)'
|
||||||
// as a prop here so we can say "Theater mode|Default mode" instead of
|
// as a prop here so we can say "Theater mode|Default mode" instead of
|
||||||
// "Toggle Theather mode".
|
// "Toggle Theater mode".
|
||||||
controlBar.getChild('Button').controlText(__('Toggle Theater mode (t)'));
|
controlBar.getChild('Button').controlText(__('Toggle Theater mode (t)'));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -337,6 +344,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
// The css starts as "hidden". We make it visible here without
|
// The css starts as "hidden". We make it visible here without
|
||||||
// re-rendering the whole thing.
|
// re-rendering the whole thing.
|
||||||
showTapButton(TAP.UNMUTE);
|
showTapButton(TAP.UNMUTE);
|
||||||
|
} else {
|
||||||
|
showTapButton(TAP.NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,6 +360,10 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
showTapButton(TAP.RETRY);
|
showTapButton(TAP.RETRY);
|
||||||
|
|
||||||
|
// reattach initial play listener in case we recover from error successfully
|
||||||
|
// $FlowFixMe
|
||||||
|
player.one('play', onInitialPlay);
|
||||||
|
|
||||||
if (player && player.loadingSpinner) {
|
if (player && player.loadingSpinner) {
|
||||||
player.loadingSpinner.hide();
|
player.loadingSpinner.hide();
|
||||||
}
|
}
|
||||||
|
@ -473,9 +486,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
|
|
||||||
// Create the video DOM element and wrapper
|
// Create the video DOM element and wrapper
|
||||||
function createVideoPlayerDOM(container) {
|
function createVideoPlayerDOM(container) {
|
||||||
if (!container) {
|
if (!container) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This seems like a poor way to generate the DOM for video.js
|
// This seems like a poor way to generate the DOM for video.js
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement('div');
|
||||||
|
@ -489,19 +500,51 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function detectFileType() {
|
||||||
|
console.log(`Detecting file type via pre-fetch...`);
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(source, { method: 'HEAD', cache: 'no-store' });
|
||||||
|
|
||||||
|
// Temp variables to hold results
|
||||||
|
let finalType = sourceType;
|
||||||
|
let finalSource = source;
|
||||||
|
|
||||||
|
// override type if we receive an .m3u8 (transcoded mp4)
|
||||||
|
// do we need to check if explicitly redirected
|
||||||
|
// or is checking extension only a safer method
|
||||||
|
if (response && response.redirected && response.url && response.url.endsWith('m3u8')) {
|
||||||
|
finalType = 'application/x-mpegURL';
|
||||||
|
finalSource = response.url;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`File type is: ${finalType}`);
|
||||||
|
|
||||||
|
// Modify video source in options
|
||||||
|
videoJsOptions.sources = [
|
||||||
|
{
|
||||||
|
src: finalSource,
|
||||||
|
type: finalType,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return res(videoJsOptions);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to pre-fetch video!`);
|
||||||
|
return rej(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize video.js
|
// Initialize video.js
|
||||||
function initializeVideoPlayer(el) {
|
function initializeVideoPlayer(el) {
|
||||||
if (!el) {
|
if (!el) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const vjs = videojs(el, videoJsOptions, () => {
|
const vjs = videojs(el, videoJsOptions, () => {
|
||||||
const player = playerRef.current;
|
const player = playerRef.current;
|
||||||
|
|
||||||
// this seems like a weird thing to have to check for here
|
// this seems like a weird thing to have to check for here
|
||||||
if (!player) {
|
if (!player) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add various event listeners to player
|
// Add various event listeners to player
|
||||||
player.one('play', onInitialPlay);
|
player.one('play', onInitialPlay);
|
||||||
|
@ -517,13 +560,45 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
// Replace volume bar with custom LBRY volume bar
|
// Replace volume bar with custom LBRY volume bar
|
||||||
LbryVolumeBarClass.replaceExisting(player);
|
LbryVolumeBarClass.replaceExisting(player);
|
||||||
|
|
||||||
|
// Add reloadSourceOnError plugin
|
||||||
|
player.reloadSourceOnError({ errorInterval: 10 });
|
||||||
|
|
||||||
// initialize mobile UI
|
// initialize mobile UI
|
||||||
player.mobileUi(); // Inits mobile version. No-op if Desktop.
|
player.mobileUi(); // Inits mobile version. No-op if Desktop.
|
||||||
|
|
||||||
|
// Add quality selector to player
|
||||||
|
player.hlsQualitySelector({
|
||||||
|
displayCurrentQuality: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add recsys plugin
|
||||||
|
// TODO: Add an if(odysee.com) around this function to only use recsys on odysee
|
||||||
|
player.recsys({
|
||||||
|
videoId: claimId,
|
||||||
|
userId: userId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// set playsinline for mobile
|
||||||
|
// TODO: make this better
|
||||||
|
player.children_[0].setAttribute('playsinline', '');
|
||||||
|
|
||||||
// I think this is a callback function
|
// I think this is a callback function
|
||||||
onPlayerReady(player);
|
onPlayerReady(player);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// pre-roll ads
|
||||||
|
// This must be initialized earlier than everything else
|
||||||
|
// otherwise a race condition occurs if we place this in the onReady call back
|
||||||
|
if (allowPreRoll && !SIMPLE_SITE && window.google) {
|
||||||
|
const google = window.google;
|
||||||
|
// player.aniview();
|
||||||
|
vjs.ima({
|
||||||
|
// $FlowFixMe
|
||||||
|
vpaidMode: google.ima.ImaSdkSettings.VpaidMode.INSECURE,
|
||||||
|
adTagUrl: macroUrl,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
|
// fixes #3498 (https://github.com/lbryio/lbry-desktop/issues/3498)
|
||||||
// summary: on firefox the focus would stick to the fullscreen button which caused buggy behavior with spacebar
|
// summary: on firefox the focus would stick to the fullscreen button which caused buggy behavior with spacebar
|
||||||
vjs.on('fullscreenchange', () => document.activeElement && document.activeElement.blur());
|
vjs.on('fullscreenchange', () => document.activeElement && document.activeElement.blur());
|
||||||
|
@ -534,16 +609,21 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
// This lifecycle hook is only called once (on mount), or when `isAudio` changes.
|
// This lifecycle hook is only called once (on mount), or when `isAudio` changes.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const vjsElement = createVideoPlayerDOM(containerRef.current);
|
const vjsElement = createVideoPlayerDOM(containerRef.current);
|
||||||
const vjsPlayer = initializeVideoPlayer(vjsElement);
|
|
||||||
|
|
||||||
// Add reference to player to global scope
|
// Detect source file type via pre-fetch (async)
|
||||||
window.player = vjsPlayer;
|
detectFileType().then(() => {
|
||||||
|
// Initialize Video.js
|
||||||
|
const vjsPlayer = initializeVideoPlayer(vjsElement);
|
||||||
|
|
||||||
// Set reference in component state
|
// Add reference to player to global scope
|
||||||
playerRef.current = vjsPlayer;
|
window.player = vjsPlayer;
|
||||||
|
|
||||||
// Add event listener for keyboard shortcuts
|
// Set reference in component state
|
||||||
window.addEventListener('keydown', handleKeyDown);
|
playerRef.current = vjsPlayer;
|
||||||
|
|
||||||
|
// Add event listener for keyboard shortcuts
|
||||||
|
window.addEventListener('keydown', handleKeyDown);
|
||||||
|
});
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -561,51 +641,28 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// For some reason the video player is responsible for detecting content type this way
|
// For some reason the video player is responsible for detecting content type this way
|
||||||
fetch(source, { method: 'HEAD', cache: 'no-store' }).then((response) => {
|
fetch(source, { method: 'HEAD', cache: 'no-store' }).then((response) => {
|
||||||
const player = playerRef.current;
|
let finalType = sourceType;
|
||||||
|
|
||||||
if (!player) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let type = sourceType;
|
|
||||||
let finalSource = source;
|
let finalSource = source;
|
||||||
|
|
||||||
// override type if we receive an .m3u8 (transcoded mp4)
|
// override type if we receive an .m3u8 (transcoded mp4)
|
||||||
|
// do we need to check if explicitly redirected
|
||||||
|
// or is checking extension only a safer method
|
||||||
if (response && response.redirected && response.url && response.url.endsWith('m3u8')) {
|
if (response && response.redirected && response.url && response.url.endsWith('m3u8')) {
|
||||||
type = 'application/x-mpegURL';
|
finalType = 'application/x-mpegURL';
|
||||||
finalSource = response.url;
|
finalSource = response.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update player poster
|
// Modify video source in options
|
||||||
// note: the poster prop seems to return null usually.
|
videoJsOptions.sources = [
|
||||||
if (poster) player.poster(poster);
|
{
|
||||||
|
src: finalSource,
|
||||||
|
type: finalType,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// Update player source
|
// Update player source
|
||||||
player.src({
|
const player = playerRef.current;
|
||||||
src: finalSource,
|
if (!player) return;
|
||||||
type: type,
|
|
||||||
});
|
|
||||||
|
|
||||||
// set playsinline for mobile
|
|
||||||
player.children_[0].setAttribute('playsinline', '');
|
|
||||||
|
|
||||||
// Add quality selector to player
|
|
||||||
player.hlsQualitySelector({
|
|
||||||
displayCurrentQuality: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add recsys plugin
|
|
||||||
if (SIMPLE_SITE) {
|
|
||||||
player.recsys({
|
|
||||||
videoId: claimId,
|
|
||||||
userId: userId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update player source
|
|
||||||
player.src({
|
|
||||||
src: finalSource,
|
|
||||||
type: type,
|
|
||||||
});
|
|
||||||
|
|
||||||
// PR #5570: Temp workaround to avoid double Play button until the next re-architecture.
|
// PR #5570: Temp workaround to avoid double Play button until the next re-architecture.
|
||||||
if (!player.paused()) {
|
if (!player.paused()) {
|
||||||
|
@ -614,6 +671,20 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
});
|
});
|
||||||
}, [source, reload]);
|
}, [source, reload]);
|
||||||
|
|
||||||
|
// Load IMA3 SDK for aniview
|
||||||
|
useEffect(() => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`;
|
||||||
|
script.async = true;
|
||||||
|
// $FlowFixMe
|
||||||
|
document.body.appendChild(script);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
// $FlowFixMe
|
||||||
|
document.body.removeChild(script);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
<div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef}>
|
<div className={classnames('video-js-parent', { 'video-js-parent--ios': IS_IOS })} ref={containerRef}>
|
||||||
|
|
|
@ -178,7 +178,9 @@ function VideoViewer(props: Props) {
|
||||||
} else if (autoplaySetting) {
|
} else if (autoplaySetting) {
|
||||||
setShowAutoplayCountdown(true);
|
setShowAutoplayCountdown(true);
|
||||||
}
|
}
|
||||||
}, [embedded, setIsEndededEmbed, autoplaySetting, setShowAutoplayCountdown, adUrl, setAdUrl]);
|
|
||||||
|
clearPosition(uri);
|
||||||
|
}, [embedded, setIsEndededEmbed, autoplaySetting, setShowAutoplayCountdown, adUrl, setAdUrl, clearPosition, uri]);
|
||||||
|
|
||||||
function onPlay(player) {
|
function onPlay(player) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
@ -187,21 +189,17 @@ function VideoViewer(props: Props) {
|
||||||
setIsEndededEmbed(false);
|
setIsEndededEmbed(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPause(player) {
|
function onPause(event, player) {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
handlePosition(player);
|
handlePosition(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDispose(player) {
|
function onDispose(event, player) {
|
||||||
handlePosition(player);
|
handlePosition(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePosition(player) {
|
function handlePosition(player) {
|
||||||
if (player.ended()) {
|
savePosition(uri, player.currentTime());
|
||||||
clearPosition(uri);
|
|
||||||
} else {
|
|
||||||
savePosition(uri, player.currentTime());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function restorePlaybackRate(player) {
|
function restorePlaybackRate(player) {
|
||||||
|
@ -233,18 +231,13 @@ function VideoViewer(props: Props) {
|
||||||
|
|
||||||
Promise.race([playPromise, timeoutPromise]).catch((error) => {
|
Promise.race([playPromise, timeoutPromise]).catch((error) => {
|
||||||
if (typeof error === 'object' && error.name && error.name === 'NotAllowedError') {
|
if (typeof error === 'object' && error.name && error.name === 'NotAllowedError') {
|
||||||
// Autoplay disallowed by browser
|
if (player.autoplay() && !player.muted()) {
|
||||||
player.play();
|
// player.muted(true);
|
||||||
}
|
// another version had player.play()
|
||||||
|
}
|
||||||
// Autoplay failed
|
|
||||||
if (PLAY_TIMEOUT_ERROR) {
|
|
||||||
setIsLoading(false);
|
|
||||||
setIsPlaying(false);
|
|
||||||
} else {
|
|
||||||
setIsLoading(false);
|
|
||||||
setIsPlaying(false);
|
|
||||||
}
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
setIsPlaying(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,10 +252,9 @@ function VideoViewer(props: Props) {
|
||||||
player.on('tracking:buffered', doTrackingBuffered);
|
player.on('tracking:buffered', doTrackingBuffered);
|
||||||
player.on('tracking:firstplay', doTrackingFirstPlay);
|
player.on('tracking:firstplay', doTrackingFirstPlay);
|
||||||
player.on('ended', onEnded);
|
player.on('ended', onEnded);
|
||||||
player.on('play', () => onPlay(player));
|
player.on('play', onPlay);
|
||||||
player.on('pause', () => onPause(player));
|
player.on('pause', (event) => onPause(event, player));
|
||||||
player.on('dispose', () => onDispose(player));
|
player.on('dispose', (event) => onDispose(event, player));
|
||||||
|
|
||||||
player.on('error', () => {
|
player.on('error', () => {
|
||||||
const error = player.error();
|
const error = player.error();
|
||||||
if (error) {
|
if (error) {
|
||||||
|
@ -348,6 +340,7 @@ function VideoViewer(props: Props) {
|
||||||
autoplay={!embedded || autoplayIfEmbedded}
|
autoplay={!embedded || autoplayIfEmbedded}
|
||||||
claimId={claimId}
|
claimId={claimId}
|
||||||
userId={userId}
|
userId={userId}
|
||||||
|
allowPreRoll={!embedded && !authenticated}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -571,9 +571,9 @@ video::-internal-media-controls-overlay-cast-button {
|
||||||
|
|
||||||
.file-render {
|
.file-render {
|
||||||
.video-js {
|
.video-js {
|
||||||
display: flex;
|
/*display: flex;*/
|
||||||
align-items: center;
|
/*align-items: center;*/
|
||||||
justify-content: center;
|
/*justify-content: center;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.vjs-big-play-button {
|
.vjs-big-play-button {
|
||||||
|
|
68
yarn.lock
68
yarn.lock
|
@ -1266,6 +1266,25 @@
|
||||||
tough-cookie "^2.2.2"
|
tough-cookie "^2.2.2"
|
||||||
tough-cookie-web-storage-store "^1.0.0"
|
tough-cookie-web-storage-store "^1.0.0"
|
||||||
|
|
||||||
|
"@hapi/boom@9.x.x":
|
||||||
|
version "9.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.2.tgz#48bd41d67437164a2d636e3b5bc954f8c8dc5e38"
|
||||||
|
integrity sha512-uJEJtiNHzKw80JpngDGBCGAmWjBtzxDCz17A9NO2zCi8LLBlb5Frpq4pXwyN+2JQMod4pKz5BALwyneCgDg89Q==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/hoek" "9.x.x"
|
||||||
|
|
||||||
|
"@hapi/cryptiles@^5.1.0":
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hapi/cryptiles/-/cryptiles-5.1.0.tgz#655de4cbbc052c947f696148c83b187fc2be8f43"
|
||||||
|
integrity sha512-fo9+d1Ba5/FIoMySfMqPBR/7Pa29J2RsiPrl7bkwo5W5o+AN1dAYQRi4SPrPwwVxVGKjgLOEWrsvt1BonJSfLA==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/boom" "9.x.x"
|
||||||
|
|
||||||
|
"@hapi/hoek@9.x.x":
|
||||||
|
version "9.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131"
|
||||||
|
integrity sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==
|
||||||
|
|
||||||
"@hot-loader/react-dom@^16.13":
|
"@hot-loader/react-dom@^16.13":
|
||||||
version "16.13.0"
|
version "16.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.13.0.tgz#de245b42358110baf80aaf47a0592153d4047997"
|
resolved "https://registry.yarnpkg.com/@hot-loader/react-dom/-/react-dom-16.13.0.tgz#de245b42358110baf80aaf47a0592153d4047997"
|
||||||
|
@ -3014,6 +3033,11 @@ camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1:
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||||
|
|
||||||
|
can-autoplay@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/can-autoplay/-/can-autoplay-3.0.0.tgz#fc2de8f1d41b36f6d860d9336b66841d30f8b62d"
|
||||||
|
integrity sha512-qQXGGYPWgF8nPjEt305o3TJ/BkN15l6/wG+VU4N93YYXD3OtYkBBx+l5un7ihIk2UU1OLytAVJjW7ZR39j/CAQ==
|
||||||
|
|
||||||
caniuse-api@^3.0.0:
|
caniuse-api@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
||||||
|
@ -5157,7 +5181,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
|
||||||
assign-symbols "^1.0.0"
|
assign-symbols "^1.0.0"
|
||||||
is-extendable "^1.0.1"
|
is-extendable "^1.0.1"
|
||||||
|
|
||||||
extend@^3.0.0, extend@~3.0.1:
|
extend@>=3.0.2, extend@^3.0.0, extend@~3.0.1:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
|
||||||
|
|
||||||
|
@ -7455,6 +7479,11 @@ lodash-es@^4.17.14, lodash-es@^4.2.1:
|
||||||
version "4.17.15"
|
version "4.17.15"
|
||||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
||||||
|
|
||||||
|
lodash._reinterpolate@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||||
|
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
|
||||||
|
|
||||||
lodash.camelcase@^4.3.0:
|
lodash.camelcase@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
|
||||||
|
@ -7504,6 +7533,21 @@ lodash.snakecase@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
|
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
|
||||||
|
|
||||||
|
lodash.template@>=4.5.0:
|
||||||
|
version "4.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
|
||||||
|
integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==
|
||||||
|
dependencies:
|
||||||
|
lodash._reinterpolate "^3.0.0"
|
||||||
|
lodash.templatesettings "^4.0.0"
|
||||||
|
|
||||||
|
lodash.templatesettings@^4.0.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33"
|
||||||
|
integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==
|
||||||
|
dependencies:
|
||||||
|
lodash._reinterpolate "^3.0.0"
|
||||||
|
|
||||||
lodash.toarray@^4.4.0:
|
lodash.toarray@^4.4.0:
|
||||||
version "4.4.0"
|
version "4.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
|
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
|
||||||
|
@ -7516,7 +7560,7 @@ lodash.unset@^4.5.2:
|
||||||
version "4.5.2"
|
version "4.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
|
resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
|
||||||
|
|
||||||
lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.6.1:
|
lodash@>=4.17.19, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.6.1:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
|
@ -12144,6 +12188,14 @@ video.js@^7.0.0:
|
||||||
videojs-font "3.2.0"
|
videojs-font "3.2.0"
|
||||||
videojs-vtt.js "^0.15.2"
|
videojs-vtt.js "^0.15.2"
|
||||||
|
|
||||||
|
videojs-contrib-ads@^6.6.5, videojs-contrib-ads@^6.9.0:
|
||||||
|
version "6.9.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/videojs-contrib-ads/-/videojs-contrib-ads-6.9.0.tgz#c792d6fda77254b277545cc3222352fc653b5833"
|
||||||
|
integrity sha512-nzKz+jhCGMTYffSNVYrmp9p70s05v6jUMOY3Z7DpVk3iFrWK4Zi/BIkokDWrMoHpKjdmCdKzfJVBT+CrUj6Spw==
|
||||||
|
dependencies:
|
||||||
|
global "^4.3.2"
|
||||||
|
video.js "^6 || ^7"
|
||||||
|
|
||||||
videojs-contrib-quality-levels@^2.0.9:
|
videojs-contrib-quality-levels@^2.0.9:
|
||||||
version "2.0.9"
|
version "2.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-2.0.9.tgz#b5d533d5092a6fc7d29eae1b43e4597d89bd527b"
|
resolved "https://registry.yarnpkg.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-2.0.9.tgz#b5d533d5092a6fc7d29eae1b43e4597d89bd527b"
|
||||||
|
@ -12164,6 +12216,18 @@ videojs-font@3.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232"
|
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232"
|
||||||
integrity sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==
|
integrity sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==
|
||||||
|
|
||||||
|
videojs-ima@^1.11.0:
|
||||||
|
version "1.11.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/videojs-ima/-/videojs-ima-1.11.0.tgz#26ad385e388c3da72372298d7d755b001d05a91d"
|
||||||
|
integrity sha512-ZRoWuGyJ75zamwZgpr0i/gZ6q7Evda/Q6R46gpW88WN7u0ORU7apw/lM1MSG4c3YDXW8LDENgzMAvMZUdifWhg==
|
||||||
|
dependencies:
|
||||||
|
"@hapi/cryptiles" "^5.1.0"
|
||||||
|
can-autoplay "^3.0.0"
|
||||||
|
extend ">=3.0.2"
|
||||||
|
lodash ">=4.17.19"
|
||||||
|
lodash.template ">=4.5.0"
|
||||||
|
videojs-contrib-ads "^6.6.5"
|
||||||
|
|
||||||
videojs-logo@^2.1.4:
|
videojs-logo@^2.1.4:
|
||||||
version "2.1.4"
|
version "2.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/videojs-logo/-/videojs-logo-2.1.4.tgz#56675b3f95949910bad3c217835ea57aa6fdf212"
|
resolved "https://registry.yarnpkg.com/videojs-logo/-/videojs-logo-2.1.4.tgz#56675b3f95949910bad3c217835ea57aa6fdf212"
|
||||||
|
|
Loading…
Reference in a new issue