UNPKG

npaw-plugin-adapters

Version:
607 lines (547 loc) 18.1 kB
/* global google */ export default class ImaAdapter { _readAdPodValue(adPodInfo, methodName, propertyName) { if (!adPodInfo) { return null; } if (typeof adPodInfo[methodName] === 'function') { return adPodInfo[methodName](); } if (adPodInfo[propertyName] !== undefined) { return adPodInfo[propertyName]; } return null; } _updateBreakInfoFromPodInfo(adPodInfo) { if (!adPodInfo) { return; } if (!this.breakAdsByOffset) { this.breakAdsByOffset = {}; } const totalAds = this._readAdPodValue(adPodInfo, 'getTotalAds', 'totalAds'); const timeOffset = this._readAdPodValue(adPodInfo, 'getTimeOffset', 'timeOffset'); if (typeof totalAds === 'number' && totalAds > 0) { this.totalAds = totalAds; } if (typeof timeOffset === 'number') { this.breakAdsByOffset[timeOffset] = Math.max(this.breakAdsByOffset[timeOffset] || 0, totalAds || 1); } } _getCuePoints() { if (this.player && typeof this.player.getCuePoints === 'function') { return this.player.getCuePoints() || []; } return []; } _getObservedBreakOffsets() { if (!this.breakAdsByOffset) { return []; } return Object.keys(this.breakAdsByOffset) .map(function (offset) { return Number(offset); }) .filter(function (offset) { return !Number.isNaN(offset); }) .sort(function (a, b) { return a - b; }); } _getContentDurationForBreaks() { let duration = null; const videoAdapter = this.getVideo() ? this.getVideo().getAdapter() : null; if (videoAdapter && typeof videoAdapter.getDuration === 'function') { duration = videoAdapter.getDuration(); } else if (this.plugin && this.plugin._adapter && typeof this.plugin._adapter.getDuration === 'function') { duration = this.plugin._adapter.getDuration(); } return typeof duration === 'number' && isFinite(duration) && duration > 0 ? duration : null; } _normalizeCuePoint(cuePoint, contentDuration) { if (cuePoint === -1) { return contentDuration !== null ? contentDuration : -1; } if (cuePoint === null || cuePoint === undefined) { return contentDuration !== null ? contentDuration : null; } return cuePoint; } _getBreakPositionFromCuePoint(cuePoint, contentDuration) { if (cuePoint === 0) { return 'pre'; } if (cuePoint === -1) { return 'post'; } if (contentDuration !== null && typeof cuePoint === 'number' && cuePoint >= contentDuration - 1) { return 'post'; } return 'mid'; } _getAdPodInfoFromEvent(e) { const adData = typeof e.getAdData === 'function' ? e.getAdData() : null; if (adData && adData.adPodInfo) { return adData.adPodInfo; } const adObject = typeof e.getAd === 'function' ? e.getAd() : this.player && this.player.getCurrentAd ? this.player.getCurrentAd() : null; if (adObject && typeof adObject.getAdPodInfo === 'function') { return adObject.getAdPodInfo(); } return null; } pauseListener(e) { this.firePause({}, 'pauseListener'); } getAdInsertionType() { return this.isDAI ? this.getNpawReference().Constants.AdInsertionType.ServerSide : this.getNpawReference().Constants.AdInsertionType.ClientSide; } progressDAIListener(e) { if (e.getStreamData && e.getStreamData()) { this.playhead = e.getStreamData().adProgressData.currentTime; } else if (typeof e.getAdData === 'function' && e.getAdData()) { this.playhead = e.getAdData().currentTime; } this.fireJoin({}, 'progressDAIListener'); } getRendition() { let ret = null; if (this.player) { if (!this.isDAI) { const currentAd = this.player.getCurrentAd(); ret = currentAd.getVastMediaWidth().toString() + 'x' + currentAd.getVastMediaHeight().toString(); } else if (this.width && this.height) { ret = this.width + 'x' + this.height; } } return ret; } startDAIListener(e) { this.isDAI = true; this.playhead = 0; } getPlayerVersion() { return google.ima.VERSION; } playListener(e) { this.isDAI = false; this.adPosition = this.getAdPosition(); const adData = typeof e.getAdData === 'function' ? e.getAdData() : null; const adPodInfo = this._getAdPodInfoFromEvent(e); this._updateBreakInfoFromPodInfo(adPodInfo); this.totalAds = adData && adData.adPodInfo ? adData.adPodInfo.totalAds : this.totalAds; this.plugin.fireInit(undefined, 'playListener', this.getVideo().getVideoKey()); if (this.getVideo().getAdapter()) { this.getVideo().getAdapter().firePause({}, 'playListener'); } this.fireStart( { adPlayhead: '0' }, 'playListener' ); } getTitle2() { let ret = this.advertiser; if (this.player && !this.isDAI) { ret = this.player.getCurrentAd().getAdvertiserName(); } return ret; } errorDAIListener(e) { this.fireError(undefined, undefined, undefined, undefined, 'errorDAIListener'); this.fireStop({}, 'errorDAIListener'); } secondQuartileListener(e) { this.fireQuartile(2); } endedListener(e) { if (this.lastDuration) { this.fireStop( { adPlayhead: this.lastDuration }, 'endedListener' ); } else { this.fireStop({}, 'endedListener'); } } getGivenBreaks() { const breaksTime = this.getBreaksTime(); return breaksTime ? breaksTime.length : 0; } loadedListener(e) { const adData = typeof e.getAdData === 'function' ? e.getAdData() : null; const adPodInfo = this._getAdPodInfoFromEvent(e); this._updateBreakInfoFromPodInfo(adPodInfo); this.totalAds = adData && adData.adPodInfo ? adData.adPodInfo.totalAds : undefined; this.clickUrl = adData ? adData.clickThroughUrl : undefined; if (this.plugin.isBreakStarted) { this.playListener(e); } } getPlayhead() { let ret = this.playhead; if (!this.flags.isJoined) { ret = 0; } else if (this.player && !this.isDAI) { ret = this.getDuration() - this.player.getRemainingTime(); } return ret; } getDuration() { let ret = this.duration; if (this.player && !this.isDAI) { if (this.player.getCurrentAd && this.player.getCurrentAd()) { this.lastDuration = this.player.getCurrentAd().getDuration(); } ret = this.lastDuration; } return ret; } getGivenAds() { return this.totalAds; } getExpectedBreaks() { const pattern = this.getExpectedPattern(); if (pattern) { return pattern.pre.length + pattern.mid.length + pattern.post.length; } return this.getGivenBreaks(); } getExpectedPattern() { const observedOffsets = this._getObservedBreakOffsets(); const cuepoints = observedOffsets.length ? observedOffsets : this.getBreaksTime(); const contentDuration = this._getContentDurationForBreaks(); const pattern = { pre: [], mid: [], post: [] }; cuepoints.forEach( function (cuePoint) { const position = this._getBreakPositionFromCuePoint(cuePoint, contentDuration); const expectedAds = (this.breakAdsByOffset && this.breakAdsByOffset[cuePoint]) || this.totalAds || 1; pattern[position].push(expectedAds); }.bind(this) ); return pattern.pre.length === 0 && pattern.mid.length === 0 && pattern.post.length === 0 ? null : pattern; } getIsSkippable() { let ret = null; if (this.player && this.player.getCurrentAd) { const currentAd = this.player.getCurrentAd(); if (currentAd && currentAd.g) { ret = currentAd.g.skippable; } } return ret; } getCreativeId() { let ret = null; if (!this.isDAI && this.player.getCurrentAd()) { ret = this.player.getCurrentAd().getCreativeId(); } return ret; } thirdQuartileListener(e) { this.fireQuartile(3); } getAudioEnabled() { let ret = null; if (this.player) { ret = this.player.getVolume ? this.player.getVolume() !== 0 : true; } return ret; } getVersion() { return '7.0.11-ima-jsclass'; } logListener(e) { if (typeof e.getAdData === 'function' && e.getAdData().adError) { const error = e.getAdData().adError; this.fireError(error.getErrorCode(), error.getMessage(), undefined, undefined, 'logListener'); this.fireStop({}, 'logListener'); } } unregisterListeners() { if (this.monitor) this.monitor.stop(); if (this.player && this.references) { for (let key in this.references) { this.player.removeEventListener(key, this.references[key]); } this.references = {}; } } clickListener(e) { let url = this.clickUrl; const current = this.player.getCurrentAd(); if (current && current.g && current.g.clickThroughUrl) { url = current.g.clickThroughUrl; } const now = new Date().getTime(); if (this.lastUrl === url && now < (this.lastTime || 0) + 2000) { return; } this.lastUrl = url; this.lastTime = now; this.fireClick(url); } getAdPosition() { let ret = this.getNpawReference().Constants.AdPosition.Midroll; if (!this.isDAI) { switch (this.player.getCurrentAd().getAdPodInfo().getTimeOffset()) { case 0: ret = this.getNpawReference().Constants.AdPosition.Preroll; break; case -1: ret = this.getNpawReference().Constants.AdPosition.Postroll; } } else { const videoAdapter = this.getVideo().getAdapter(); if (videoAdapter && (!videoAdapter.flags.isJoined || videoAdapter.getPlayhead() < 1)) { ret = this.getNpawReference().Constants.AdPosition.Preroll; } else if ( videoAdapter && videoAdapter.flags.isJoined && videoAdapter.getPlayhead() + this.duration + 1 >= videoAdapter.getDuration() ) { ret = this.getNpawReference().Constants.AdPosition.Postroll; } } return ret; } firstQuartileListener(e) { this.fireQuartile(1); } getIsLive() { let ret = null; if (this.player.levels && this.player.levels[this.player.currentLevel]) { ret = this.player.levels[this.player.currentLevel].details.live; } return ret; } getTitle() { let ret = this.title; if (this.player && !this.isDAI) { ret = this.player.getCurrentAd().getTitle(); } return ret; } registerListeners() { this.references = {}; if (google.ima.AdEvent) { this.monitorPlayhead(true, false); const event = google.ima.AdEvent.Type; this.references[event.CONTENT_PAUSE_REQUESTED] = this.playListener.bind(this); this.references[event.LOADED] = this.loadedListener.bind(this); this.references[event.PAUSED] = this.pauseListener.bind(this); this.references[event.STARTED] = this.playingListener.bind(this); this.references[event.RESUMED] = this.playingListener.bind(this); this.references[google.ima.AdErrorEvent.Type.AD_ERROR] = this.errorListener.bind(this); this.references[event.COMPLETE] = this.endedListener.bind(this); this.references[event.CONTENT_RESUME_REQUESTED] = this.endedListener.bind(this); this.references[event.SKIPPED] = this.skippedListener.bind(this); this.references[event.CLICK] = this.clickListener.bind(this); this.references[event.ALL_ADS_COMPLETED] = this.endedViewListener.bind(this); this.references[event.LOG] = this.logListener.bind(this); this.references[event.FIRST_QUARTILE] = this.firstQuartileListener.bind(this); this.references[event.MIDPOINT] = this.secondQuartileListener.bind(this); this.references[event.THIRD_QUARTILE] = this.thirdQuartileListener.bind(this); this.references[event.CONTENT_RESUME_REQUESTED] = this.breakEndListener.bind(this); } if (google.ima.dai) { const eventDAI = google.ima.dai.api.StreamEvent.Type; this.references[eventDAI.SKIPPED] = this.skippedL.bind(this); this.references[eventDAI.ERROR] = this.errorDAIListener.bind(this); this.references[eventDAI.AD_BREAK_STARTED] = this.startDAIListener.bind(this); this.references[eventDAI.AD_BREAK_ENDED] = this.stopDAIListener.bind(this); this.references[eventDAI.AD_PROGRESS] = this.progressDAIListener.bind(this); this.references[eventDAI.CLICK] = this.clickDAIListener.bind(this); this.references[eventDAI.STARTED] = this.joinDAIListener.bind(this); this.references[eventDAI.LOADED] = this.loadedDAIListener.bind(this); this.references[eventDAI.COMPLETE] = this.completeDAIListener.bind(this); this.references[eventDAI.FIRST_QUARTILE] = this.firstQuartileListener.bind(this); this.references[eventDAI.MIDPOINT] = this.secondQuartileListener.bind(this); this.references[eventDAI.THIRD_QUARTILE] = this.thirdQuartileListener.bind(this); this.references[eventDAI.PAUSED] = this.pauseDAIListener.bind(this); this.references[eventDAI.RESUMED] = this.resumeDAIListener.bind(this); } if (this.player) { for (let key in this.references) { this.player.addEventListener(key, this.references[key]); } } } loadedDAIListener(e) { if (e.getStreamData) { const streamData = e.getStreamData(); if (streamData) { this.resource = streamData.url; } } } stopDAIListener(e) { this.fireStop( { adPlayhead: this.duration }, 'stopDAIListener' ); if (this.getVideo().getAdapter()) { this.getVideo().getAdapter().fireResume({}, 'stopDAIListener'); } this.fireBreakStop(); } getResource() { let ret = null; if (!this.isDAI && this.player.getCurrentAd()) { ret = this.player.getCurrentAd().getMediaUrl(); } else if (this.isDAI) { ret = this.resource; } return ret; } getProvider() { let ret = null; if (!this.isDAI && this.player.getCurrentAd()) { ret = this.player.getCurrentAd().getAdSystem(); } return ret; } skippedL() { this.fireSkip(); } skippedListener(e) { this.fireSkip({ adPlayhead: this.getPlayhead() }); } joinDAIListener(e) { const adData = e.getAd(); if (adData) { this.duration = adData.getDuration(); this.title = adData.getTitle(); this.width = adData.getVastMediaWidth(); this.height = adData.getVastMediaHeight(); this.advertiser = adData.getAdvertiserName(); this.adPosition = this.getAdPosition(); } if (this.getVideo().getAdapter()) this.getVideo().getAdapter().firePause({}, 'joinDAIListener'); this.plugin.fireInit(undefined, 'joinDAIListener', this.getVideo().getVideoKey()); this.fireStart({}, 'joinDAIListener'); this.fireJoin({}, 'joinDAIListener'); } completeDAIListener(e) { this.fireStop({}, 'completeDAIListener'); } getPlayerName() { return 'IMA'; } getIsVisible() { let ret = null; if (this.player) { if (!this.contentPlayer) { for (const key in this.player) { const element = this.player[key]; if (!!element && element.videoHeight && element.clientHeight) { this.contentPlayer = element; break; } } } ret = this.getNpawUtils().calculateAdViewability(this.contentPlayer); } return ret; } playingListener(e) { this.fireStart( { adPlayhead: '0' }, 'playingListener' ); this.fireResume({}, 'playingListener'); this.fireSeekEnd({}, 'playingListener'); this.fireBufferEnd({}, 'playingListener'); this.fireJoin( { adPlayhead: '0' }, 'playingListener' ); } endedViewListener(e) { if (this.getPosition() === this.getNpawReference().Constants.AdPosition.Postroll) { this.getVideo().getAdapter().fireStop({}, 'endedViewListener'); } } getPosition() { let ret = null; if (this.player) { if (this.getVideo().getAdapter() && !this.getVideo().getAdapter().flags.isJoined) { ret = this.getNpawReference().Constants.AdPosition.Preroll; } else if (this.getIsLive()) { ret = this.getNpawReference().Constants.AdPosition.Midroll; } else { ret = this.adPosition || this.getNpawReference().Constants.AdPosition.Midroll; } } return ret; } errorListener(e) { this.fireError(undefined, undefined, undefined, undefined, 'errorListener'); this.fireStop({}, 'errorListener'); } breakEndListener(e) { this.fireBreakStop(); } getBreaksTime() { const observedOffsets = this._getObservedBreakOffsets(); let cuepoints = observedOffsets.length ? observedOffsets : this._getCuePoints(); const contentDuration = this._getContentDurationForBreaks(); if (cuepoints && cuepoints.length) { // If no break has been observed yet, ignore IMA's synthetic postroll marker (-1). if (!observedOffsets.length) { cuepoints = cuepoints.filter(function (cuePoint) { return cuePoint !== -1 && cuePoint !== null && cuePoint !== undefined; }); } cuepoints = cuepoints.map( function (cuePoint) { return this._normalizeCuePoint(cuePoint, contentDuration); }.bind(this) ); cuepoints = cuepoints.filter(function (cuePoint) { return cuePoint !== null && cuePoint !== undefined; }); } return cuepoints && cuepoints.length ? cuepoints : []; } clickDAIListener(e) { this.fireClick(this.clickUrl); } pauseDAIListener(e) { this.firePause({}, 'pauseDAIListener'); var videoAdapter = this.getVideo().getAdapter(); if (videoAdapter) { videoAdapter.flags.isAdPaused = true; } } resumeDAIListener(e) { this.fireResume({}, 'resumeDAIListener'); var videoAdapter = this.getVideo().getAdapter(); if (videoAdapter) { videoAdapter.flags.isAdPaused = false; } } }