In video_player.js
, define a video player wrapper class to initiate and
control the dash.js player.
Set up the broadband player
Define where in your app to place the broadband player by creating video and wrapper tags:
<div id="broadband-wrapper"> <video id="broadband-video"></video> </div>
Create the video player
Initialize the video player class with variables for HTML elements, the dash.js player, and callbacks that other class methods can use.
/** * Video player wrapper class to control ad creative playback with dash.js in * broadband. */ var VideoPlayer = function() { this.videoElement = document.querySelector('video'); this.broadbandWrapper = document.getElementById('broadband-wrapper'); this.player = dashjs.MediaPlayer().create(); this.onAdPodEndedCallback = null; // Function passed in VideoPlayer.prototype.setEmsgEventHandler. this.onCustomEventHandler = null; // Scope (this) passed in VideoPlayer.prototype.setEmsgEventHandler. this.customEventHandlerScope = null; // Function to remove all of player event listeners. this.cleanUpPlayerListener = null; debugView.log('Player: Creating dash.js player'); };
Define the playback control functions
To show the ad player and attach the video view, create the VideoPlayer.play()
method. Afterwards, create the create VideoPlayer.stop()
method to handle
clean-up after ad pods finish.
/** Starts playback of ad stream. */ VideoPlayer.prototype.play = function() { debugView.log('Player: Start playback'); this.show(); this.player.attachView(this.videoElement); }; /** Stops ad stream playback and deconstructs player. */ VideoPlayer.prototype.stop = function() { debugView.log('Player: Request to stop player'); if (this.cleanUpPlayerListener) { this.cleanUpPlayerListener(); } this.player.reset(); this.player.attachView(null); this.player.attachSource(null); this.player = null; this.hide(); };
Preload the ad stream manifest
To ensure ads are sufficiently loaded during the content stream and before the
ad break begins, use VideoPlayer.preload()
and VideoPlayer.isPreloaded()
.
1. Preload the ad stream
Create the VideoPlayer.preload()
method to preload the ad stream manifest and
build up an ad buffer prior to an ad break. You must update the player streaming
settings 'cacheInitSegments'
to true
. By updating the settings, you enable
caching the init segments, which avoids delays when switching to ads.
/** * Starts ad stream prefetching into Media Source Extensions (MSE) buffer. * @param {string} url manifest url for ad stream playback. */ VideoPlayer.prototype.preload = function(url) { if (!this.player) { this.player = dashjs.MediaPlayer().create(); } debugView.log('Player: init with ' + url); this.player.initialize(/* HTMLVideoElement */ null, url, /* autoplay */ true); this.player.updateSettings({ 'debug': { 'logLevel': dashjs.Debug.LOG_LEVEL_WARNING, 'dispatchEvent': true, // flip to false to hide all debug events. }, 'streaming': { 'cacheInitSegments': true, } }); this.player.preload(); this.attachPlayerListener(); debugView.log('Player: Pre-loading into MSE buffer'); };
2. Check the preloaded ad buffer
Create the VideoPlayer.isPreloaded()
method to check if enough ad buffer has
preloaded compared to a buffer threshold set in the app:
// Ads will only play with 10 or more seconds of ad loaded. var MIN_BUFFER_THRESHOLD = 10;
/** * Checks if the ad is preloaded and ready to play. * @return {boolean} whether the ad buffer level is sufficient. */ VideoPlayer.prototype.isPreloaded = function() { var currentBufferLevel = this.player.getDashMetrics() .getCurrentBufferLevel('video', true); return currentBufferLevel >= MIN_BUFFER_THRESHOLD; };
Attach player listeners
To add event listeners for the dash.js player event, create the
VideoPlayer.attachPlayerListener()
method: PLAYBACK_PLAYING
,
PLAYBACK_ENDED
, LOG
, and ERROR
. This method also handles events for the
scheme ID URI, in addition to setting the clean-up function to remove these
listeners.
var SCHEME_ID_URI = 'https://developer.apple.com/streaming/emsg-id3';
/** Attaches event listener for various dash.js events.*/ VideoPlayer.prototype.attachPlayerListener = function() { var playingHandler = function() { this.onAdPodPlaying(); }.bind(this); this.player.on(dashjs.MediaPlayer.events['PLAYBACK_PLAYING'], playingHandler); var endedHandler = function() { this.onAdPodEnded(); }.bind(this); this.player.on(dashjs.MediaPlayer.events['PLAYBACK_ENDED'], endedHandler); var logHandler = function(e) { this.onLog(e); }.bind(this); this.player.on(dashjs.MediaPlayer.events['LOG'], logHandler); var errorHandler = function(e) { this.onAdPodError(e); }.bind(this); this.player.on(dashjs.MediaPlayer.events['ERROR'], errorHandler); var customEventHandler = null; if (this.onCustomEventHandler) { customEventHandler = this.onCustomEventHandler.bind(this.customEventHandlerScope); this.player.on(SCHEME_ID_URI, customEventHandler); } this.cleanUpPlayerListener = function() { this.player.off( dashjs.MediaPlayer.events['PLAYBACK_PLAYING'], playingHandler); this.player.off(dashjs.MediaPlayer.events['PLAYBACK_ENDED'], endedHandler); this.player.off(dashjs.MediaPlayer.events['LOG'], logHandler); this.player.off(dashjs.MediaPlayer.events['ERROR'], errorHandler); if (customEventHandler) { this.player.off(SCHEME_ID_URI, customEventHandler); } }; };
Set player event callbacks
To manage the ad pod playback based on player events, create the
VideoPlayer.onAdPodPlaying()
, VideoPlayer.onAdPodEnded()
, and
VideoPlayer.onAdPodError()
methods:
/** * Called when ad stream playback buffered and is playing. */ VideoPlayer.prototype.onAdPodPlaying = function() { debugView.log('Player: Ad Playback started'); }; /** * Called when ad stream playback has been completed. * Will call the restart of broadcast stream. */ VideoPlayer.prototype.onAdPodEnded = function() { debugView.log('Player: Ad Playback ended'); this.stop(); if (this.onAdPodEndedCallback) { this.onAdPodEndedCallback(); } }; /** * @param {!Event} event The error event to handle. */ VideoPlayer.prototype.onAdPodError = function(event) { debugView.log('Player: Ad Playback error from dash.js player.'); this.stop(); if (this.onAdPodEndedCallback) { this.onAdPodEndedCallback(); } };
Create the setter for the onAdPodEnded
event
Set a callback function that runs when an ad pod ends by creating the
VideoPlayer.setOnAdPodEnded()
method. The app class uses this method to resume
the content broadcast after ad breaks.
/** * Sets a callback function for when an ad pod has ended. * @param {!Function} callback Callback function. */ VideoPlayer.prototype.setOnAdPodEnded = function(callback) { this.onAdPodEndedCallback = callback; };
Handle stream metadata events
Set a callback function that runs based on emsg events by creating the
VideoPlayer.setEmsgEventHandler()
method. For this guide, include the scope
parameter, as you evoke setEmsgEventHandler()
outside of video_player.js
.
/** * Sets emsg event handler. * @param {!Function} customEventHandler Event handler. * @param {!Object} scope JS scope in which event handler function is called. */ VideoPlayer.prototype.setEmsgEventHandler = function( customEventHandler, scope) { this.onCustomEventHandler = customEventHandler; this.customEventHandlerScope = scope; };
Show and hide the video player for ad breaks
To display the video player during ad breaks, and hide the player after the ad
break finishes, create the VideoPlayer.show()
and VideoPlayer.hide()
methods:
/** Shows the video player. */ VideoPlayer.prototype.show = function() { debugView.log('Player: show'); this.broadbandWrapper.style.display = 'block'; }; /** Hides the video player. */ VideoPlayer.prototype.hide = function() { debugView.log('Player: hide'); this.broadbandWrapper.style.display = 'none'; };
Next, create an ads manager class to use the IMA SDK to make a stream request, get an ad pod manifest, listen to IMA stream events, and pass emsg events to the IMA SDK.