as

Settings
Sign out
Notifications
Alexa
Amazon Appstore
Ring
AWS
Documentation
Support
Contact Us
My Cases
Get Started
Design and Develop
Publish
Reference
Support

Implement client-side ad insertion using the JS approach

In this tutorial, you'll implement client-side ad insertion (CSAI) in your Vega app using the JS approach. This approach uses direct React Native component integration where VideoPlayer instances are created and managed within the UI component layer. You'll set up a dual-player architecture with a main player for content and an ad player that takes over a shared video surface during ad breaks.

The examples in this tutorial demonstrate pre-buffered ads for seamless ad transitions. For background on CSAI concepts, techniques, and sync strategies, see Client-side ad insertion in Vega.

In this tutorial, you learn how to:

  • Set up player references and imports
  • Detect an ad marker and pre-initialize the ad player
  • Wait for the ad to buffer, then pause main content
  • Switch the video surface and play the ad
  • Return to main content after the ad ends

Prerequisites

  • Vega development environment set up
  • Vega SDK v0.22 or later
  • @amazon-devices/react-native-w3cmedia package installed
  • Main content player already initialized and playing
  • Basic knowledge of React Native and TypeScript

Set up player references

Import the required components and create refs for the main player, ad player, and shared surface handle.

Copied to clipboard.


import { VideoPlayer, KeplerVideoSurfaceView } from '@amazon-devices/react-native-w3cmedia';

// Player references
const videoPlayer = useRef<VideoPlayer | null>(null);       // Main content player (already initialized)
const adVideoPlayer = useRef<VideoPlayer | null>(null);     // Ad player
const cachedSurface = useRef<any>(null);                    // Shared surface handle

Detect the ad marker and pre-initialize the ad player

When the app detects an upcoming ad break (for example, 5 seconds before the ad start time), pre-initialize the ad player and begin buffering the ad content with autoPlay=false.

  1. Register a timeupdate listener on the main player to detect upcoming ad breaks.

Copied to clipboard.


videoPlayer.current.addEventListener('timeupdate', () => {
  const currentTime = videoPlayer.current?.currentTime || 0;
  // App-specific logic to determine if an ad break is approaching
  // (e.g., VMAP schedule, sidecar file, hardcoded list, or ad SDK callback)
  if (adBreakApproaching(currentTime)) {
    initializeAdPlayer(AD_CONTENT_URL);
  }
});

  1. Create the ad player initialization function. Set autoPlay to false so you control when playback starts.

Copied to clipboard.


const initializeAdPlayer = async (adUrl: string) => {
  adVideoPlayer.current = new VideoPlayer();
  await adVideoPlayer.current.initialize();
  adVideoPlayer.current.autoplay = false;
  adVideoPlayer.current.addEventListener('canplay', onAdReady);
  adVideoPlayer.current.addEventListener('ended', onAdEnded);
  adVideoPlayer.current.src = adUrl;
};

Wait for the ad to buffer, then pause main content

After the ad player signals it is buffered (canplay) and the ad start time is reached, pause the main content.

Copied to clipboard.


const onAdReady = () => {
  // Ad is buffered — wait for the scheduled ad start time
  // When the position listener detects ad start time is reached:
  videoPlayer.current?.pause();
};

Switch the surface and play the ad

When the main content pauses, clear the main player's surface and assign it to the ad player.

Copied to clipboard.


videoPlayer.current.addEventListener('pause', () => {
  // Clear main player surface and assign to ad player
  videoPlayer.current?.clearSurfaceHandle(cachedSurface.current);
  adVideoPlayer.current?.setSurfaceHandle(cachedSurface.current);
  adVideoPlayer.current?.play();
});

Return to main content

After the ad finishes, clear the ad surface, clean up the ad player, and resume main content.

Copied to clipboard.


const onAdEnded = async () => {
  adVideoPlayer.current?.clearSurfaceHandle(cachedSurface.current);
  videoPlayer.current?.setSurfaceHandle(cachedSurface.current);
  videoPlayer.current?.play();
  await adVideoPlayer.current?.deinitialize();
  adVideoPlayer.current = null;
};

Clean up resources

When your component unmounts or the player session ends, deinitialize both players and release the surface handle.

Copied to clipboard.


const cleanup = async () => {
  if (adVideoPlayer.current) {
    await adVideoPlayer.current.deinitialize();
    adVideoPlayer.current = null;
  }
  // Main player cleanup handled by your existing teardown logic
};


Last updated: Mar 13, 2026