Ads setup (#62)
* re enable preload ads * switch macro to aniview * point towards test server * improving documentation * bugfix and turn skip back on * only run twenty percent of the time for unauthed users * allow for embeds * enable show internal feature * working prototype * seems to work well * bugfix * review old aniview setup * change to production channelid * final touchups
This commit is contained in:
parent
0e96f8d468
commit
fa889112c5
8 changed files with 226 additions and 195 deletions
|
@ -68,6 +68,7 @@
|
||||||
"tempy": "^0.6.0",
|
"tempy": "^0.6.0",
|
||||||
"videojs-contrib-ads": "^6.9.0",
|
"videojs-contrib-ads": "^6.9.0",
|
||||||
"videojs-ima": "^1.11.0",
|
"videojs-ima": "^1.11.0",
|
||||||
|
"videojs-ima-player": "^0.5.6",
|
||||||
"videojs-logo": "^2.1.4"
|
"videojs-logo": "^2.1.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -255,7 +255,7 @@ const analytics: Analytics = {
|
||||||
startWatchmanIntervalIfNotRunning();
|
startWatchmanIntervalIfNotRunning();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoStartEvent: (claimId, duration, poweredBy, passedUserId, canonicalUrl, passedPlayer, videoBitrate) => {
|
videoStartEvent: (claimId, timeToStartVideo, poweredBy, passedUserId, canonicalUrl, passedPlayer, videoBitrate) => {
|
||||||
// populate values for watchman when video starts
|
// populate values for watchman when video starts
|
||||||
userId = passedUserId;
|
userId = passedUserId;
|
||||||
claimUrl = canonicalUrl;
|
claimUrl = canonicalUrl;
|
||||||
|
@ -265,8 +265,8 @@ const analytics: Analytics = {
|
||||||
videoPlayer = passedPlayer;
|
videoPlayer = passedPlayer;
|
||||||
bitrateAsBitsPerSecond = videoBitrate;
|
bitrateAsBitsPerSecond = videoBitrate;
|
||||||
|
|
||||||
sendPromMetric('time_to_start', duration);
|
sendPromMetric('time_to_start', timeToStartVideo);
|
||||||
sendMatomoEvent('Media', 'TimeToStart', claimId, duration);
|
sendMatomoEvent('Media', 'TimeToStart', claimId, timeToStartVideo);
|
||||||
},
|
},
|
||||||
error: (message) => {
|
error: (message) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
|
|
@ -67,6 +67,8 @@ export const IS_MAC = navigator.userAgent.indexOf('Mac OS X') !== -1;
|
||||||
const MOUSE_BACK_BTN = 3;
|
const MOUSE_BACK_BTN = 3;
|
||||||
const MOUSE_FORWARD_BTN = 4;
|
const MOUSE_FORWARD_BTN = 4;
|
||||||
|
|
||||||
|
const imaLibraryPath = 'https://imasdk.googleapis.com/js/sdkloader/ima3.js';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
language: string,
|
language: string,
|
||||||
languages: Array<string>,
|
languages: Array<string>,
|
||||||
|
@ -325,21 +327,19 @@ function App(props: Props) {
|
||||||
}
|
}
|
||||||
}, [previousRewardApproved, isRewardApproved]);
|
}, [previousRewardApproved, isRewardApproved]);
|
||||||
|
|
||||||
// Load IMA3 SDK for aniview: DISABLED FOR NOW
|
// Load IMA3 SDK for aniview
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// if (ENABLE_PREROLL_ADS) {
|
const script = document.createElement('script');
|
||||||
// const script = document.createElement('script');
|
script.src = imaLibraryPath;
|
||||||
// script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`;
|
script.async = true;
|
||||||
// script.async = true;
|
// $FlowFixMe
|
||||||
// // $FlowFixMe
|
document.body.appendChild(script);
|
||||||
// document.body.appendChild(script);
|
return () => {
|
||||||
// return () => {
|
// $FlowFixMe
|
||||||
// // $FlowFixMe
|
document.body.removeChild(script);
|
||||||
// document.body.removeChild(script);
|
};
|
||||||
// };
|
});
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// @endif
|
// @endif
|
||||||
|
|
||||||
// @if TARGET='app'
|
// @if TARGET='app'
|
||||||
|
|
|
@ -30,9 +30,11 @@ const select = (state, props) => {
|
||||||
const urlParams = new URLSearchParams(search);
|
const urlParams = new URLSearchParams(search);
|
||||||
const autoplay = urlParams.get('autoplay');
|
const autoplay = urlParams.get('autoplay');
|
||||||
const uri = props.uri;
|
const uri = props.uri;
|
||||||
|
|
||||||
// TODO: eventually this should be received from DB and not local state (https://github.com/lbryio/lbry-desktop/issues/6796)
|
// TODO: eventually this should be received from DB and not local state (https://github.com/lbryio/lbry-desktop/issues/6796)
|
||||||
const position = urlParams.get('t') !== null ? urlParams.get('t') : makeSelectContentPositionForUri(uri)(state);
|
const position = urlParams.get('t') !== null ? urlParams.get('t') : makeSelectContentPositionForUri(uri)(state);
|
||||||
const userId = selectUser(state) && selectUser(state).id;
|
const userId = selectUser(state) && selectUser(state).id;
|
||||||
|
const internalFeature = selectUser(state) && selectUser(state).internal_feature;
|
||||||
const playingUri = selectPlayingUri(state);
|
const playingUri = selectPlayingUri(state);
|
||||||
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || (playingUri && playingUri.collectionId);
|
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID) || (playingUri && playingUri.collectionId);
|
||||||
const isMarkdownOrComment = playingUri && (playingUri.source === 'markdown' || playingUri.source === 'comment');
|
const isMarkdownOrComment = playingUri && (playingUri.source === 'markdown' || playingUri.source === 'comment');
|
||||||
|
@ -50,6 +52,7 @@ const select = (state, props) => {
|
||||||
return {
|
return {
|
||||||
position,
|
position,
|
||||||
userId,
|
userId,
|
||||||
|
internalFeature,
|
||||||
collectionId,
|
collectionId,
|
||||||
nextRecommendedUri,
|
nextRecommendedUri,
|
||||||
previousListUri,
|
previousListUri,
|
||||||
|
|
|
@ -1,130 +0,0 @@
|
||||||
// Created by xander on 6/21/2021
|
|
||||||
import videojs from 'video.js';
|
|
||||||
import 'videojs-contrib-ads';
|
|
||||||
import 'videojs-ima';
|
|
||||||
const VERSION = '0.0.1';
|
|
||||||
|
|
||||||
/* Macro provided by aniview
|
|
||||||
* 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` +
|
|
||||||
`&logo=false` +
|
|
||||||
`&usevslot=true` +
|
|
||||||
`&vastretry=3` +
|
|
||||||
`&hidecontrols=false`;
|
|
||||||
* */
|
|
||||||
|
|
||||||
// TEST PRE-ROLL WITH THIS TAG:
|
|
||||||
// https://pubads.g.doubleclick.net/gampad/ads?sz=640x480&iu=/124319096/external/ad_rule_samples&ciu_szs=300x250&ad_rule=1&impl=s&gdfp_req=1&env=vp&output=vmap&unviewed_position_start=1&cust_params=deployment%3Ddevsite%26sample_ar%3Dpreonly&cmsid=496&vid=short_onecue&correlator=
|
|
||||||
|
|
||||||
// Modified to work with IMA
|
|
||||||
const macroUrl =
|
|
||||||
`https://vast.aniview.com/api/adserver61/vast/` +
|
|
||||||
`?AV_PUBLISHERID=60afcbc58cfdb065440d2426` +
|
|
||||||
`&AV_CHANNELID=60b354389c7adb506d0bd9a4` +
|
|
||||||
`&AV_URL=[URL]` +
|
|
||||||
`&cb=[CACHEBUSTING]` +
|
|
||||||
`&AV_WIDTH=[WIDTH]` +
|
|
||||||
`&AV_HEIGHT=[HEIGHT]` +
|
|
||||||
// `&AV_SCHAIN=[SCHAIN_MACRO]` +
|
|
||||||
// `&AV_CCPA=[CCPA_MACRO]` +
|
|
||||||
// `&AV_GDPR=[GDPR_MACRO]` +
|
|
||||||
// `&AV_CONSENT=[CONSENT_MACRO]` +
|
|
||||||
`&skip=true` +
|
|
||||||
`&skiptimer=5` +
|
|
||||||
`&logo=true` +
|
|
||||||
`&usevslot=true` +
|
|
||||||
`&vastretry=5` +
|
|
||||||
`&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;
|
|
||||||
|
|
||||||
// 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) {
|
|
||||||
// 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('aniview', AniviewPlugin);
|
|
||||||
|
|
||||||
const onPlayerReady = (player, options) => {
|
|
||||||
player.aniview = new AniviewPlugin(player, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the plugin.
|
|
||||||
*
|
|
||||||
* @function plugin
|
|
||||||
* @param {Object} [options={}]
|
|
||||||
*/
|
|
||||||
const plugin = function (options) {
|
|
||||||
const google = window.google;
|
|
||||||
|
|
||||||
this.ima({
|
|
||||||
// $FlowFixMe
|
|
||||||
vpaidMode: google.ima.ImaSdkSettings.VpaidMode.INSECURE,
|
|
||||||
adTagUrl: macroUrl,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.ready(() => {
|
|
||||||
onPlayerReady(this, videojs.mergeOptions(defaults, options));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
plugin.VERSION = VERSION;
|
|
||||||
|
|
||||||
registerPlugin('aniview', plugin);
|
|
||||||
|
|
||||||
export default plugin;
|
|
|
@ -6,6 +6,8 @@ import * as ICONS from 'constants/icons';
|
||||||
import * as KEYCODES from 'constants/keycodes';
|
import * as KEYCODES from 'constants/keycodes';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import videojs from 'video.js';
|
import videojs from 'video.js';
|
||||||
|
import 'videojs-contrib-ads';
|
||||||
|
import 'videojs-ima';
|
||||||
import 'video.js/dist/alt/video-js-cdn.min.css';
|
import 'video.js/dist/alt/video-js-cdn.min.css';
|
||||||
import eventTracking from 'videojs-event-tracking';
|
import eventTracking from 'videojs-event-tracking';
|
||||||
import * as OVERLAY from './overlays';
|
import * as OVERLAY from './overlays';
|
||||||
|
@ -14,10 +16,6 @@ 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';
|
||||||
// @if TARGET='web'
|
|
||||||
// Disabled for now.
|
|
||||||
// import './plugins/videojs-aniview/plugin';
|
|
||||||
// @endif
|
|
||||||
const isDev = process.env.NODE_ENV !== 'production';
|
const isDev = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
export type Player = {
|
export type Player = {
|
||||||
|
@ -60,7 +58,8 @@ type Props = {
|
||||||
adUrl: ?string,
|
adUrl: ?string,
|
||||||
claimId: ?string,
|
claimId: ?string,
|
||||||
userId: ?number,
|
userId: ?number,
|
||||||
// allowPreRoll: ?boolean,
|
allowPreRoll: ?boolean,
|
||||||
|
internalFeatureEnabled: ?boolean,
|
||||||
shareTelemetry: boolean,
|
shareTelemetry: boolean,
|
||||||
replay: boolean,
|
replay: boolean,
|
||||||
videoTheaterMode: boolean,
|
videoTheaterMode: boolean,
|
||||||
|
@ -77,6 +76,18 @@ type Props = {
|
||||||
// muted?: boolean,
|
// muted?: boolean,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
function hitsFiftyPercent() {
|
||||||
|
// from 0 - 999
|
||||||
|
const rand = Math.floor(Math.random() * (1000 + 1));
|
||||||
|
|
||||||
|
// 499 is 50% chance of running
|
||||||
|
if (rand > 499) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const videoPlaybackRates = [0.25, 0.5, 0.75, 1, 1.1, 1.25, 1.5, 1.75, 2];
|
const videoPlaybackRates = [0.25, 0.5, 0.75, 1, 1.1, 1.25, 1.5, 1.75, 2];
|
||||||
|
|
||||||
const IS_IOS =
|
const IS_IOS =
|
||||||
|
@ -178,7 +189,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
adUrl,
|
adUrl,
|
||||||
claimId,
|
claimId,
|
||||||
userId,
|
userId,
|
||||||
// allowPreRoll,
|
allowPreRoll,
|
||||||
|
internalFeatureEnabled, // for people on the team to test new features internally
|
||||||
shareTelemetry,
|
shareTelemetry,
|
||||||
replay,
|
replay,
|
||||||
videoTheaterMode,
|
videoTheaterMode,
|
||||||
|
@ -539,6 +551,54 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
// 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) return;
|
if (!player) return;
|
||||||
|
|
||||||
|
// live channel
|
||||||
|
// b354389c7adb506d0bd9a4
|
||||||
|
|
||||||
|
// ford ad
|
||||||
|
// 612fb75a42715a07645a614c
|
||||||
|
|
||||||
|
// Modified to work with IMA
|
||||||
|
const macroUrl =
|
||||||
|
`https://vast.aniview.com/api/adserver61/vast/` +
|
||||||
|
`?AV_PUBLISHERID=60afcbc58cfdb065440d2426` +
|
||||||
|
`&AV_CHANNELID=b354389c7adb506d0bd9a4` +
|
||||||
|
`&AV_URL=[URL]` +
|
||||||
|
`&cb=[CACHEBUSTING]` +
|
||||||
|
`&AV_WIDTH=[WIDTH]` +
|
||||||
|
`&AV_HEIGHT=[HEIGHT]` +
|
||||||
|
// `&AV_SCHAIN=[SCHAIN_MACRO]` +
|
||||||
|
// `&AV_CCPA=[CCPA_MACRO]` +
|
||||||
|
// `&AV_GDPR=[GDPR_MACRO]` +
|
||||||
|
// `&AV_CONSENT=[CONSENT_MACRO]` +
|
||||||
|
`&skip=true` +
|
||||||
|
`&skiptimer=5` +
|
||||||
|
`&logo=true` +
|
||||||
|
`&usevslot=true` +
|
||||||
|
`&vastretry=2` +
|
||||||
|
`&hidecontrols=false`;
|
||||||
|
|
||||||
|
// always have ads on if internal feature is on,
|
||||||
|
// otherwise if not authed, roll for 20% to see an ad
|
||||||
|
const shouldShowAnAd = internalFeatureEnabled || (allowPreRoll && hitsFiftyPercent());
|
||||||
|
|
||||||
|
// only run on chrome (brave included) and don't run on mobile for time being
|
||||||
|
const browserIsChrome = videojs.browser.IS_CHROME;
|
||||||
|
const IS_IOS = videojs.browser.IS_IOS;
|
||||||
|
const IS_ANDROID = videojs.browser.IS_ANDROID;
|
||||||
|
const IS_MOBILE = IS_IOS || IS_ANDROID;
|
||||||
|
|
||||||
|
if (shouldShowAnAd && browserIsChrome && !IS_MOBILE) {
|
||||||
|
// fire up ima integration via module
|
||||||
|
player.ima({adTagUrl: macroUrl});
|
||||||
|
}
|
||||||
|
|
||||||
|
// kick player in the butt, sometimes it doesn't always autoplay when it should
|
||||||
|
player.on('loadstart', function(event) {
|
||||||
|
if (autoplay) {
|
||||||
|
player.play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Add various event listeners to player
|
// Add various event listeners to player
|
||||||
player.one('play', onInitialPlay);
|
player.one('play', onInitialPlay);
|
||||||
player.on('play', resolveCtrlText);
|
player.on('play', resolveCtrlText);
|
||||||
|
@ -579,20 +639,10 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
|
|
||||||
// I think this is a callback function
|
// I think this is a callback function
|
||||||
const videoNode = containerRef.current && containerRef.current.querySelector('video, audio');
|
const videoNode = containerRef.current && containerRef.current.querySelector('video, audio');
|
||||||
|
|
||||||
onPlayerReady(player, videoNode);
|
onPlayerReady(player, videoNode);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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
|
|
||||||
// allow if isDev because otherwise you'll never see ads when basing to master
|
|
||||||
// @if TARGET='web'
|
|
||||||
// DISABLED FOR NOW
|
|
||||||
// if ((allowPreRoll && SIMPLE_SITE) || isDev) {
|
|
||||||
// vjs.aniview();
|
|
||||||
// }
|
|
||||||
// @endif
|
|
||||||
|
|
||||||
// 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());
|
||||||
|
|
|
@ -55,6 +55,7 @@ type Props = {
|
||||||
setVideoPlaybackRate: (number) => void,
|
setVideoPlaybackRate: (number) => void,
|
||||||
authenticated: boolean,
|
authenticated: boolean,
|
||||||
userId: number,
|
userId: number,
|
||||||
|
internalFeature: boolean,
|
||||||
homepageData?: { [string]: HomepageCat },
|
homepageData?: { [string]: HomepageCat },
|
||||||
shareTelemetry: boolean,
|
shareTelemetry: boolean,
|
||||||
isFloating: boolean,
|
isFloating: boolean,
|
||||||
|
@ -98,6 +99,7 @@ function VideoViewer(props: Props) {
|
||||||
homepageData,
|
homepageData,
|
||||||
authenticated,
|
authenticated,
|
||||||
userId,
|
userId,
|
||||||
|
internalFeature,
|
||||||
shareTelemetry,
|
shareTelemetry,
|
||||||
isFloating,
|
isFloating,
|
||||||
doPlayUri,
|
doPlayUri,
|
||||||
|
@ -152,6 +154,7 @@ function VideoViewer(props: Props) {
|
||||||
};
|
};
|
||||||
}, [embedded, videoPlaybackRate]);
|
}, [embedded, videoPlaybackRate]);
|
||||||
|
|
||||||
|
// TODO: analytics functionality
|
||||||
function doTrackingBuffered(e: Event, data: any) {
|
function doTrackingBuffered(e: Event, data: any) {
|
||||||
fetch(source, { method: 'HEAD', cache: 'no-store' }).then((response) => {
|
fetch(source, { method: 'HEAD', cache: 'no-store' }).then((response) => {
|
||||||
data.playerPoweredBy = response.headers.get('x-powered-by');
|
data.playerPoweredBy = response.headers.get('x-powered-by');
|
||||||
|
@ -159,13 +162,24 @@ function VideoViewer(props: Props) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analytics functionality that is run on first video start
|
||||||
|
* @param e - event from videojs (from the plugin?)
|
||||||
|
* @param data - only has secondsToLoad property
|
||||||
|
*/
|
||||||
function doTrackingFirstPlay(e: Event, data: any) {
|
function doTrackingFirstPlay(e: Event, data: any) {
|
||||||
let timeToStart = data.secondsToLoad;
|
// how long until the video starts
|
||||||
|
let timeToStartVideo = data.secondsToLoad;
|
||||||
|
|
||||||
if (desktopPlayStartTime !== undefined) {
|
// TODO: what's happening here briefly?
|
||||||
const differenceToAdd = Date.now() - desktopPlayStartTime;
|
if (!IS_WEB) {
|
||||||
timeToStart += differenceToAdd;
|
if (desktopPlayStartTime !== undefined) {
|
||||||
|
const differenceToAdd = Date.now() - desktopPlayStartTime;
|
||||||
|
timeToStartVideo += differenceToAdd;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send matomo event (embedded is boolean)
|
||||||
analytics.playerStartedEvent(embedded);
|
analytics.playerStartedEvent(embedded);
|
||||||
|
|
||||||
// convert bytes to bits, and then divide by seconds
|
// convert bytes to bits, and then divide by seconds
|
||||||
|
@ -175,13 +189,16 @@ function VideoViewer(props: Props) {
|
||||||
if (durationInSeconds) {
|
if (durationInSeconds) {
|
||||||
bitrateAsBitsPerSecond = Math.round(contentInBits / durationInSeconds);
|
bitrateAsBitsPerSecond = Math.round(contentInBits / durationInSeconds);
|
||||||
}
|
}
|
||||||
|
// figure out what server the video is served from and then run start analytic event
|
||||||
fetch(source, { method: 'HEAD', cache: 'no-store' }).then((response) => {
|
fetch(source, { method: 'HEAD', cache: 'no-store' }).then((response) => {
|
||||||
|
// server string such as 'eu-p6'
|
||||||
let playerPoweredBy = response.headers.get('x-powered-by') || '';
|
let playerPoweredBy = response.headers.get('x-powered-by') || '';
|
||||||
analytics.videoStartEvent(claimId, timeToStart, playerPoweredBy, userId, claim.canonical_url, this, bitrateAsBitsPerSecond);
|
// populates data for watchman, sends prom and matomo event
|
||||||
|
analytics.videoStartEvent(claimId, timeToStartVideo, playerPoweredBy, userId, claim.canonical_url, this, bitrateAsBitsPerSecond);
|
||||||
});
|
});
|
||||||
|
|
||||||
doAnalyticsView(uri, timeToStart).then(() => {
|
// hit backend to mark a view
|
||||||
|
doAnalyticsView(uri, timeToStartVideo).then(() => {
|
||||||
claimRewards();
|
claimRewards();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -264,6 +281,7 @@ function VideoViewer(props: Props) {
|
||||||
clearPosition(uri);
|
clearPosition(uri);
|
||||||
}, [adUrl, autoplayNext, clearPosition, collectionId, embedded, ended, setAdUrl, uri]);
|
}, [adUrl, autoplayNext, clearPosition, collectionId, embedded, ended, setAdUrl, uri]);
|
||||||
|
|
||||||
|
// MORE ON PLAY STUFF
|
||||||
function onPlay(player) {
|
function onPlay(player) {
|
||||||
setEnded(false);
|
setEnded(false);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
|
@ -444,29 +462,28 @@ function VideoViewer(props: Props) {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isFetchingAd && (
|
<VideoJs
|
||||||
<VideoJs
|
adUrl={adUrl}
|
||||||
adUrl={adUrl}
|
source={adUrl || source}
|
||||||
source={adUrl || source}
|
sourceType={forcePlayer || adUrl ? 'video/mp4' : contentType}
|
||||||
sourceType={forcePlayer || adUrl ? 'video/mp4' : contentType}
|
isAudio={isAudio}
|
||||||
isAudio={isAudio}
|
poster={isAudio || (embedded && !autoplayIfEmbedded) ? thumbnail : ''}
|
||||||
poster={isAudio || (embedded && !autoplayIfEmbedded) ? thumbnail : ''}
|
onPlayerReady={onPlayerReady}
|
||||||
onPlayerReady={onPlayerReady}
|
startMuted={autoplayIfEmbedded}
|
||||||
startMuted={autoplayIfEmbedded}
|
toggleVideoTheaterMode={toggleVideoTheaterMode}
|
||||||
toggleVideoTheaterMode={toggleVideoTheaterMode}
|
autoplay={!embedded || autoplayIfEmbedded}
|
||||||
autoplay={!embedded || autoplayIfEmbedded}
|
autoplaySetting={autoplayNext}
|
||||||
autoplaySetting={autoplayNext}
|
claimId={claimId}
|
||||||
claimId={claimId}
|
userId={userId}
|
||||||
userId={userId}
|
allowPreRoll={!authenticated} // used to not include embeds, removed for now
|
||||||
allowPreRoll={!embedded && !authenticated}
|
internalFeatureEnabled={internalFeature}
|
||||||
shareTelemetry={shareTelemetry}
|
shareTelemetry={shareTelemetry}
|
||||||
replay={replay}
|
replay={replay}
|
||||||
videoTheaterMode={videoTheaterMode}
|
videoTheaterMode={videoTheaterMode}
|
||||||
playNext={doPlayNext}
|
playNext={doPlayNext}
|
||||||
playPrevious={doPlayPrevious}
|
playPrevious={doPlayPrevious}
|
||||||
embedded={embedded}
|
embedded={embedded}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
92
yarn.lock
92
yarn.lock
|
@ -1854,6 +1854,20 @@
|
||||||
resolved "https://registry.yarnpkg.com/@ungap/from-entries/-/from-entries-0.2.1.tgz#7e86196b8b2e99d73106a8f25c2a068326346354"
|
resolved "https://registry.yarnpkg.com/@ungap/from-entries/-/from-entries-0.2.1.tgz#7e86196b8b2e99d73106a8f25c2a068326346354"
|
||||||
integrity sha512-CAqefTFAfnUPwYqsWHXpOxHaq1Zo5UQ3m9Zm2p09LggGe57rqHoBn3c++xcoomzXKynAUuiBMDUCQvKMnXjUpA==
|
integrity sha512-CAqefTFAfnUPwYqsWHXpOxHaq1Zo5UQ3m9Zm2p09LggGe57rqHoBn3c++xcoomzXKynAUuiBMDUCQvKMnXjUpA==
|
||||||
|
|
||||||
|
"@videojs/http-streaming@2.10.2":
|
||||||
|
version "2.10.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.10.2.tgz#02e6fcfa74f7850b5f9eb40a8e5c85c9d7d33eaf"
|
||||||
|
integrity sha512-JTAlAUHzj0sTsge2WBh4DWKM2I5BDFEZYOvzxmsK/ySILmI0GRyjAHx9uid68ZECQ2qbEAIRmZW5lWp0R5PeNA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/vhs-utils" "3.0.3"
|
||||||
|
aes-decrypter "3.1.2"
|
||||||
|
global "^4.4.0"
|
||||||
|
m3u8-parser "4.7.0"
|
||||||
|
mpd-parser "0.19.0"
|
||||||
|
mux.js "5.13.0"
|
||||||
|
video.js "^6 || ^7"
|
||||||
|
|
||||||
"@videojs/http-streaming@2.2.4":
|
"@videojs/http-streaming@2.2.4":
|
||||||
version "2.2.4"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.2.4.tgz#c71bb63dbc4749e35193c4c334430bd8ce728ec0"
|
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-2.2.4.tgz#c71bb63dbc4749e35193c4c334430bd8ce728ec0"
|
||||||
|
@ -1882,6 +1896,15 @@
|
||||||
mux.js "5.11.1"
|
mux.js "5.11.1"
|
||||||
video.js "^6 || ^7"
|
video.js "^6 || ^7"
|
||||||
|
|
||||||
|
"@videojs/vhs-utils@3.0.3":
|
||||||
|
version "3.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-3.0.3.tgz#708bc50742e9481712039695299b32da6582ef92"
|
||||||
|
integrity sha512-bU7daxDHhzcTDbmty1cXjzsTYvx2cBGbA8hG5H2Gvpuk4sdfuvkZtMCwtCqL59p6dsleMPspyaNS+7tWXx2Y0A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
global "^4.4.0"
|
||||||
|
url-toolkit "^2.2.1"
|
||||||
|
|
||||||
"@videojs/vhs-utils@^2.2.1":
|
"@videojs/vhs-utils@^2.2.1":
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-2.3.0.tgz#490a3a00dfc1b51d85d5dcf8f8361e2d4c4d1440"
|
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-2.3.0.tgz#490a3a00dfc1b51d85d5dcf8f8361e2d4c4d1440"
|
||||||
|
@ -1900,6 +1923,15 @@
|
||||||
global "^4.4.0"
|
global "^4.4.0"
|
||||||
url-toolkit "^2.2.1"
|
url-toolkit "^2.2.1"
|
||||||
|
|
||||||
|
"@videojs/vhs-utils@^3.0.3":
|
||||||
|
version "3.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-3.0.4.tgz#e253eecd8e9318f767e752010d213587f94bb03a"
|
||||||
|
integrity sha512-hui4zOj2I1kLzDgf8QDVxD3IzrwjS/43KiS8IHQO0OeeSsb4pB/lgNt1NG7Dv0wMQfCccUpMVLGcK618s890Yg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
global "^4.4.0"
|
||||||
|
url-toolkit "^2.2.1"
|
||||||
|
|
||||||
"@videojs/xhr@2.5.1":
|
"@videojs/xhr@2.5.1":
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.5.1.tgz#26bc5a79dbb3b03bfb13742c6ce559f89e90719e"
|
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.5.1.tgz#26bc5a79dbb3b03bfb13742c6ce559f89e90719e"
|
||||||
|
@ -1909,6 +1941,15 @@
|
||||||
global "~4.4.0"
|
global "~4.4.0"
|
||||||
is-function "^1.0.1"
|
is-function "^1.0.1"
|
||||||
|
|
||||||
|
"@videojs/xhr@2.6.0":
|
||||||
|
version "2.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.6.0.tgz#cd897e0ad54faf497961bcce3fa16dc15a26bb80"
|
||||||
|
integrity sha512-7J361GiN1tXpm+gd0xz2QWr3xNWBE+rytvo8J3KuggFaLg+U37gZQ2BuPLcnkfGffy2e+ozY70RHC8jt7zjA6Q==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.5.5"
|
||||||
|
global "~4.4.0"
|
||||||
|
is-function "^1.0.1"
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.8.5":
|
"@webassemblyjs/ast@1.8.5":
|
||||||
version "1.8.5"
|
version "1.8.5"
|
||||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
|
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359"
|
||||||
|
@ -2042,6 +2083,11 @@
|
||||||
resolved "https://registry.yarnpkg.com/@wojtekmaj/date-utils/-/date-utils-1.0.3.tgz#2dcfd92881425c5923e429c2aec86fb3609032a1"
|
resolved "https://registry.yarnpkg.com/@wojtekmaj/date-utils/-/date-utils-1.0.3.tgz#2dcfd92881425c5923e429c2aec86fb3609032a1"
|
||||||
integrity sha512-1VPkkTBk07gMR1fjpBtse4G+oJqpmE+0gUFB0dg3VIL7qJmUVaBoD/vlzMm/jNeOPfvlmerl1lpnsZyBUFIRuw==
|
integrity sha512-1VPkkTBk07gMR1fjpBtse4G+oJqpmE+0gUFB0dg3VIL7qJmUVaBoD/vlzMm/jNeOPfvlmerl1lpnsZyBUFIRuw==
|
||||||
|
|
||||||
|
"@xmldom/xmldom@^0.7.2":
|
||||||
|
version "0.7.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d"
|
||||||
|
integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==
|
||||||
|
|
||||||
"@xtuc/ieee754@^1.2.0":
|
"@xtuc/ieee754@^1.2.0":
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
|
||||||
|
@ -11188,6 +11234,16 @@ mpd-parser@0.17.0:
|
||||||
global "^4.4.0"
|
global "^4.4.0"
|
||||||
xmldom "^0.5.0"
|
xmldom "^0.5.0"
|
||||||
|
|
||||||
|
mpd-parser@0.19.0:
|
||||||
|
version "0.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mpd-parser/-/mpd-parser-0.19.0.tgz#8937044040ca85e20398ecf5d94552655e2c6728"
|
||||||
|
integrity sha512-FDLIXtZMZs99fv5iXNFg94quNFT26tobo0NUgHu7L3XgZvEq1NBarf5yxDFFJ1zzfbcmtj+NRaml6nYIxoPWvw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/vhs-utils" "^3.0.2"
|
||||||
|
"@xmldom/xmldom" "^0.7.2"
|
||||||
|
global "^4.4.0"
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
|
@ -11228,6 +11284,13 @@ mux.js@5.11.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.11.2"
|
"@babel/runtime" "^7.11.2"
|
||||||
|
|
||||||
|
mux.js@5.13.0:
|
||||||
|
version "5.13.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.13.0.tgz#99c3da21f6c0362a1529729d1c5e5b51f34f606d"
|
||||||
|
integrity sha512-PkmnzHcTQjUBEHp3KRPQAFoNkJtKlpCEvsYtXDfDrC+/WqbMuxHvoYfmAbHVAH7Sa/KliPVU0dT1ureO8wilog==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.11.2"
|
||||||
|
|
||||||
mux.js@5.6.7:
|
mux.js@5.6.7:
|
||||||
version "5.6.7"
|
version "5.6.7"
|
||||||
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.6.7.tgz#d39fc85cded5a1257de9f6eeb5cf1578c4a63eb8"
|
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.6.7.tgz#d39fc85cded5a1257de9f6eeb5cf1578c4a63eb8"
|
||||||
|
@ -16600,6 +16663,25 @@ vfile@^2.0.0:
|
||||||
videojs-font "3.2.0"
|
videojs-font "3.2.0"
|
||||||
videojs-vtt.js "^0.15.3"
|
videojs-vtt.js "^0.15.3"
|
||||||
|
|
||||||
|
"video.js@^6.0.1 || ^7":
|
||||||
|
version "7.15.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.15.4.tgz#0f96ef138035138cb30bf00a989b6174f0d16bac"
|
||||||
|
integrity sha512-hghxkgptLUvfkpktB4wxcIVF3VpY/hVsMkrjHSv0jpj1bW9Jplzdt8IgpTm9YhlB1KYAp07syVQeZcBFUBwhkw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.12.5"
|
||||||
|
"@videojs/http-streaming" "2.10.2"
|
||||||
|
"@videojs/vhs-utils" "^3.0.3"
|
||||||
|
"@videojs/xhr" "2.6.0"
|
||||||
|
aes-decrypter "3.1.2"
|
||||||
|
global "^4.4.0"
|
||||||
|
keycode "^2.2.0"
|
||||||
|
m3u8-parser "4.7.0"
|
||||||
|
mpd-parser "0.19.0"
|
||||||
|
mux.js "5.13.0"
|
||||||
|
safe-json-parse "4.0.0"
|
||||||
|
videojs-font "3.2.0"
|
||||||
|
videojs-vtt.js "^0.15.3"
|
||||||
|
|
||||||
video.js@^7.0.0:
|
video.js@^7.0.0:
|
||||||
version "7.10.2"
|
version "7.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.10.2.tgz#5156aabad7820e726d72ea6c32324059c68885a4"
|
resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.10.2.tgz#5156aabad7820e726d72ea6c32324059c68885a4"
|
||||||
|
@ -16614,7 +16696,7 @@ 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:
|
videojs-contrib-ads@^6.6.5, videojs-contrib-ads@^6.7.0, videojs-contrib-ads@^6.9.0:
|
||||||
version "6.9.0"
|
version "6.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/videojs-contrib-ads/-/videojs-contrib-ads-6.9.0.tgz#c792d6fda77254b277545cc3222352fc653b5833"
|
resolved "https://registry.yarnpkg.com/videojs-contrib-ads/-/videojs-contrib-ads-6.9.0.tgz#c792d6fda77254b277545cc3222352fc653b5833"
|
||||||
integrity sha512-nzKz+jhCGMTYffSNVYrmp9p70s05v6jUMOY3Z7DpVk3iFrWK4Zi/BIkokDWrMoHpKjdmCdKzfJVBT+CrUj6Spw==
|
integrity sha512-nzKz+jhCGMTYffSNVYrmp9p70s05v6jUMOY3Z7DpVk3iFrWK4Zi/BIkokDWrMoHpKjdmCdKzfJVBT+CrUj6Spw==
|
||||||
|
@ -16642,6 +16724,14 @@ 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-player@^0.5.6:
|
||||||
|
version "0.5.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/videojs-ima-player/-/videojs-ima-player-0.5.6.tgz#73f5aaaa7111ebffa7cb4eef84b2c6e62421368f"
|
||||||
|
integrity sha512-3QlzKqExLc30MMB4cRVbYluZGDPbxJ32HQ8nD+cGLM+e/oMwrb/rDyfMm1+fXKMhWKvV+pjiYtwx28hdciLTng==
|
||||||
|
dependencies:
|
||||||
|
video.js "^6.0.1 || ^7"
|
||||||
|
videojs-contrib-ads "^6.7.0"
|
||||||
|
|
||||||
videojs-ima@^1.11.0:
|
videojs-ima@^1.11.0:
|
||||||
version "1.11.0"
|
version "1.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/videojs-ima/-/videojs-ima-1.11.0.tgz#26ad385e388c3da72372298d7d755b001d05a91d"
|
resolved "https://registry.yarnpkg.com/videojs-ima/-/videojs-ima-1.11.0.tgz#26ad385e388c3da72372298d7d755b001d05a91d"
|
||||||
|
|
Loading…
Reference in a new issue