Compare commits
9 commits
master
...
reenable-a
Author | SHA1 | Date | |
---|---|---|---|
|
939be05e5d | ||
|
85447185a8 | ||
|
59a9f46c29 | ||
|
5b4151bc72 | ||
|
6c463e7310 | ||
|
3afee8e5c9 | ||
|
26fc53bb4d | ||
|
858d038c48 | ||
|
65994c4ebf |
6 changed files with 117 additions and 56 deletions
|
@ -240,7 +240,7 @@ const analytics: Analytics = {
|
||||||
startWatchmanIntervalIfNotRunning();
|
startWatchmanIntervalIfNotRunning();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
videoStartEvent: (claimId, duration, poweredBy, passedUserId, canonicalUrl, passedPlayer) => {
|
videoStartEvent: (claimId, timeToStartVideo, poweredBy, passedUserId, canonicalUrl, passedPlayer) => {
|
||||||
// populate values for watchman when video starts
|
// populate values for watchman when video starts
|
||||||
userId = passedUserId;
|
userId = passedUserId;
|
||||||
claimUrl = canonicalUrl;
|
claimUrl = canonicalUrl;
|
||||||
|
@ -249,8 +249,8 @@ const analytics: Analytics = {
|
||||||
videoType = passedPlayer.currentSource().type;
|
videoType = passedPlayer.currentSource().type;
|
||||||
videoPlayer = passedPlayer;
|
videoPlayer = passedPlayer;
|
||||||
|
|
||||||
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) => {
|
||||||
|
|
|
@ -327,19 +327,17 @@ function App(props: Props) {
|
||||||
|
|
||||||
// Load IMA3 SDK for aniview: DISABLED FOR NOW
|
// Load IMA3 SDK for aniview: DISABLED FOR NOW
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// if (ENABLE_PREROLL_ADS) {
|
const script = document.createElement('script');
|
||||||
// const script = document.createElement('script');
|
script.src = `https://imasdk.googleapis.com/js/sdkloader/ima3.js`;
|
||||||
// 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,
|
||||||
|
|
|
@ -26,13 +26,19 @@ const VERSION = '0.0.1';
|
||||||
* */
|
* */
|
||||||
|
|
||||||
// TEST PRE-ROLL WITH THIS TAG:
|
// 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=
|
// const macroUrl = '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=';
|
||||||
|
|
||||||
|
// live channel
|
||||||
|
// b354389c7adb506d0bd9a4
|
||||||
|
|
||||||
|
// ford ad
|
||||||
|
// 612fb75a42715a07645a614c
|
||||||
|
|
||||||
// Modified to work with IMA
|
// Modified to work with IMA
|
||||||
const macroUrl =
|
const macroUrl =
|
||||||
`https://vast.aniview.com/api/adserver61/vast/` +
|
`https://vast.aniview.com/api/adserver61/vast/` +
|
||||||
`?AV_PUBLISHERID=60afcbc58cfdb065440d2426` +
|
`?AV_PUBLISHERID=60afcbc58cfdb065440d2426` +
|
||||||
`&AV_CHANNELID=60b354389c7adb506d0bd9a4` +
|
`&AV_CHANNELID=612fb75a42715a07645a614c` +
|
||||||
`&AV_URL=[URL]` +
|
`&AV_URL=[URL]` +
|
||||||
`&cb=[CACHEBUSTING]` +
|
`&cb=[CACHEBUSTING]` +
|
||||||
`&AV_WIDTH=[WIDTH]` +
|
`&AV_WIDTH=[WIDTH]` +
|
||||||
|
@ -45,7 +51,7 @@ const macroUrl =
|
||||||
`&skiptimer=5` +
|
`&skiptimer=5` +
|
||||||
`&logo=true` +
|
`&logo=true` +
|
||||||
`&usevslot=true` +
|
`&usevslot=true` +
|
||||||
`&vastretry=5` +
|
`&vastretry=2` +
|
||||||
`&hidecontrols=false`;
|
`&hidecontrols=false`;
|
||||||
|
|
||||||
const defaults = {
|
const defaults = {
|
||||||
|
@ -69,16 +75,16 @@ class AniviewPlugin extends Component {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
|
|
||||||
// request ads whenever there's new video content
|
// request ads whenever there's new video content
|
||||||
/* player.on('contentchanged', () => {
|
player.on('contentchanged', () => {
|
||||||
// in a real plugin, you might fetch your ad inventory here
|
// in a real plugin, you might fetch your ad inventory here
|
||||||
player.trigger('adsready');
|
player.trigger('adsready');
|
||||||
}); */
|
});
|
||||||
|
|
||||||
// Plugin event listeners
|
// Plugin event listeners
|
||||||
// player.on('readyforpreroll', (event) => this.onReadyForPreroll(event));
|
player.on('readyforpreroll', (event) => this.onReadyForPreroll(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* onReadyForPreroll(event) {
|
onReadyForPreroll(event) {
|
||||||
// send event when ad is playing to remove loading spinner
|
// send event when ad is playing to remove loading spinner
|
||||||
this.player.one('adplaying', () => {
|
this.player.one('adplaying', () => {
|
||||||
this.player.trigger('ads-ad-started');
|
this.player.trigger('ads-ad-started');
|
||||||
|
@ -88,7 +94,7 @@ class AniviewPlugin extends Component {
|
||||||
this.player.one('adended', () => {
|
this.player.one('adended', () => {
|
||||||
this.player.ads.endLinearAdMode();
|
this.player.ads.endLinearAdMode();
|
||||||
});
|
});
|
||||||
} */
|
}
|
||||||
|
|
||||||
log(...args) {
|
log(...args) {
|
||||||
if (this.options_.debug) {
|
if (this.options_.debug) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import qualityLevels from 'videojs-contrib-quality-levels';
|
||||||
import isUserTyping from 'util/detect-typing';
|
import isUserTyping from 'util/detect-typing';
|
||||||
// @if TARGET='web'
|
// @if TARGET='web'
|
||||||
// Disabled for now.
|
// Disabled for now.
|
||||||
// import './plugins/videojs-aniview/plugin';
|
import './plugins/videojs-aniview/plugin';
|
||||||
// @endif
|
// @endif
|
||||||
const isDev = process.env.NODE_ENV !== 'production';
|
const isDev = process.env.NODE_ENV !== 'production';
|
||||||
|
|
||||||
|
@ -60,7 +60,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 +78,30 @@ type Props = {
|
||||||
// muted?: boolean,
|
// muted?: boolean,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
|
function hitsTwentyPercent() {
|
||||||
|
// from 0 - 999
|
||||||
|
var rand = Math.floor(Math.random() * (1000 + 1));
|
||||||
|
|
||||||
|
console.log(rand);
|
||||||
|
console.log('rand');
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
console.log('play here');
|
||||||
|
player.play()
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
if (rand > 799) {
|
||||||
|
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 +203,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
|
||||||
adUrl,
|
adUrl,
|
||||||
claimId,
|
claimId,
|
||||||
userId,
|
userId,
|
||||||
// allowPreRoll,
|
allowPreRoll,
|
||||||
|
internalFeatureEnabled,
|
||||||
shareTelemetry,
|
shareTelemetry,
|
||||||
replay,
|
replay,
|
||||||
videoTheaterMode,
|
videoTheaterMode,
|
||||||
|
@ -539,6 +565,14 @@ 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;
|
||||||
|
|
||||||
|
// always have ads on if internal feature is on,
|
||||||
|
// otherwise if not authed, roll for 20% to see an ad
|
||||||
|
const shouldShowAnAd = internalFeatureEnabled || (allowPreRoll && hitsTwentyPercent());
|
||||||
|
|
||||||
|
if (shouldShowAnAd) {
|
||||||
|
vjs.aniview();
|
||||||
|
}
|
||||||
|
|
||||||
// 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,6 +613,7 @@ 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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -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,21 +162,37 @@ 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;
|
||||||
|
|
||||||
|
// TODO: what's happening here briefly?
|
||||||
|
if (!IS_WEB) {
|
||||||
if (desktopPlayStartTime !== undefined) {
|
if (desktopPlayStartTime !== undefined) {
|
||||||
const differenceToAdd = Date.now() - desktopPlayStartTime;
|
const differenceToAdd = Date.now() - desktopPlayStartTime;
|
||||||
timeToStart += differenceToAdd;
|
timeToStartVideo += differenceToAdd;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// send matomo event (embedded is boolean)
|
||||||
analytics.playerStartedEvent(embedded);
|
analytics.playerStartedEvent(embedded);
|
||||||
|
|
||||||
|
// 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);
|
|
||||||
|
// populates data for watchman, sends prom and matomo event
|
||||||
|
analytics.videoStartEvent(claimId, timeToStartVideo, playerPoweredBy, userId, claim.canonical_url, this);
|
||||||
});
|
});
|
||||||
|
|
||||||
doAnalyticsView(uri, timeToStart).then(() => {
|
// hit backend to mark a view
|
||||||
|
doAnalyticsView(uri, timeToStartVideo).then(() => {
|
||||||
claimRewards();
|
claimRewards();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -256,6 +275,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);
|
||||||
|
@ -436,7 +456,6 @@ function VideoViewer(props: Props) {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!isFetchingAd && (
|
|
||||||
<VideoJs
|
<VideoJs
|
||||||
adUrl={adUrl}
|
adUrl={adUrl}
|
||||||
source={adUrl || source}
|
source={adUrl || source}
|
||||||
|
@ -450,7 +469,8 @@ function VideoViewer(props: Props) {
|
||||||
autoplaySetting={autoplayNext}
|
autoplaySetting={autoplayNext}
|
||||||
claimId={claimId}
|
claimId={claimId}
|
||||||
userId={userId}
|
userId={userId}
|
||||||
allowPreRoll={!embedded && !authenticated}
|
allowPreRoll={!authenticated} // used to not include embeds, removed for now
|
||||||
|
internalFeatureEnabled={internalFeature}
|
||||||
shareTelemetry={shareTelemetry}
|
shareTelemetry={shareTelemetry}
|
||||||
replay={replay}
|
replay={replay}
|
||||||
videoTheaterMode={videoTheaterMode}
|
videoTheaterMode={videoTheaterMode}
|
||||||
|
@ -458,7 +478,6 @@ function VideoViewer(props: Props) {
|
||||||
playPrevious={doPlayPrevious}
|
playPrevious={doPlayPrevious}
|
||||||
embedded={embedded}
|
embedded={embedded}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue