UNPKG

videojs-contrib-ads

Version:

A framework that provides common functionality needed by video advertisement libraries working with video.js.

234 lines (194 loc) 8.28 kB
/* * Implements the public API available in `player.ads` as well as application state. */ import videojs from 'video.js'; import {version as adsVersion} from '../package.json'; export default function getAds(player) { return { disableNextSnapshotRestore: false, // This is true if we have finished actual content playback but haven't // dealt with postrolls and officially ended yet _contentEnding: false, // This is set to true if the content has officially ended at least once. // After that, the user can seek backwards and replay content, but _contentHasEnded // remains true. _contentHasEnded: false, // Tracks if loadstart has happened yet for the initial source. It is not reset // on source changes because loadstart is the event that signals to the ad plugin // that the source has changed. Therefore, no special signaling is needed to know // that there has been one for subsequent sources. _hasThereBeenALoadStartDuringPlayerLife: false, // Tracks if loadeddata has happened yet for the current source. _hasThereBeenALoadedData: false, // Tracks if loadedmetadata has happened yet for the current source. _hasThereBeenALoadedMetaData: false, // Are we after startLinearAdMode and before endLinearAdMode? _inLinearAdMode: false, // Should we block calls to play on the content player? _shouldBlockPlay: false, // Was play blocked by the plugin's playMiddleware feature? _playBlocked: false, // Tracks whether play has been requested for this source, // either by the play method or user interaction _playRequested: false, // This is an estimation of the current ad type being played // This is experimental currently. Do not rely on its presence or behavior! adType: null, VERSION: adsVersion, reset() { player.ads.disableNextSnapshotRestore = false; player.ads._contentEnding = false; player.ads._contentHasEnded = false; player.ads.snapshot = null; player.ads.adType = null; player.ads._hasThereBeenALoadedData = false; player.ads._hasThereBeenALoadedMetaData = false; player.ads._cancelledPlay = false; player.ads._shouldBlockPlay = false; player.ads._playBlocked = false; player.ads.nopreroll_ = false; player.ads.nopostroll_ = false; player.ads._playRequested = false; }, // Call this when an ad response has been received and there are // linear ads ready to be played. startLinearAdMode() { player.ads._state.startLinearAdMode(); }, // Call this when a linear ad pod has finished playing. endLinearAdMode() { player.ads._state.endLinearAdMode(); }, // Call this when an ad response has been received but there are no // linear ads to be played (i.e. no ads available, or overlays). // This has no effect if we are already in an ad break. Always // use endLinearAdMode() to exit from linear ad-playback state. skipLinearAdMode() { player.ads._state.skipLinearAdMode(); }, // With no arguments, returns a boolean value indicating whether or not // contrib-ads is set to treat ads as stitched with content in a single // stream. With arguments, treated as a setter, but this behavior is // deprecated. stitchedAds(arg) { if (arg !== undefined) { videojs.log.warn('Using player.ads.stitchedAds() as a setter is deprecated, ' + 'it should be set as an option upon initialization of contrib-ads.'); // Keep the private property and the settings in sync. When this // setter is removed, we can probably stop using the private property. this.settings.stitchedAds = !!arg; } return this.settings.stitchedAds; }, // Returns whether the video element has been modified since the // snapshot was taken. // We test both src and currentSrc because changing the src attribute to a URL that // AdBlocker is intercepting doesn't update currentSrc. videoElementRecycled() { if (player.ads.shouldPlayContentBehindAd(player)) { return false; } if (!this.snapshot) { throw new Error('You cannot use videoElementRecycled while there is no snapshot.'); } const srcChanged = player.tech_.src() !== this.snapshot.src; const currentSrcChanged = player.currentSrc() !== this.snapshot.currentSrc; return srcChanged || currentSrcChanged; }, // Returns a boolean indicating if given player is in live mode. // One reason for this: https://github.com/videojs/video.js/issues/3262 // Also, some live content can have a duration. isLive(somePlayer = player) { if (typeof somePlayer.ads.settings.contentIsLive === 'boolean') { return somePlayer.ads.settings.contentIsLive; } else if (somePlayer.duration() === Infinity) { return true; } else if (videojs.browser.IOS_VERSION === '8' && somePlayer.duration() === 0) { return true; } return false; }, // Return true if content playback should mute and continue during ad breaks. // This is only done during live streams on platforms where it's supported. // This improves speed and accuracy when returning from an ad break. shouldPlayContentBehindAd(somePlayer = player) { if (!somePlayer) { throw new Error('shouldPlayContentBehindAd requires a player as a param'); } else if (!somePlayer.ads.settings.liveCuePoints) { return false; } else { return !videojs.browser.IS_IOS && !videojs.browser.IS_ANDROID && somePlayer.duration() === Infinity; } }, // Return true if the ads plugin should save and restore snapshots of the // player state when moving into and out of ad mode. shouldTakeSnapshots(somePlayer = player) { return !this.shouldPlayContentBehindAd(somePlayer) && !this.stitchedAds(); }, // Returns true if player is in ad mode. // // Ad mode definition: // If content playback is blocked by the ad plugin. // // Examples of ad mode: // // * Waiting to find out if an ad is going to play while content would normally be // playing. // * Waiting for an ad to start playing while content would normally be playing. // * An ad is playing (even if content is also playing) // * An ad has completed and content is about to resume, but content has not resumed // yet. // // Examples of not ad mode: // // * Content playback has not been requested // * Content playback is paused // * An asynchronous ad request is ongoing while content is playing // * A non-linear ad is active isInAdMode() { return this._state.isAdState(); }, // Returns true if in ad mode but an ad break hasn't started yet. isWaitingForAdBreak() { return this._state.isWaitingForAdBreak(); }, // Returns true if content is resuming after an ad. This is part of ad mode. isContentResuming() { return this._state.isContentResuming(); }, // Deprecated because the name was misleading. Use inAdBreak instead. isAdPlaying() { return this._state.inAdBreak(); }, // Returns true if an ad break is ongoing. This is part of ad mode. // An ad break is the time between startLinearAdMode and endLinearAdMode. inAdBreak() { return this._state.inAdBreak(); }, /* * Remove the poster attribute from the video element tech, if present. When * reusing a video element for multiple videos, the poster image will briefly * reappear while the new source loads. Removing the attribute ahead of time * prevents the poster from showing up between videos. * * @param {Object} player The videojs player object */ removeNativePoster() { const tech = player.$('.vjs-tech'); if (tech) { tech.removeAttribute('poster'); } }, debug(...args) { if (this.settings.debug) { if (args.length === 1 && typeof args[0] === 'string') { videojs.log('ADS: ' + args[0]); } else { videojs.log('ADS:', ...args); } } } }; }