Skip to content

Ease Live Bridge HTML5 SDK

This is a guide for developers to get up and running with the Ease Live Bridge SDK for HTML5.

This library allows you as a web developer to integrate Ease Live with your chosen video streaming player on your web site.

Customers that have their own website and want to integrate it with Ease Live need a convenient way to do so. They may have their own player or a specific player they want to use. The Ease Live UI needs to be in sync with the video player in terms of duration, buffering, timecodes, etc. With the Ease Live Bridge SDK the customer can do this in the easiest and fastest way possible.

Ease Live supports browsers with native ES2015 support.

  • Chrome 87+
  • Edge 88+
  • Firefox 78+
  • Opera 99+
  • Safari 14+

Installation

NPM

The package can be downloaded from Ease Live's private NPM registry. To get access, add the following line to your .npmrc file.

@ease-live:registry=https://easelive.jfrog.io/artifactory/api/npm/npm-public/

Put it in one of these two places:

  • per-project config file (/path/to/my/project/.npmrc)
  • per-user config file (~/.npmrc)

To learn more about npm config files, head on over to NPM's official docs on the subject.

Once the npm config is in place, install the package:

sh
npm install @ease-live/ease-live-bridge-web

Then in your application you can import/require the library:

js
var EaseLive = require('@ease-live/ease-live-bridge-web')

or use ES6 module syntax:

js
import EaseLive from '@ease-live/ease-live-bridge-web'

Examples

A list of Codesandbox examples can be found here.

The EaseLive instance

Every Ease Live Bridge application starts by creating a new EaseLive instance with the EaseLive function:

js
const easeLive = new EaseLive({
	// project and environment to load
	accountId: 'tutorials',
	// projectId: '0346ae3e-7a91-4760-bcd3-cd84bb6790dd', // optional. it is inferred by program
	programId: '2d2711ff-6ff2-41c1-a141-060e9ffa2c38',
	env: 'prod',

	// optionally override parameters set by the environment.
	// they will appear as query string params in the generated URL,
	// such as &myQueryParam=value
	params: {
		myQueryParam: 'value',
	},

	// DOM element in which the Ease Live overlay will render
	viewContainer: '#ease-live-container',

	// setup integration with player. See section "Writing a player plugin"
	playerPlugin: (easeLive, config) => {
		// overlay will load when player ready is emitted
		easeLive.emit('player.ready', {});
	}
});

easeLive.init();

The values in the code above will load an SDK installation UI that will help verifying your implementation.

Optionally, you can send in an env variable to the configuration. That will allow you to generate multiple target overlay URLs under settings in your program. If not specified, env defaults to prod. Other values are staging and dev. If the staging and dev URLs doesn't exist in project settings, the SDK will make sure to fallback to the prod URL.

js
const easeLive = new EaseLive({
	// ...
	env: 'dev'
})

When you create an EaseLive instance, you pass in an options object. The majority of features in the Ease Live Bridge can be configured to create your desired behavior using options. For reference, you can also browse the full list of options in the API reference. When the instance is created, the lifecycle of a bridge will start.

The initialization of the EaseLive bridge will start when the init() method is invoked: easeLive.init().

To remove the EaseLive bridge, call the destroy() method. This will make sure that any event handlers are removed, along with the overlay itself.

Lifecycle Diagram

Ease Live Bridge lifecycle

Event dispatcher

  • Add a new listener: easeLive.on(event, listener)
  • Remove a listener: easeLive.off(event, listener)
  • Trigger an event: easeLive.emit(event, payload)

Error handling

Listen for errors emitted from the EaseLive instance and overlay. The error listener should be added before easeLive.init().

If the type is "fatal" overlay can not continue and the EaseLive instance should be destroyed. For example: the project or main program failed to load.

If the type is "warning" something failed, but the overlay can continue with reduced functionality. For example: a custom plugin failed to load.

js
easeLive.on('easelive.error', (e) => {
	if (e.type === 'fatal') {
		easeLive.destroy();
		easeLive = null;
	}
});

Status handling

Listen for change in status of the loaded overlay, which can change during runtime.

If the status is "disabled" the EaseLive instance can be destroyed.

If the status is "hidden" or "disabled", when used on TV, the focus should be moved to player controls.

js
easeLive.on('app.status', ({status}) => {
	if (status === 'disabled') {
		// overlay is disabled
		easeLive.destroy();
		easeLive = null;
		// if on TV, move focus to your player controls
	} else if (status === 'hidden') {
		// overlay is hidden, but can be enabled later
		// if on TV, move focus to your player controls
	} else if (status === 'enabled') {
		// overlay is enabled
	}
});

Plugins

Plugins can add additional functionality to the EaseLive instance. There is no strictly defined scope for a plugin, however it is usually used for adding extra functionality to the bridge by adding listeners to the lifecycle events.

