Appearance
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-webQuick 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
timeupdateevent (~4x per second) - Use
EXT-X-PROGRAM-DATE-TIMEfrom HLS manifests when available
Timecode sources (in priority order):
- ID3 timed metadata (COMM, TXXX, TPE1 frames with JSON
{ut: timestamp}) - Elemental PRIV tags (
com.elementaltechnologies.timestamp.utc) EXT-X-PROGRAM-DATE-TIMEfrom HLS fragments- 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:
| Event | Data | When |
|---|---|---|
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 (send1on 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 integrationplugins/devicetime- Device time generator for testing
Troubleshooting
Overlay not showing:
- Check
viewContaineris in DOM beforeinit() - Verify z-index stacking order
- Check browser console for errors
Timecodes not syncing:
- Ensure
player.timeemits on everytimeupdate - 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.