@rideview/livestream-web-sdk
v1.2.0
Published
Lightmetrics LiveStream SDK
Readme
LiveStream SDK --- Technical Documentation
1. Overview
The LiveStreamSDK enables real-time streaming from devices using:
WebRTC → Media transport (low-latency streaming)
HLS → CDN-friendly scalable playback
Socket.IO signaling → Session negotiation
Factory-based transport selection → Host decides streaming mode
Event-driven architecture → Unified lifecycle events for UI
Browser autoplay-safe playback
This SDK is designed for web portals.
2. Architecture
HostApplication
│
▼
LiveStreamSDK
│
├───────────────► Session Service ─────────► HTTP Client ─────────► Backend API
│ │
│ ├─ Session Creation
│ ├─ 409 Conflict Recovery (only for WebRTC)
│ └─ Returns Session
│
▼
StreamPlayerFactory
│
├──────────────► WebRTC Player
│ │
│ ├────────► SignalingClient (Socket Connection)
│ │ │
│ │ ▼
│ │ Signaling Server
│ │ │
│ │ └─ Exchanges ICE
│ │
│ └────────► PeerConnectionManager
│ │ │
│ │ ├─ Connects to relay server
│ │ └─ Receives the media
│ │
│ └────────► Attaches VideoStream
│ │
│ ▼
│ HTMLVideoElement
│
└──────────────► HLS Player
│
└─ Feeds Source Stream
│
▼
HTMLVideoElementIntegration Overview
| Mode | Responsibility | Use Case |
| -------------------- | ----------------------------------------------------------------- | ----------------------------------------- |
| sdk-managed | SDK handles API calls (Start / Stop / Join) via SessionService. | Standalone apps, simple integrations. |
| external-managed | Host provides session object; SDK skips lifecycle API calls. | Micro-frontends, shared backend sessions. |
3. Module Documentation
| Module | Layer | Responsibility | | --------------------- | ---------------------- | ----------------------------------------------------------------------------------- | | LiveStreamSDK | Facade / Orchestration | Public API for host, manages lifecycle, selects player via factory, re-emits events | | StreamPlayerFactory | Creation | Creates correct player (WebRTCPlayer, HLSPlayer) based on host choice | | IStreamPlayer | Abstraction | Defines common contract all players must follow | | WebRTCPlayer | Real-Time Transport | Handles WebRTC session, signaling coordination, attaches RTC media | | HLSPlayer | HTTP Streaming | Handles HLS playback via hls.js / native HLS | | Telemetry | External Monitoring | Error tracking across the SDK lifecycle for external monitoring plugins | | PeerConnectionManager | WebRTC Engine Wrapper | Manages RTCPeerConnection, ICE, tracks, MediaStream | | SignalingClient | Communication | Handles Socket.IO messaging for SDP/ICE exchange | | SessionService | API Calls | Handles session related API calls and automatic stream recovery. | | EventEmitter | Infrastructure | Provides internal event system between modules |
3.1 EventEmitter
File: utils/EventEmitter.ts
class EventEmitter {
-listeners: Record<string, Listener[]>
+on(event, cb)
+off(event, cb)
+removeAllListeners(event?)
#emit(event, data)
}Used For:
- Player → SDK communication
- SDK → Host UI events
- Lifecycle propagation
3.2 SessionService
File: session/sessionService.ts
Handles session related API calls and automatic stream recovery.
class SessionService {
- LiveStreamAPI api
- HttpClient http
- getHeaders()
+ createOrJoinRTCSession(payload: any)
+ createRTCSession(payload: any)
+ joinRTCSession(streamRequestId: string, fleetId: string)
+ createHLSSession(payload: any)
+ endSession(streamRequestId: string, fleetId: string)
}
3.3 SignalingClient
File: signaling/SignalingClient.ts
Handles ONLY signaling transport (no WebRTC logic).
class SignalingClient {
-socket: Socket
+connect(config)
+sendAnswer(answer)
+sendIce(candidate)
+sendMessage(type, payload)
+close()
}Socket connection is configured with automatic reconnection (reconnection: true, reconnectionAttempts: 3, reconnectionDelay: 1000).
Emits Events
| Event | Meaning | | ------------ | -------------------- | | connected | Socket established | | disconnected | Socket lost | | message | Offer / ICE received |
3.4 PeerConnectionManager
File: webrtc/PeerConnectionManager.ts
Encapsulates pure WebRTC logic.
class PeerConnectionManager {
-pc: RTCPeerConnection
-stream: MediaStream
+init(iceServers)
+handleOffer(offer)
+addIceCandidate(candidate)
+getStream()
+addTrack(track)
+removeTrack(track)
+close()
}3.5 IStreamPlayer
File: players/IStreamPlayer.ts
Defines contract implemented by all playback types.
class IStreamPlayer {
<<interface>>
+init(session)
+attach(element)
+stop()
+on(event, cb)
+off(event, cb)
+removeAllListeners(event?)
+sendMessage(type, payload)
}This abstraction allows adding new protocols without modifying SDK.
3.6 WebRTCPlayer
File: players/WebRTCPlayer.ts
Implements low-latency streaming using:
SignalingClientPeerConnectionManager- Relay transport
class WebRTCPlayer {
-signaling: SignalingClient
-pcManager: PeerConnectionManager
-mediaElement: HTMLMediaElement
}3.7 HLSPlayer
File: players/HLSPlayer.ts
Implements HTTP-based playback using:
hls.js(Chrome / Edge)- Native HLS (Safari)
class HLSPlayer {
-hls: Hls
-mediaElement: HTMLMediaElement
-url: string
}3.8 StreamPlayerFactory
File: factory/StreamPlayerFactory.ts
Creates appropriate player based on host preference.
StreamPlayerFactory.create('webrtc');
StreamPlayerFactory.create('hls');Adding a new protocol requires:
- Implement
IStreamPlayer - Register in factory
- No SDK changes required
class StreamPlayerFactory {
+create(mode): IStreamPlayer
}3.9 SdkTelemetry
File: telemetry/SDKtelemetry.ts | types/Telemetry.ts
Standardizes event normalization and error tracking across the SDK lifecycle for external monitoring plugins.
class SdkTelemetry {
- ITelemetryPlugin plugin
+ trackEvent(type: string, metadata?: object): void
+ trackError(sessionId: string, error: Error, phase: string): void
}
interface ITelemetryPlugin {
+ trackEvent(event: Omit<TelemetryEvent, 'timestamp' | 'sdkVersion'>): void
+ trackError(sessionId: string, error: Error, phase: string): void
}
type TelemetryEvent = {
type: string;
timestamp: number;
sdkVersion: string;
sessionId: string;
metadata?: Record<string, unknown>;
};
3.10 LiveStreamSDK (Public Interface)
File: LiveStreamSDK.ts
This is the only class host apps will use.
class LiveStreamSDK {
- HttpClient
- sessionService: SessionService
- player: IStreamPlayer
- sessionMode: SessionMode
- activeSession : SessionDetails
- state: SDKState
- internalStart(mode, fleetId, sessionResolver)
- safeRollback(session, fleetId)
- bindPlayerEvents()
- unbindPlayerEvents()
+ start(config, mode): Promise<SessionDetails>
+ startWithSession(session, mode, fleetId): Promise<SessionDetails>
+ join(streamRequestId, fleetId, mode): Promise<SessionDetails>
+ attach(element: HTMLVideoElement)
+ stop()
+ on(event, handler)
}
4. Streaming Lifecycle
Step 1 — Host Starts Stream
Depending on the initialization mode chosen in the constructor, the host calls one of two entry points:
SDK-Managed
const sessionDetails = await sdk.start(config, 'webrtc' | 'hls');start() returns:
{
currentSessionId: string;
fleetId: string;
currentMode: 'webrtc' | 'hls';
role: 'host' | 'guest';
sessionType?: 'basic';
}The config payload supports only the basic live stream session type ('basic').
Live Stream Video Configuration (sessionType: 'basic' or omitted):
const config = {
fleetId: 'fleet-abc',
deviceId: 'device-123',
userId: 'user-xyz',
sessionType: 'basic', // Optional
videoType: 'road', // 'road' | 'driver' | 'sideBySide' | 'pictureInPictureRoad' | 'pictureInPictureDriver' | 'MDVR'
unitSystem: 'metric', // 'metric' | 'imperial'
videoResolution: '1280x720', // // '1920x1080' | '1280x720' | '640x360' | '320x180'. Required for non-MDVR
};For videoType: 'MDVR', use:
collagesourcesresolution
(videoResolution is not required in MDVR mode.)
External-Managed
const sessionDetails = await sdk.startWithSession(sessionObject, 'webrtc', 'fleetId');startWithSession() supports only 'webrtc'.
Step 2 — Session Creation
The SDK resolves the session metadata required to initialize the transport layer.
SDK-managed mode
The SDK performs the API handshake depending on the mode:
- WebRTC
POST /v2/live/create-stream-request- HLS
POST /live/create-stream-request- HLS Guest / Join
POST /live/hls-sessionExternal-managed mode
The SDK skips the network request and immediately uses the provided sessionObject.
Step 3 — Conflict Resolution (Managed Mode Only)
If the backend returns a 409 Conflict (stream already active), the sessionService throws an API_SESSION_CONFLICT error. The host application must catch this error and explicitly call sdk.join(...) to join the active stream session as a guest.
WebRTC Guest Join
For WebRTC streams, guest joining issues:
POST /live/join-webrtc-streamExample Handling:
try {
await sdk.start(config, STREAM_MODES.WEBRTC);
} catch (error) {
if (error.code === 'API_SESSION_CONFLICT') {
const conflictId = error?.cause?.data?.conflictingRequestId;
await sdk.join(conflictId, config.fleetId, STREAM_MODES.WEBRTC);
} else {
throw error;
}
}HLS Guest Join
For HLS streams, guests can join the existing HLS session via:
POST /live/hls-sessionExample Handling:
// Guest joins HLS session using the host's active request ID
await sdk.join(activeStreamRequestId, fleetId, STREAM_MODES.HLS);
sdk.attach(videoElement);Host Role
- If
streamRequestIdis returned, the SDK acts as the owner. - The SDK calls the
stop()API on exit.
Guest Role
- If
conflictStreamRequestIdis used, the SDK acts as a viewer. - The SDK skips the
stop()API on exit.
Step 4 — Player Created via Factory
The internalStart logic passes the resolved session to the Factory.
Factory Creation
StreamPlayerFactory.create(mode);This instantiates the correct player implementation.
Event Binding
The SDK attaches internal listeners to the player:
connectedplayingbufferingstoppederrordevice-connectedleave
These events are proxied to the Host UI.
Transport Initialization
player.init(session);This starts signaling (WebRTC) or manifest loading (HLS).
Step 5 — Transport Initialization
WebRTC
- Offer ← Relay
- Answer → Relay
- ICE negotiation
HLS
- Manifest fetched
- Segments buffered
Step 6 — Media Rendering Begins
The video element emits:
"playing"The SDK then emits the **playing event`.
This represents the first frame rendered (TTFF milestone).
5. Events Exposed to Host Application
SDK normalizes events across WebRTC & HLS.
sdk.on("connected", ...)
sdk.on("playing", ...)
sdk.on("error", ...)
sdk.on("stopped", ...)
sdk.on("device-connected", ...)
sdk.on("buffering", ...)
sdk.on("leave", ...)| Event | Meaning | Payload / Data | | :------------------- | :---------------------------------- | :------------- | | connected | Stream session established | - | | playing | First frame rendered | - | | buffering | Playback is temporarily buffering | - | | error | Playback failure / conflict | Error object | | stopped | Stream session closed | - | | device-connected | Target device is connected & active | - | | leave | Viewer leaves or session ended | - |
Host UI should rely on "playing" to hide loader screens.
6. Error Handling
The SDK separates errors into two distinct categories to prevent unhandled promise rejections and to provide predictable failure handling.
Startup Errors
Startup errors occur before a connection or stream is successfully established.
Examples:
- Invalid authentication credentials
- API unavailable or unreachable
- Configuration errors during initialization
These errors:
- Do not emit SDK events
- Must be handled using
try/catch
try {
await sdk.start(config, 'webrtc');
} catch (error) {
console.error('Startup error:', error);
// Handle initialization failure
}Runtime / Stream Errors
Runtime errors occur after a session or stream has already started.
Examples:
- Network disconnection
- ICE negotiation failure
- WebRTC transport issues
- Unexpected stream termination
These errors:
- Emit an
errorevent - Do not automatically throw
You must subscribe to the error event:
sdk.on('error', (e) => {
console.error('Runtime error:', e);
// Handle recovery, cleanup, reconnection, UI updates, etc.
});7. Host Application Integration
HTML
<!-- For Video Streaming -->
<video id="video-player"></video>7.1 SDK Managed Mode
Initialise the SDK
import { LiveStreamSDK, LogLevel } from '@rideview/livestream-web-sdk';
const sdk = new LiveStreamSDK({
mode: 'sdk-managed',
apiBaseUrl: 'https://api.example.com',
// Option 1: Static headers
/*
headers: {
Authorization: "Bearer YOUR_ACCESS_TOKEN",
"x-tenant-id": "tenant-1"
},
*/
// Option 2: Dynamic header provider
headers: async () => {
const token = await authService.getFreshToken();
return {
Authorization: `Bearer ${token}`,
'x-tenant-id': getActiveTenant(),
};
},
// Optional: Override default API endpoints
endpoints: {
create: '/v3/start',
stop: '/v3/terminate',
join: '/v3/join',
createHLS: '/v3/startHLS',
hlsJoin: '/v3/joinHLS',
},
logLevel: LogLevel.DEBUG,
enableTelemetry: false,
});Start Video Streaming
const sessionDetails = await sdk.start(
{
deviceId: 'device-123',
fleetId: 'fleet-abc',
videoType: 'road',
unitSystem: 'imperial',
videoResolution: '640x360',
userId: 'userId',
},
'webrtc', // Options: 'webrtc' | 'hls'
);
sdk.attach(document.getElementById('video-player'));
console.log('Started session:', sessionDetails.currentSessionId, sessionDetails.role);7.2 External Managed Mode
Initialise the SDK
const sdk = new LiveStreamSDK({
mode: 'external-managed',
logLevel: LogLevel.DEBUG,
enableTelemetry: false,
});Create Session via Backend
The host application must create the stream session
const mySession = await fetch(`${EXTERNAL_API}`);Your backend should return a session object containing the necessary signalling information.
Start SDK with Session
const sessionDetails = await sdk.startWithSession(mySession, 'webrtc', 'fleet-abc');
sdk.attach(videoElement);
console.log('Started external session:', sessionDetails.currentSessionId);7.3 HLS Guest / Viewer Mode
When an HLS stream is active, viewers can scale and join as guests without causing session conflict errors.
// Guest joins an existing HLS stream session
await sdk.join('active-stream-request-id', 'fleet-abc', 'hls');
// Attach player
sdk.attach(document.getElementById('video-player'));8. Clean Shutdown
await sdk.stop();Ensures:
- Peer connection closed
- Socket disconnected
- HLS destroyed
- Event listeners cleaned
Prevents memory leaks & ghost sessions.
9. SDK Internal Dependencies
| Library | Purpose | | ---------------- | ---------------------------------------------------------------------- | | socket.io-client | WebRTC signaling transport | | hls.js | HLS playback (non-Safari browsers) | | sentry | Captures and reports browser-side errors for monitoring and debugging. | | tslib | Provides TypeScript helper functions to reduce bundle size. |
