Package Exports
- @xnstream/player-sdk
- @xnstream/player-sdk/package.json
Readme
XStream Player SDK
A powerful and feature-rich video player SDK for streaming content, built with TypeScript and HLS.js.
Features
- 🎥 HLS (HTTP Live Streaming) support - Industry-standard adaptive streaming
- 📊 Adaptive bitrate streaming - Automatic quality adjustment based on network conditions
- 🎯 Auto level capping - Restrict maximum quality based on resolution or bitrate
- 🎬 Multi-audio track support - Switch between different audio languages
- 📝 Subtitle/Caption support - Multiple subtitle tracks with language selection
- 📈 Analytics tracking - Built-in watch time, bandwidth, and error tracking
- 🎚️ Quality level switching - Manual or automatic quality control
- ⚡ Playback rate control - Speed up or slow down playback
- 🎨 Customizable branding - Server-controlled theming and messaging
- 📺 VAST/VPAID ads support - Pre-roll, mid-roll, and post-roll advertisements
- 🔄 Automatic error recovery - Smart retry strategies for recoverable errors
- 🎯 TypeScript support - Fully typed API for better development experience
- 🌐 Comprehensive event system - React to all player state changes
- 🔐 Secure playback - Session management and authentication
- 💾 Local storage integration - Secure device registration
Installation
npm install @xnstream/player-sdkQuick Start
import { StreamPlayer } from '@xnstream/player-sdk';
// Create player instance
const player = await StreamPlayer.create({
appId: 'your-app-id',
stream_code: 'your-stream-code',
containerId: 'player-container',
autoPlay: true,
startAt: 0
});
// Initialize the player
await player.initialize();
// Listen for events
player.on('ready', () => {
console.log('Player is ready');
});
player.on('playing', () => {
console.log('Playback started');
});
player.on('error', (error) => {
console.error('Playback error:', error);
});
// Play the stream
await player.play();API Reference
StreamPlayer
The main player class that handles video playback and streaming.
Core Methods
Player Lifecycle
create(options: StreamPlayerOptions): Promise<StreamPlayer>- Create player instanceinitialize(): Promise<void>- Initialize and load the streamdestroy(): void- Cleanup and destroy player instance
Playback Control
play(): Promise<void>- Start playbackpause(): void- Pause playbackseek(time: number): void- Seek to specific timerewind(offset?: number): void- Rewind by offset (default: 10s)fastForward(offset?: number): void- Fast forward by offset (default: 10s)seekToLive(): void- Jump to live edge (for live streams)
Volume Control
setVolume(volume: number): void- Set volume (0.0 to 1.0)getVolume(): number- Get current volumetoggleMute(): void- Toggle mute stateisMuted(): boolean- Check if muted
Playback Rate
setPlaybackRate(rate: number): void- Set playback speed (e.g., 0.5, 1.0, 2.0)getPlaybackRate(): number- Get current playback rate
Quality Control
switchLevel(level: number): void- Switch to specific quality levelgetLevels(): Level[]- Get available quality levelsgetCurrentLevel(): number- Get current quality level IDisAutolevelEnabled(): boolean- Check if automatic quality switching is enabled
Audio Tracks
getAudioTracks(): AudioTrack[]- Get available audio tracksgetCurrentAudioTrack(): number- Get current audio track IDsetAudioTrack(trackId: number): void- Switch audio track
Subtitle Tracks
getSubtitleTracks(): SubtitleTrack[]- Get available subtitle tracksgetCurrentSubtitleTrack(): number- Get current subtitle track ID (-1 = disabled)setSubtitleTrack(trackId: number): void- Switch subtitle track (-1 to disable)
Configuration
getPlayerConfig(): PlayerConfig | undefined- Get player configuration from backend
Events
Playback Events
ready- Player is ready to playplaying- Playback has startedpaused- Playback is pausedended- Playback has finishedbuffering- Player is buffering
Progress Events
onProgressUpdate: (progress: ProgressUpdate) => void- Progress updates (every 300ms)onDataLoaded: (duration: number) => void- Video metadata loaded
Quality Events
onLevelsLoaded: (levels: Level[]) => void- Quality levels detectedonLevelSwitch: (level: number) => void- Quality level changedonBufferUpdated: (buffer: BufferAppendedData) => void- Buffer updated
Audio Track Events
onAudioTracksLoaded: (tracks: AudioTrack[]) => void- Audio tracks detectedonAudioTrackSwitch: (trackId: number) => void- Audio track switched
Subtitle Track Events
onSubtitleTracksLoaded: (tracks: SubtitleTrack[]) => void- Subtitle tracks detectedonSubtitleTrackSwitch: (trackId: number) => void- Subtitle track switched
Control Events
volumechange: (volume: number) => void- Volume changedratechange: (rate: number) => void- Playback rate changed
Resource Events
onResourceChange: (resource: Resource) => void- Stream resource loaded
Error Events
error: (error: UnifiedError) => void- Error occurred (with retry information)
Ad Events
onAdStart: () => void- Ad playback startedonAdEnd: () => void- Ad playback completedonAdProgress: (progress) => void- Ad playback progressonAdError: (error: UnifiedError) => void- Ad error occurredonAdClick: () => void- User clicked on adonAdFirstQuartile: () => void- Ad 25% completeonAdSecondQuartile: () => void- Ad 50% completeonAdThirdQuartile: () => void- Ad 75% complete
Configuration
StreamPlayerOptions
interface StreamPlayerOptions {
appId: string; // Your application ID
stream_code: string; // Stream identifier
containerId: string; // DOM element ID for player
autoPlay?: boolean; // Auto-start playback (default: false)
startAt?: number; // Start position in seconds
lowlatenctMode?: boolean; // Enable low-latency mode for live streams
context?: Record<string, any>; // Custom context for analytics
adOptions?: IAdsRequest; // Advertisement configuration
levelCapping?: LevelCappingOptions; // Auto quality level capping options
}
interface LevelCappingOptions {
width?: number; // Maximum video width
height?: number; // Maximum video height
bitrate?: number; // Maximum bitrate in bps
}PlayerConfig (Backend Configuration)
The player receives configuration from the backend that controls branding and behavior:
interface PlayerConfig {
controls?: {
viewsCounter?: boolean; // Show view counter
disablePause?: boolean; // Disable pause button
liveRewind?: boolean; // Enable rewind for live streams
autoPlay?: boolean; // Override client autoPlay setting
liveIcon?: boolean; // Show live indicator
};
branding?: {
theme?: string; // Theme name
colorScheme?: string; // Color scheme
pageTitle?: string; // Custom page title
offlineMessage?: string; // Custom offline message title
offlineDescription?: string; // Custom offline message description
};
}The backend configuration takes precedence over client options and provides custom error messages.
Advanced Features
Audio and Subtitle Tracks
The player supports multiple audio and subtitle tracks:
// Listen for available tracks
player.on('onAudioTracksLoaded', (tracks) => {
console.log('Audio tracks:', tracks);
// Display track selector UI
});
player.on('onSubtitleTracksLoaded', (tracks) => {
console.log('Subtitle tracks:', tracks);
// Display subtitle selector UI
});
// Switch tracks
player.setAudioTrack(1); // Switch to audio track 1
player.setSubtitleTrack(0); // Enable subtitle track 0
player.setSubtitleTrack(-1); // Disable subtitles
// React to track changes
player.on('onAudioTrackSwitch', (trackId) => {
console.log('Audio switched to:', trackId);
});
player.on('onSubtitleTrackSwitch', (trackId) => {
console.log('Subtitle switched to:', trackId);
});Error Handling
The SDK includes comprehensive error handling with automatic retry strategies:
player.on('error', (error) => {
console.log('Error type:', error.type);
console.log('Error context:', error.context);
console.log('Is retryable:', error.isRetryable);
console.log('Retry strategy:', error.retryStrategy);
console.log('Severity:', error.severity);
// All errors are automatically retried if retryable
// Custom error messages from backend are displayed
});Error Types:
validation- Input validation errorsclient- Client-side errors (4xx)server- Server-side errors (5xx)network- Network connectivity issuesmedia- Media playback errorsstorage- Local storage errorssecurity- Security/encryption errorsads- Advertisement errors
Error Contexts:
unauthorized,forbidden,notFoundsourceOffline,sessionExpiredgeoRestricted,deviceLimitReached,subscriptionRequiredmediaUnavailable,manifestError,fragmentErrornetworkTimeout,networkUnavailable- And more...
All errors include retry strategies with exponential backoff where appropriate.
Auto Level Capping
The SDK allows you to restrict the maximum quality level that can be selected automatically by the adaptive bitrate algorithm. This is useful for:
- Limiting bandwidth usage on mobile networks
- Matching video quality to device capabilities
- Preventing high-resolution playback on smaller screens
// Cap quality to 1080p (Full HD)
const player = await StreamPlayer.create({
appId: 'my-app-id',
stream_code: 'my-stream',
containerId: 'player-container',
levelCapping: {
width: 1920,
height: 1080
}
});
// Cap quality by bitrate (e.g., 5 Mbps)
const player = await StreamPlayer.create({
appId: 'my-app-id',
stream_code: 'my-stream',
containerId: 'player-container',
levelCapping: {
bitrate: 5000000 // 5 Mbps in bits per second
}
});
// Cap to 720p for mobile devices
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
const player = await StreamPlayer.create({
appId: 'my-app-id',
stream_code: 'my-stream',
containerId: 'player-container',
levelCapping: isMobile ? {
width: 1280,
height: 720
} : undefined
});How it works:
- The player finds the highest quality level that doesn't exceed your specified constraints
- If both
width/heightandbitrateare provided,width/heighttakes priority - The cap only affects automatic quality selection (ABR), not manual quality switching
- If no level matches the constraints, no capping is applied
Custom Error Messages
The player displays custom error messages from the backend configuration:
// Backend provides custom offline message via PlayerConfig
{
"branding": {
"offlineMessage": "Stream Temporarily Unavailable",
"offlineDescription": "We're experiencing technical difficulties. Check back soon."
}
}Analytics
The SDK includes built-in analytics tracking for:
- Watch time - Accurate playback duration tracking
- Bandwidth usage - Data consumption monitoring
- Error tracking - Comprehensive error reporting
- Quality level changes - Bitrate switching events
- Delivery metrics - Fragment loading performance
- Ad analytics - Advertisement interaction tracking
Type Definitions
The SDK is fully typed. Key types include:
import type {
StreamPlayer,
StreamPlayerOptions,
LevelCappingOptions,
StreamPlayerEvents,
Level,
AudioTrack,
SubtitleTrack,
PlayerConfig,
UnifiedError,
ProgressUpdate,
Resource
} from '@xnstream/player-sdk';Browser Support
- ✅ Chrome (latest)
- ✅ Firefox (latest)
- ✅ Safari (latest)
- ✅ Edge (latest)
- ✅ Mobile browsers (iOS Safari, Chrome Mobile)
Requires support for:
- ES2015+ JavaScript
- Promises/async-await
- Fetch API
- HLS.js compatibility
Example: Complete Player Setup
import { StreamPlayer } from '@xnstream/player-sdk';
import type { AudioTrack, SubtitleTrack, UnifiedError } from '@xnstream/player-sdk';
async function setupPlayer() {
// Create player
const player = await StreamPlayer.create({
appId: 'my-app-id',
stream_code: 'my-stream',
containerId: 'player-container',
autoPlay: false,
startAt: 0,
context: {
user_id: '12345',
session_type: 'premium'
}
});
// Setup event listeners
player.on('ready', () => {
console.log('Player ready');
});
player.on('onLevelsLoaded', (levels) => {
console.log('Quality levels:', levels);
});
player.on('onAudioTracksLoaded', (tracks) => {
// Build audio track selector
tracks.forEach(track => {
console.log(`Audio: ${track.name} (${track.lang})`);
});
});
player.on('onSubtitleTracksLoaded', (tracks) => {
// Build subtitle track selector
tracks.forEach(track => {
console.log(`Subtitle: ${track.name} (${track.lang})`);
});
});
player.on('error', (error: UnifiedError) => {
console.error('Error:', error.message);
if (error.isRetryable) {
console.log('Will retry automatically');
}
});
player.on('onProgressUpdate', (progress) => {
console.log(`Position: ${progress.position}s`);
});
// Initialize and play
await player.initialize();
await player.play();
// Example: Switch to Spanish audio
const spanishAudio = player.getAudioTracks().find(t => t.lang === 'es');
if (spanishAudio) {
player.setAudioTrack(spanishAudio.id);
}
// Example: Enable English subtitles
const englishSubs = player.getSubtitleTracks().find(t => t.lang === 'en');
if (englishSubs) {
player.setSubtitleTrack(englishSubs.id);
}
}
setupPlayer();License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
For issues and questions, please visit our GitHub repository.
Repository
This project is hosted on GitHub: https://github.com/caltek/xPlayerSDKJS