Skip to content

Instantly share code, notes, and snippets.

@yuhui
Last active December 8, 2021 09:24
Show Gist options
  • Save yuhui/9fbd4ce5172327cdba6edab0f1825273 to your computer and use it in GitHub Desktop.
Save yuhui/9fbd4ce5172327cdba6edab0f1825273 to your computer and use it in GitHub Desktop.
Track Brightcove IFRAME video playback events with CustomEvents
/**
* @fileoverview Detects video playback events in the Brightcove player and
* send a CustomEvent for each of them.
*
* @author yuhui
* @version 1.0.0
*
* @see https://player.support.brightcove.com/coding-topics/overview-player-api.html
* Brightcove Player development overview
* @see https://docs.brightcove.com/brightcove-player/current-release/Player.html
* Brightcove Player API
* @see https://html.spec.whatwg.org/#mediaevents
* HTML5 media events
*
* @copyright 2021 Yuhui.
*
* @license GPL-3.0-or-later
* Licensed under the GNU General Public License, Version 3.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.gnu.org/licenses/gpl-3.0.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @disclaimer This Software is provided "as-is" and any expressed or implied
* warranties, including, but not limited to, the implied warranties of
* merchantability and fitness for a particular purpose are disclaimed. In no
* event shall the regents or contributors be liable for any direct, indirect,
* incidental, special, exemplaray, or consequential damages (including, but
* not limited to, procurement of substitute goods or services; loss of use,
* data, or profits; or business interruption) however caused and on any theory
* of liability, whether in contract, strict liability, or tort (including
* negligence or otherwise) arising in any way out of the use of this software,
* even if advised of the possibility of such damage.
*/
/**
* @private
* Given a playback event, get other metadata related to the event,
* then send the event's details in a CustomEvent.
* @param {Event} event The playback event.
* @this {object} The Brightcove player object.
*/
function handlePlaybackEvent_(event) {
var eventType = event.type;
var eventTarget = event.target;
var player = this;
var eventName = '';
switch (eventType) {
case 'loadeddata':
eventName = 'Loaded Data';
break;
case 'volumechange':
eventName = 'Volume Change';
break;
default:
eventName = eventType.charAt(0).toUpperCase() + eventType.slice(1);
break;
}
eventName = 'Video ' + eventName;
var videoName = player.mediainfo.name;
var eventDetail = {
player: player,
playerEventTarget: eventTarget,
playerState: eventType,
currentTime: player.currentTime(),
duration: player.duration(),
muted: player.muted(),
playbackRate: player.playbackRate(),
videoBufferedPercent: player.bufferedPercent(),
videoId: player.mediainfo.id,
videoName: videoName,
videoTitle: videoName,
videoUrl: player.currentSrc(),
volume: parseInt(player.volume() * 100),
};
var eventInit = {
detail: eventDetail,
};
var customEvent = new CustomEvent(eventName, eventInit);
(window.frameElement || window.parent).dispatchEvent(customEvent);
}
/**
* @public
* Post messages to the window frame for specific media playback events.
* @param {int} numTries Counter of tries to check that players are valid.
* @throws any error from Brightcove's `videojs` object.
*/
function handleBrightcovePlayers(numTries) {
var players = videojs.getPlayers();
var playerIds = Object.keys(players);
if (playerIds.length === 0) {
// players are not ready, try again
// give up after a total of about 7.5 seconds
if (numTries < 10) {
// use exponential backoff to delay
setTimeout(function() {
var numTries = numTries * 2;
handleBrightcovePlayers(numTries);
}, numTries * 500);
}
} else {
// a Brightcove IFRAME can only include one player
var playerId = playerIds[0];
try {
videojs.getPlayer(playerId).ready(function() {
var player = this;
var playerEvents = [
'ended',
'loadeddata',
'pause',
'play',
'stalled',
'timeupdate',
'volumechange',
];
playerEvents.forEach(function(playerEvent) {
player.on(playerEvent, handlePlaybackEvent_);
});
});
} catch (e) {
// use a warning, not an error, so that other scripts can run normally
console.warn(e);
}
}
}
handleBrightcovePlayers(1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment