src/formats/outstream.js
import { cpexLog, cpexError, addIframe, loadScript, addElement, enrichVast } from '../utils.js'
/**
* Integrated outstream video ad format, using video.js library
*/
export default class Outstream {
constructor (elementId, adUnit, main, width, height) {
this.main = main
this.type = 'outstream'
this.elementId = elementId
this.adUnit = adUnit
this.settings = main.settings.formats.outstream
this.loaded = false
this.width = width || 640
this.height = height || 360
cpexLog('Outstream: Caught Outstream custom format, in elementId ' + elementId)
}
async render (winningBid, vastUrl, vastXml) {
try {
if (winningBid) {
vastUrl = winningBid.vastUrl
vastXml = winningBid.vastXml
} else {
vastUrl = enrichVast(vastUrl) // add gdpr, gdpr_consent, correlator and npa to vastUrl if needed
}
if (!vastUrl && !vastXml) { throw new Error('No VAST URL or XML provided') }
// Load video.js library and css into an iframe
this.containerEl = document.getElementById(this.elementId)
this.iframe = addIframe(this.containerEl, { id: this.elementId + '-iframe', width: this.width, height: this.height })
const styleLoad = loadScript(this.iframe.contentDocument, 'https://cdn.cpex.cz/video/video-js.min.css', 'video.js style', 'link')
const playerLoad = loadScript(this.iframe.contentDocument, 'https://cdn.cpex.cz/video/video-js.min.js', 'video.js script')
const pluginLoad = loadScript(this.iframe.contentDocument, 'https://cdn.cpex.cz/video/vast-plugin.js', 'VAST plugin')
await Promise.all([styleLoad, playerLoad, pluginLoad])
cpexLog('Outstream: video.js library loaded')
this.loaded = true
this.videoContainerEl = addElement('div', this.iframe.contentDocument.body, { id: 'cpex-outstream' })
this.videoEl = addElement('video', this.videoContainerEl, { class: 'video-js', width: this.width, height: this.height, preload: 'auto', muted: true })
const context = this.iframe.contentWindow
const options = { autoplay: 'muted', controls: false, width: this.width, height: this.height, loop: false, autoSetup: false, fluid: true, language: 'cs', playsinline: true }
this.player = context.videojs(this.videoEl, options)
this.playerReady = new Promise(resolve => this.player.ready(resolve))
this.vastPlugin = new context.VASTplugin({ iframeWindow: context, player: this.player })
this.vast = await this.vastPlugin.loadVast(vastXml || vastUrl)
await Promise.all([this.playerReady, this.vast])
this.play()
cpexLog('Outstream: Playing')
} catch (e) {
cpexError('Outstream: Error loading video.js library', e)
}
}
play () {
if (!this.vast || !this.vast.mediaFile || !this.vast.mediaFile.url) {
return cpexError('Outstream: No playable media in VAST')
}
this.vastPlugin.pingUrls(this.vast.errorUrls)
this.player.src({ src: this.vast.mediaFile.url, type: this.vast.mediaFile.type || 'video/mp4' })
// clickthrough overlay
if (this.vast.clickThroughUrl) {
this.overlay = this.vastPlugin.addClickOverlay(this.videoContainerEl, () => {
try { this.vastPlugin.pingUrls(this.vast.clickTrackingUrls) } finally {
this.iframe.contentWindow.open(this.vast.clickThroughUrl, '_blank', 'noopener')
}
})
}
this.player.play()
if (this.main.headerbidding) {
this.main.headerbidding.triggerBidWon(this.adUnit)
}
// this.player.on('ended', () => this.onVideoEnd())
}
// onVideoEnd () { console.log('Outstream video ended') }
/**
* Returns the page to its original state
*/
reset () {
if (this.iframe) { this.iframe.remove() }
if (this.vastPlugin) { this.vastPlugin.destroy() }
if (this.overlay && this.overlay.parentNode) {
this.overlay.parentNode.removeChild(this.overlay)
}
// if (this.overlay?.parentNode) { this.overlay.parentNode.removeChild(this.overlay) }
const ads = window.cpexPackage.customAds
if (ads) { delete ads[this.elementId] }
}
}