Skip to content

Ease Live Bridge SDK Integration Guide for Hls.js

Overview

The Ease Live Bridge SDK connects your video player to the Ease Live overlay system. The SDK handles communication between your player and interactive overlays that display synchronized content based on video timecodes.

Installation

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

Quick Start

typescript
import EaseLive from '@ease-live/ease-live-bridge-web';
import hlsjsPlugin from '@ease-live/ease-live-bridge-web/plugins/hlsjs';
import Hls from 'hls.js';

const video = document.getElementById('video');
const hls = new Hls();

const easeLive = new EaseLive({
  accountId: 'your-account-id',
  programId: 'your-program-id',
  viewContainer: '#ease-live-view',
  playerPlugin: [hlsjsPlugin, {
    player: Hls,
    container: video,
    source: 'https://your-stream.m3u8',
    instance: hls,
  }],
});

easeLive.init();

Critical Concepts

1. Timecode Synchronization

The most important aspect of integration is sending accurate timecodes. The overlay content is synchronized to these timecodes.

Requirements:

  • Timecodes must be Unix timestamps in milliseconds
  • Strip decimals: use Math.floor(time)
  • Send on every video timeupdate event (~4x per second)
  • Use EXT-X-PROGRAM-DATE-TIME from HLS manifests when available

Timecode sources (in priority order):

  1. ID3 timed metadata (COMM, TXXX, TPE1 frames with JSON {ut: timestamp})
  2. Elemental PRIV tags (com.elementaltechnologies.timestamp.utc)
  3. EXT-X-PROGRAM-DATE-TIME from HLS fragments
  4. Interpolation from last known timecode

Interpolation example:

javascript
let lastTimecode = null;
let lastPosition = 0;

function onTimecodeReceived(timecode) {
  lastTimecode = timecode;
  lastPosition = video.currentTime;
}

function onTimeUpdate() {
  if (lastTimecode) {
    const diff = video.currentTime - lastPosition;
    const interpolated = lastTimecode + (diff * 1000);
    easeLive.emit('player.time', { timecode: Math.floor(interpolated) });
  }
}

video.addEventListener('timeupdate', onTimeUpdate);

2. Layer Stacking Order

The Ease Live overlay must be positioned between the video and player controls:

┌─────────────────────────────────┐
│  Player Controls (z-index: 2)   │  ← Clickable, above overlay
├─────────────────────────────────┤
│  Ease Live View (z-index: 1)    │  ← Interactive overlay
├─────────────────────────────────┤
│  Video Element (z-index: 0)     │  ← Base video layer
└─────────────────────────────────┘

HTML Structure:

html
<div id="player-wrapper">
  <video id="video"></video>
  <!-- Ease Live view inserted here dynamically -->
  <div id="controls">...</div>
</div>

CSS:

css
#player-wrapper {
  position: relative;
}

#video {
  position: absolute;
  width: 100%;
  height: 100%;
}

#ease-live-view {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
}

#controls {
  position: absolute;
  bottom: 0;
  width: 100%;
  z-index: 2;
}

3. Player Controls and Navigation

Ease Live changes how player controls work. Traditional video players have invisible click zones covering the entire video surface for play/pause. With Ease Live, the overlay needs that space for interactive graphics.

Key principle: Player controls must be confined to a small area (typically a bottom bar) and NOT cover the full video. The Ease Live layer needs navigational freedom across the entire video surface to enable interactive graphics.

┌─────────────────────────────────────┐
│                                     │
│     Ease Live interactive area      │  ← Clickable overlay graphics
│     (full video surface)            │
│                                     │
├─────────────────────────────────────┤
│  ▶  advancement advancement   🔊 ⛶  │  ← Controls (small, bottom only)
└─────────────────────────────────────┘

Requirements:

  • Controls positioned above overlay (z-index: 2)
  • Controls confined to bottom bar with fixed height, NOT full-screen click zones
  • No invisible overlays intercepting clicks meant for Ease Live
  • If native controls can be separated from the video element, they work fine

Toggle controls visibility via stage.clicked:

javascript
const controls = document.getElementById('controls');

// Toggle controls when clicking the overlay background
easeLive.on('stage.clicked', () => {
  controls.classList.toggle('visible');
});

CSS for toggle:

css
#controls {
  position: absolute;
  bottom: 0;
  height: 40px;  /* Fixed height, not full video */
  opacity: 0;
  transition: opacity 0.2s;
}

#controls.visible {
  opacity: 1;
}

4. Dynamic View Container

Create the view container after player is ready and insert it in the correct DOM position:

javascript
const viewContainer = document.createElement('div');
viewContainer.id = 'ease-live-view';

easeLive.on('player.ready', () => {
  // Insert before controls, after video
  playerWrapper.insertBefore(viewContainer, controls);
});

Required Events

Your player plugin must emit these events:

EventDataWhen
player.ready{ playerContainer, instance }Player initialized
player.time{ timecode: number }Every timeupdate (~4x/sec)
player.state{ state: 'playing' | 'paused' }Play/pause state changes

Optional events:

  • player.speed - { speed: number } - Playback rate (send 1 on ready)
  • player.volume - { volume: 0-100 }
  • player.mute - { mute: boolean }
  • player.error - { type: 'fatal' | 'warning', message: string }

Live Stream Support

For live streams, detect via HLS.js and adjust controls:

javascript
hls.on(Hls.Events.LEVEL_LOADED, (event, data) => {
  if (data.details.live) {
    // Hide seek bar and time display
    // Show LIVE badge instead
  }
});

TypeScript Support

The SDK includes full TypeScript definitions:

typescript
import EaseLive from '@ease-live/ease-live-bridge-web';
import type { EaseLiveOptions, PlayerPlugin } from '@ease-live/ease-live-bridge-web';
import type { HlsjsPluginConfig } from '@ease-live/ease-live-bridge-web/plugins/hlsjs';

Available Plugins

  • plugins/hlsjs - HLS.js integration
  • plugins/devicetime - Device time generator for testing

Troubleshooting

Overlay not showing:

  • Check viewContainer is in DOM before init()
  • Verify z-index stacking order
  • Check browser console for errors

Timecodes not syncing:

  • Ensure player.time emits on every timeupdate
  • Verify timecode is Unix ms (13 digits)
  • Check HLS stream has EXT-X-PROGRAM-DATE-TIME

Controls not clickable:

  • Controls must have higher z-index than overlay
  • Controls must be separable from video element for independent positioning

Overlay clicks not working:

  • Remove full-screen click zones that intercept clicks meant for Ease Live
  • Controls must be confined to bottom bar, not cover entire video
  • Check for invisible overlays (play/pause zones) blocking the Ease Live layer

Example

See the complete working example in /example/ directory.