Documentation Index Fetch the complete documentation index at: https://mintlify.com/lastninja294/adgent-sdk/llms.txt
Use this file to discover all available pages before exploring further.
Optimization
Smart TV platforms have unique constraints compared to desktop browsers. This guide covers optimization strategies for bundle size, performance, and platform-specific limitations.
Bundle Size Optimization
The SDK is designed to be lightweight with minimal dependencies.
Current Bundle Size
From README.md:405:
Metric Value Gzipped Size < 20 KB Minified Size ~50 KB Dependencies 1 (fast-xml-parser)
Tree Shaking
Use ES modules for optimal tree shaking:
// Good: Import only what you need
import { AdPlayer , getPlatformAdapter } from 'adgent-sdk' ;
// Avoid: Importing entire module
import * as Adgent from 'adgent-sdk' ;
Build configuration (Webpack/Vite):
// webpack.config.js
module . exports = {
optimization: {
usedExports: true ,
sideEffects: false
},
resolve: {
mainFields: [ 'module' , 'main' ]
}
};
// vite.config.js
export default {
build: {
minify: 'terser' ,
terserOptions: {
compress: {
drop_console: true // Remove console.logs in production
}
}
}
} ;
Lazy Loading
Load the SDK only when needed:
class VideoPlayer {
private adPlayer : any = null ;
async playPrerollAd ( vastUrl : string ) {
// Lazy load SDK only when ad is needed
if ( ! this . adPlayer ) {
const { AdPlayer } = await import ( 'adgent-sdk' );
this . adPlayer = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl
});
await this . adPlayer . init ();
}
}
async playMainContent () {
// Main content doesn't load ad SDK
this . mainVideo . play ();
}
}
Benefits :
Reduces initial bundle size
Ad SDK only loaded when ads are served
Faster app startup
Code Splitting
Split ad-related code into separate chunk:
// routes/video.tsx
import { lazy , Suspense } from 'react' ;
// Lazy load ad player component
const AdPlayerComponent = lazy (() => import ( './components/AdPlayer' ));
function VideoPage () {
return (
< div >
< Suspense fallback = {<div>Loading ad ...</ div > } >
< AdPlayerComponent vastUrl = "https://example.com/vast.xml" />
</ Suspense >
< MainVideoPlayer />
</ div >
);
}
Bitrate Selection Strategy
Choosing the right bitrate is critical for TV performance.
Default Bitrate
From src/core/AdPlayer.ts:23:
const DEFAULT_CONFIG = {
targetBitrate: 2500 , // ~1080p quality
// ...
};
From src/core/PlatformAdapter.ts:357:
Platform Recommended Bitrate Reason Tizen 15000 kbps High-end Samsung TVs handle it well WebOS 15000 kbps Modern LG TVs FireTV 10000 kbps Good performance Roku 8000 kbps Conservative (variable HEVC support) Xbox/PS 20000 kbps Game consoles have powerful hardware Generic 5000 kbps Safe default for web
Adaptive Bitrate Selection
import { AdPlayer , getPlatformAdapter } from 'adgent-sdk' ;
function getOptimalBitrate () : number {
const adapter = getPlatformAdapter ();
const settings = adapter . getRecommendedVideoSettings ();
let bitrate = settings . maxBitrate ;
// Adjust based on screen resolution
switch ( adapter . capabilities . maxResolution ) {
case '4k' :
bitrate = Math . min ( bitrate , 8000 );
break ;
case '1080p' :
bitrate = Math . min ( bitrate , 3500 );
break ;
case '720p' :
bitrate = Math . min ( bitrate , 2000 );
break ;
}
// Further reduce for specific platforms
if ( adapter . platform === 'roku' ) {
bitrate = Math . min ( bitrate , 6000 ); // Roku struggles with high bitrates
}
return bitrate ;
}
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
targetBitrate: getOptimalBitrate ()
});
Network-Aware Bitrate
Adjust based on network conditions:
async function getNetworkAwareBitrate () : Promise < number > {
const adapter = getPlatformAdapter ();
let baseBitrate = adapter . getRecommendedVideoSettings (). maxBitrate ;
// Check connection type (if available)
if ( 'connection' in navigator ) {
const connection = ( navigator as any ). connection ;
if ( connection . effectiveType === '4g' ) {
baseBitrate = Math . min ( baseBitrate , 5000 );
} else if ( connection . effectiveType === '3g' ) {
baseBitrate = Math . min ( baseBitrate , 2000 );
} else if ( connection . effectiveType === '2g' ) {
baseBitrate = Math . min ( baseBitrate , 800 );
}
// Reduce for slow connections
if ( connection . downlink && connection . downlink < 5 ) {
baseBitrate = Math . min ( baseBitrate , 2000 );
}
}
return baseBitrate ;
}
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
targetBitrate: await getNetworkAwareBitrate ()
});
VAST Caching
Cache VAST responses to reduce network requests and improve performance.
In-Memory Cache
class VASTCache {
private cache = new Map < string , { response : string ; timestamp : number }>();
private ttl = 300000 ; // 5 minutes
async getVAST ( vastUrl : string ) : Promise < string > {
const cached = this . cache . get ( vastUrl );
if ( cached && Date . now () - cached . timestamp < this . ttl ) {
console . log ( 'Using cached VAST' );
return cached . response ;
}
// Fetch fresh VAST
const response = await fetch ( vastUrl );
const vastXml = await response . text ();
// Cache it
this . cache . set ( vastUrl , {
response: vastXml ,
timestamp: Date . now ()
});
return vastXml ;
}
clear () {
this . cache . clear ();
}
}
// Usage
const vastCache = new VASTCache ();
async function playAd ( vastUrl : string ) {
// Get cached or fresh VAST
const vastXml = await vastCache . getVAST ( vastUrl );
// Convert to data URL to avoid re-fetch
const vastDataUrl = `data:text/xml;base64, ${ btoa ( vastXml ) } ` ;
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: vastDataUrl
});
await player . init ();
}
LocalStorage Cache
For persistent caching across sessions:
class PersistentVASTCache {
private storageKey = 'adgent_vast_cache' ;
private ttl = 3600000 ; // 1 hour
async getVAST ( vastUrl : string ) : Promise < string > {
try {
const cacheData = localStorage . getItem ( this . storageKey );
if ( cacheData ) {
const cache = JSON . parse ( cacheData );
const entry = cache [ vastUrl ];
if ( entry && Date . now () - entry . timestamp < this . ttl ) {
console . log ( 'Using cached VAST from localStorage' );
return entry . response ;
}
}
} catch ( e ) {
console . warn ( 'Cache read failed:' , e );
}
// Fetch fresh
const response = await fetch ( vastUrl );
const vastXml = await response . text ();
// Save to cache
this . saveToCache ( vastUrl , vastXml );
return vastXml ;
}
private saveToCache ( vastUrl : string , vastXml : string ) {
try {
const cacheData = localStorage . getItem ( this . storageKey );
const cache = cacheData ? JSON . parse ( cacheData ) : {};
cache [ vastUrl ] = {
response: vastXml ,
timestamp: Date . now ()
};
localStorage . setItem ( this . storageKey , JSON . stringify ( cache ));
} catch ( e ) {
console . warn ( 'Cache write failed:' , e );
}
}
clear () {
localStorage . removeItem ( this . storageKey );
}
}
Be mindful of localStorage size limits (typically 5-10MB). Clear old entries periodically.
1. Minimize DOM Operations
// Bad: Multiple DOM operations
const container = document . getElementById ( 'ad-container' );
container . style . position = 'relative' ;
container . style . width = '100%' ;
container . style . height = '100%' ;
container . style . background = '#000' ;
// Good: Single operation with cssText
const container = document . getElementById ( 'ad-container' );
container . style . cssText = '
position: relative ;
width : 100 % ;
height : 100 % ;
background : # 000 ;
' ;
2. Cleanup Resources
Always destroy the player when done:
const player = new AdPlayer ({ /* config */ });
await player . init ();
// ... ad plays ...
// IMPORTANT: Cleanup
player . destroy ();
The destroy() method (src/core/AdPlayer.ts:770):
Removes event listeners
Cleans up video element
Removes UI elements
Clears tracking data
3. Debounce Progress Updates
function debounce ( func : Function , wait : number ) {
let timeout : NodeJS . Timeout ;
return ( ... args : any []) => {
clearTimeout ( timeout );
timeout = setTimeout (() => func ( ... args ), wait );
};
}
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
// Debounce UI updates
onProgress: debounce (( progress ) => {
updateProgressBar ( progress . percentage );
}, 100 ) // Update every 100ms instead of every frame
});
4. Reduce Timeout Values
From README.md:417:
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
timeout: 8000 , // Faster timeout = faster failure recovery
maxWrapperDepth: 3 // Reduce wrapper depth for faster loads
});
5. Disable Debug in Production
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
debug: process . env . NODE_ENV === 'development' // Only debug in dev
});
Debug mode logs extensively which impacts performance.
6. Use sendBeacon for Tracking
import { getPlatformAdapter } from 'adgent-sdk' ;
const adapter = getPlatformAdapter ();
if ( adapter . capabilities . sendBeacon ) {
// Use sendBeacon - more efficient
navigator . sendBeacon ( trackingUrl , data );
} else {
// Fallback
fetch ( trackingUrl , { method: 'POST' , body: data , keepalive: true });
}
Smart TV Constraints
Memory Limitations
Smart TVs typically have 512MB - 2GB RAM, much less than desktops.
Problem: Memory Leaks
// Bad: Creates memory leak
const players : AdPlayer [] = [];
function playAd ( vastUrl : string ) {
const player = new AdPlayer ({ /* config */ });
players . push ( player ); // Never cleaned up!
await player . init ();
}
Solution: Proper Cleanup
// Good: Single player instance, properly cleaned up
class AdManager {
private currentPlayer : AdPlayer | null = null ;
async playAd ( vastUrl : string ) {
// Clean up previous player
if ( this . currentPlayer ) {
this . currentPlayer . destroy ();
this . currentPlayer = null ;
}
// Create new player
this . currentPlayer = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl ,
onComplete : () => {
this . cleanup ();
},
onError : () => {
this . cleanup ();
}
});
await this . currentPlayer . init ();
}
cleanup () {
if ( this . currentPlayer ) {
this . currentPlayer . destroy ();
this . currentPlayer = null ;
}
}
}
Video Element Limits
// Limit number of video elements
class VideoManager {
private static MAX_VIDEOS = 2 ; // Main + Ad
private videos : HTMLVideoElement [] = [];
createVideo () : HTMLVideoElement {
// Remove excess videos
while ( this . videos . length >= VideoManager . MAX_VIDEOS ) {
const old = this . videos . shift ();
if ( old && old . parentNode ) {
old . pause ();
old . src = '' ;
old . load ();
old . remove ();
}
}
const video = document . createElement ( 'video' );
this . videos . push ( video );
return video ;
}
}
Network Limitations
TV WiFi chips are often slower than mobile/desktop.
Optimize VAST Requests
// Reduce wrapper depth to minimize network requests
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
maxWrapperDepth: 3 , // Limit to 3 redirects
timeout: 12000 // Longer timeout for TV WiFi
});
Prefetch VAST
class VideoPlayer {
private vastCache : string | null = null ;
// Prefetch VAST before showing ad
async prefetchAd ( vastUrl : string ) {
try {
const response = await fetch ( vastUrl );
this . vastCache = await response . text ();
console . log ( 'VAST prefetched' );
} catch ( e ) {
console . error ( 'Prefetch failed:' , e );
}
}
async playAd () {
const vastDataUrl = this . vastCache
? `data:text/xml;base64, ${ btoa ( this . vastCache ) } `
: 'https://example.com/vast.xml' ;
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: vastDataUrl
});
await player . init ();
}
}
Compression
Ensure VAST responses are gzip compressed:
// Server-side (Express example)
app . get ( '/vast.xml' , ( req , res ) => {
res . set ( 'Content-Encoding' , 'gzip' );
res . set ( 'Content-Type' , 'text/xml' );
res . send ( gzippedVast );
});
CPU Constraints
TV processors are slower than desktop CPUs.
Avoid Heavy Computation
// Bad: Heavy computation on every progress update
player . on (( event ) => {
if ( event . type === 'progress' ) {
// This runs every ~16ms!
const analytics = computeComplexAnalytics ( event . data );
sendToServer ( analytics );
}
});
// Good: Throttle heavy operations
let lastAnalyticsTime = 0 ;
player . on (( event ) => {
if ( event . type === 'progress' ) {
const now = Date . now ();
// Send analytics every 5 seconds max
if ( now - lastAnalyticsTime > 5000 ) {
lastAnalyticsTime = now ;
const analytics = computeComplexAnalytics ( event . data );
sendToServer ( analytics );
}
}
});
Use requestIdleCallback
function scheduleBackgroundTask ( task : () => void ) {
if ( 'requestIdleCallback' in window ) {
requestIdleCallback ( task );
} else {
// Fallback for platforms without requestIdleCallback
setTimeout ( task , 1 );
}
}
player . on (( event ) => {
if ( event . type === 'complete' ) {
// Schedule non-critical work for idle time
scheduleBackgroundTask (() => {
cleanupCache ();
sendBatchedAnalytics ();
});
}
});
Recommended Configuration
Optimized configuration for Smart TV platforms:
import { AdPlayer , getPlatformAdapter } from 'adgent-sdk' ;
const adapter = getPlatformAdapter ();
const settings = adapter . getRecommendedVideoSettings ();
// Conservative bitrate for TVs
const targetBitrate = Math . min ( settings . maxBitrate , 3500 );
const player = new AdPlayer ({
container: document . getElementById ( 'ad-container' ),
vastUrl: 'https://example.com/vast.xml' ,
// Performance optimizations
targetBitrate , // Platform-appropriate bitrate
maxWrapperDepth: 3 , // Limit redirects
timeout: 12000 , // Generous timeout for TV WiFi
debug: false , // Disable debug in production
// Lifecycle management
onComplete : () => {
player . destroy (); // Clean up immediately
resumeMainContent ();
},
onError : ( error ) => {
console . error ( error );
player . destroy (); // Always clean up on error
resumeMainContent ();
},
onSkip : () => {
player . destroy ();
resumeMainContent ();
}
});
await player . init ();
Next Steps
Configuration Learn about all configuration options
Platform Detection Optimize for specific TV platforms
Error Handling Handle errors efficiently
Event Handling Optimize event handling