Writing a plugin

A plugin should expose an install method. This method will be called with the easeLive instance as the first argument, along with possible options.

js
MyPlugin.install = function (easeLive, options) {
	// 1. add listeners to lifecycle events
	easeLive.on('player.time', function (event) {
		// some logic using the player timecode ...
	})

	// 2. add your own lifecycle events
	easeLive.emit('myplugin.create', {
		// some options ...
	)

	// 3. add global method or property to the EaseLive instance
	easeLive.myGlobalMethod = function () {
		// some custom logic ...
	}
}

Using a plugin

Use plugins by calling the easeLive.use global method.

js
easeLive.use(MyPlugin)

You can optionally pass in some options:

js
easeLive.use(MyPlugin, {someOption: true})

easeLive.use automatically prevents you from using the same plugin more than once.

Writing a player plugin

The main job of a player plugin is to handle the communication between the player and the bridge SDK. Any player events triggered will be received by the web app. As a minimum, the player plugin needs to handle the following events:

  • player.time
  • player.state

A player plugin is very similar to writing a regular plugin, with a few subtle differences:

  • there can only be one player plugin in use at the time (per bridge instance)
  • the plugin won't be called immediately, but at the appropriate time after easeLive.init() has been called
  • the plugin should return a player instance

As an example, here's a player plugin for video.js. See API reference for full list of events.

js
function install(easeLive, config) {
	// 1. Listen for the overlay requesting the player to change its state

	// event from EaseLive to change player controls visibility when the EL background was clicked
	easeLive.on('stage.clicked', ({ controls }) => {
		player.userActive(controls === 'visible');
	}, true);
	// event from EaseLive when mouse pointer enters view container, can be used to show controls
	easeLive.on('view.mouseenter', () => {
		player.userActive(true);
	}, true);

	// event from EaseLive to change player state
	easeLive.on('player.state', ({ state }) => {
		if (state === 'playing') player.play();
		if (state === 'paused') player.pause();
	}, true);

	// event from EaseLive to seek to the position of an absolute time
	let currentTimecode;
	easeLive.on('player.time', ({ timecode }) => {
		if (currentTimecode > 0) {
			// calculate the timeline position for the absolute time
			const diff = (timecode - currentTimecode) / 1000;
			const position = player.currentTime() + diff;
			player.currentTime(position);
		}
	}, true);

	// 2. Listen for changes in the player's state and notify EaseLive

	// notify EaseLive when player controls visibility changes
	player.on('useractive', () => {
		easeLive.emit('player.controls', { controls: 'visible' });
	});
	player.on('userinactive', () => {
		easeLive.emit('player.controls', { controls: 'hidden' });
	});

	// notify EaseLive when player state changes
	function onPlayerState(state) {
		easeLive.emit('player.state', { state });
	}
	player.on('playing', () => { onPlayerState('playing') });
	player.on('pause', () => { onPlayerState('paused'); });
	player.on('stalled', () => { onPlayerState('buffering'); });
	player.on('seeking', () => { onPlayerState('seeking'); });
	player.on('seeked', () => { onPlayerState('playing'); });

	// notify EaseLive when the absolute UTC time for the current playback position is read from stream
	player.textTracks().addEventListener('addtrack', function (addTrackEvent) {
		const track = addTrackEvent.track;
		track.addEventListener('cuechange', function (cueChangeEvent) {
			if (track.activeCues.length <= 0) return;
			for (let cueIdx = 0; cueIdx < track.activeCues.length; cueIdx++) {
				// read time from metadata
				const cue = track.activeCues[cueIdx];
				if (cue.value.dateTimeObject) {
					// example: timecode from EXT-X-PROGRAM-DATE-TIME in a HLS stream
					const timecode = cue.value.dateTimeObject.getTime()
					currentTimecode = timecode;
					easeLive.emit('player.time', { timecode });
				}
			}
		}, false);
	}, false);

	// notify EaseLive when player is ready
	player.ready(() => {
		easeLive.emit('player.ready', {});
	});
}

export default install;

For additional examples, see the src/plugins folder in the SDK package.

Custom bridge messages

Custom messages can be used to send data from the web page to the Ease Live overlay, and to receive data from the overlay. This can be used for custom functionality in the overlay.

Sending a message to the overlay

js
easeLive.emit('appMessage', {
    event: 'myPrefix.myEvent',
    metadata: {
		myCustomValue: "some data"
	}
});

To receive this message in the overlay configure a "Bridge message is received" trigger on the Bridge data source in the Studio project.

Receiving a message from the overlay

A message can be sent from the overlay by configuring a "Send bridge message" trigger in the Studio project.

Such messages can be received in the container web page by listening for it:

js
easeLive.on('myPrefix.myEvent', (event) => {
	console.log(event.metadata.myCustomValue)
});