CSAI techniques
Vega supports two techniques for determining when to insert ads: out-of-band (standard) and in-band (advanced).Standard CSAI: out-of-band ads
In standard CSAI, the client app relies on external information, not manifest tags, to determine when to insert ads. The player receives an unmodified content manifest and handles ad logic separately. Ad triggering methods include:- VMAP: The player fetches an external XML file that schedules ad breaks at specific timestamps (for example, at 0s, 300s).
- Hardcoded logic: The application triggers ad requests at fixed intervals based on the player’s current time position (for example, every 20 seconds).
- Sidecar files: The app downloads a separate configuration file (JSON/XML) from a content management system (CMS) that lists ad break times for a specific piece of content.
- Ad SDKs: An SDK (such as Google Interactive Media Ads) manages timing internally via ad rules, removing the need for the developer to manage specific timestamps or manifest tags.
Advanced CSAI: in-band ads
In advanced CSAI, the player monitors the manifest for in-stream metadata markers that signal ad opportunities. Common markers include:#EXT-X-CUE-OUT), it interprets this as an ad avail opportunity and initiates a VAST or VMAP request to an ad server for the indicated duration. The ad content is fetched and buffered in parallel while the main content continues playing. The main content pauses only when the ad presentation time is reached. By this time, the ad is expected to be ready to play for a seamless experience.
In an in-band implementation using the Headless approach, the UI can send an ad list to the service layer via sendMessage({type: 'adList', ads}) to provide the same data that manifest parsing would produce. The service stores the ad list on the PlayerSession and processes ad markers during getCurrentPlaybackPosition(). When an ad’s pre-buffer window is reached (5 seconds before startTime), the service sends an {type: 'adMarkers', ad} message back to the UI, which then triggers ad insertion.
Playback sync strategies
Both implementation approaches support two strategies for coordinating the main and ad players during transitions.Pre-buffered ad (seamless)
The ad player is pre-initialized and buffered before the transition occurs. This provides a gapless user experience with no visual interruptions.- Main content plays.
- Ad marker detected. Pre-initialize ad player with
autoPlay=false. - Ad player buffers.
canplayevent fires (JS) or service sends READY status (Headless). - UI receives ready signal. Ad is ready to play, waits for scheduled playback time.
- Position listener detects ad start time reached. Pause main content.
- Main content paused. Clear main surface, set ad surface, play ad.
- Ad ends. Clear ad surface, clean up ad player, set main surface, resume main content.
- No visual interruption
- Pre-buffers ad content before playback
- Best for premium viewing experiences
autoPlaysetting:false(manual control)
Instant autoplay ad (with gap)
The ad player is initialized on-demand when the ad break occurs. Because the ad loads at playback time withautoPlay=true, there may be a brief transition gap during ad player initialization.
- Main content plays.
- Ad marker detected. Pause main content.
- Main content paused. Clear main surface, initialize ad player with
autoPlay=true. - Ad player ready. Set ad surface, playback starts automatically.
- Ad ends. Clear ad surface, clean up ad player, set main surface, resume main content.
- Brief black or pause screen possible during transition
- Loads ad on-demand
- Simpler implementation
autoPlaysetting:true(automatic playback)
Back-to-back advertisements
When your ad break contains multiple consecutive ads, you have three approaches depending on device capabilities:- Single ad player (resource-constrained devices): Create only a single ad player at a time to play a single advertisement. This may not provide seamless or gapless transitions and is only recommended for devices with limited memory or decoders.
- Multiple ad players (high-performance devices): Use two ad player instances for seamless back-to-back ad playback. Provides gapless transitions between consecutive ads. Requires sufficient device resources.
- Main content player recreation (alternative approach): Store the current playback position of primary content. Recreate the main player during the last ad playback. This allows creating two separate ad players on resource-constrained devices.
Challenges with CSAI
Consider the following challenges when implementing CSAI:- Buffering and latency: When ads are loaded on-demand (instant ads), pausing content to load ads can lead to buffering or latency. To resolve this, pre-buffered ads buffer the ad content before the actual presentation time and pause the main content only after sufficient buffering.
- Device compatibility: Inconsistent performance across different devices due to varying hardware capabilities (memory, decoders, processing power).
- Single surface rendering: The ad must play from the first frame after rendering the last frame of main content. There shouldn’t be missing frames or any overlap of frames during the surface switch.
- Surface clearing black flash: In shared surface mode, calling
clearSurfaceHandle(JS) orclearVideoView(Headless) clears the display buffer, causing a visible black frame between the main content’s last frame and the ad’s first frame. Use dual surface mode to avoid this.
Surface modes
Both implementation approaches support two surface modes for managing the video output during ad transitions.Single surface (shared)
Both the main player and the ad player share the sameKeplerVideoSurfaceView. Before the ad player can render to the surface, the main player must release it:
- JS approach: Call
clearSurfaceHandle(surfaceHandle)on the main player, then callsetSurfaceHandle(surfaceHandle)on the ad player. - Headless approach: Call
clearVideoView(sessionId)on the main player session, then callsetVideoView(surfaceHandle, sessionId)on the ad player session.
Dual surface
Each player has its own dedicatedKeplerVideoSurfaceView. The ad surface overlays the main content surface using zIndex positioning. The main player doesn’t need to release its surface when the ad plays.
Surface view layout (JSX)
The main content surface useszIndex: 1 and the ad surface uses zIndex: 2 so the ad renders on top:
Handling ads with different aspect ratios (dual surface)
When the ad and main content share the same aspect ratio (for example, both 16:9), the ad surface overlays the main content directly. No additional handling is needed. When the ad has a different aspect ratio than the main content, the inactive surface may be visible behind the active one due to the size mismatch. To prevent this, use offscreen rendering to move the inactive surface off-screen:const [adSurfaceVisible, setAdSurfaceVisible] = useState(false) and toggle it to true when the ad starts and false when the ad ends.
Ad duration enforcement
If the ad’s defined duration is less than the actual media duration, you can force-end the ad at the correct time using a position or time update listener:Choose your implementation approach
Vega provides two implementation approaches for CSAI. Choose the approach that matches your app architecture.JS approach
The JS approach uses direct React Native component integration.VideoPlayer instances are created and managed within the UI component layer. The application has direct access to W3C Media APIs and controls playback through direct method calls.
- Your app uses a single-threaded React Native architecture
- You want direct access to W3C Media API
- You prefer simpler component-level player management
@amazon-devices/react-native-w3cmedia
To implement this approach, see Implement client-side ad insertion using the JS approach.
Headless approach
The Headless approach uses a client-server architecture.IPlayerClient instances in the UI layer communicate with VideoPlayer instances managed in a separate service layer via KeplerPlayerClientTurboModule using JavaScript Interface (JSI) for high-performance inter-process communication (IPC).
- Your app uses a multi-threaded architecture with separate UI and service layers
- You need the performance benefits of JSI-based IPC
- You want session-based player management with
PlayerSession
Related content
- Implement client-side ad insertion using the JS approach
- Implement client-side ad insertion using the Headless approach

