Using Shaka Player
Quickstart
Add your HTML
Shaka player works by transforming a regular video tag into an HLS player, (widely supported by browsers)[https://caniuse.com/stream].
There are three important parts of this code below:
Caution
TODO: For videos we should give the recommended aspect ratio to make embedding possible without a flash of content
- The aspect ratio within the style tag. This tells the browser what size the video should be.
- The links. The
posteris your thumbnail and thedata-srcis your video link - The video controls like
controlsorplaysinline. Take a look at the video player cheat sheet for more on these.
<div class="shaka-player" style="width:100%; position:relative; aspect-ratio:16/9; background:#000;"> <video poster="https://worker.hesedvid.com/v1/thumbnail/org_01KAYN8RMNAEF0N243CYJCM9HR/env_A3TTAVN02AQHJTBLP7UTQ3V56ZYLNZ4/vid_K7VDWQKBCE06N0AK1O0LWDT2FQSS9A.png?width=1920&timeStamp=30" data-src="https://worker.hesedvid.com/v1/edge_EVNENCJS37003VO58NNFZQTMWG7S66YA9TUY78/master.m3u8" controls playsinline style="position:absolute; inset:0; width:100%; height:100%;" ></video></div>Add your javascript
Shaka player relies on Javascript to work. Below is the minimal javascript/typescript code to use to get started.
import shaka from 'shaka-player/dist/shaka-player.compiled.js';
// Because HLS streaming isn't natively supported by some browsers,// shaka starts with a polyfillshaka.polyfill.installAll();
// Transparent error handling for very very old browsersif (shaka.Player.isBrowserSupported()) { // There can be multiple shaka player instances on a page, // so we loop through them document.querySelectorAll('.shaka-player video[data-src]').forEach(async (video: HTMLVideoElement) => { // create and configure the player const player = new shaka.Player(); // Full docs here: https://shaka-player-demo.appspot.com/docs/api/tutorial-config.html player.configure({ streaming: { // After seeking, how many seconds should be // buffered before playing again? rebufferingGoal: 0.1, // How many seconds into the future // should be buffered? bufferingGoal: 15, // How many seconds of previous video // should be kept bufferBehind: 10, // how much buffer to leave in the past }, }); try { await player.attach(video); await player.load(video.dataset.src as string); } catch (e) { console.error('Error loading video', e); } });} else {console.error('Browser does not support Shaka Player');}Demo Video
Here’s what Shaka Player looks like based on the above code
Client-Side Ad Insertion (CSAI)
Shaka Player supports Client-Side Ad Insertion (CSAI) using the Google IMA SDK. The recommended approach is to use VMAP (Video Multi-Ad Playlist) tags, which define the complete ad schedule in a single URL.
Why VMAP?
A VMAP tag acts like a playlist for ads. It tells the player exactly when to play ads:
- Pre-roll: Before the content starts
- Mid-roll: At specific timestamps during playback
- Post-roll: After the content ends
Shaka + IMA handle all the pausing, ad playback, and UI overlay (like “Skip Ad” buttons) automatically. This is far more reliable than manually pausing the video and swapping sources with JavaScript timers.
Demo
This demo uses a Google sample VMAP tag configured with a pre-roll, mid-roll, and post-roll:
Requirements
To add ads to Shaka Player, you need:
- Shaka Player UI build - The UI version (
shaka-player.ui.js), not the compiled version - Google IMA SDK - Loaded before your player code
- A VMAP/VAST tag URL - From your ad server (e.g., Google Ad Manager)
Step 1: Add the Scripts
<!-- Google IMA SDK (must be loaded first) --><script src="//imasdk.googleapis.com/js/sdkloader/ima3.js"></script>
<!-- Shaka Player UI build --><script src="https://cdnjs.cloudflare.com/ajax/libs/shaka-player/4.3.0/shaka-player.ui.min.js"></script><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/shaka-player/4.3.0/controls.min.css">Or with npm:
import shaka from 'shaka-player/dist/shaka-player.ui';import 'shaka-player/dist/controls.css';Caution
You must use the UI build (shaka-player.ui.js) for ads. The compiled build (shaka-player.compiled.js) does not include the ad manager.
Step 2: Set Up the HTML
The UI overlay needs a container div wrapping the video:
<div id="video-container" style="width:100%; max-width:800px; position:relative;"> <video id="video" style="width:100%; height:100%;"></video></div>Step 3: Initialize the Player with Ads
const video = document.getElementById('video');const container = document.getElementById('video-container');
// Create player and UI overlayconst player = new shaka.Player();const ui = new shaka.ui.Overlay(player, container, video);
await player.attach(video);
// Get the ad managerconst adManager = player.getAdManager();
// Initialize client-side ads// Use the container so ads render on top of the videoadManager.initClientSide(container, video);
// Create the ad request with your VMAP tagconst adsRequest = new google.ima.AdsRequest();adsRequest.adTagUrl = 'https://your-ad-server.com/vmap-tag';adsRequest.linearAdSlotWidth = video.clientWidth;adsRequest.linearAdSlotHeight = video.clientHeight;
// Request ads - Shaka parses the VMAP and schedules all ad breaksadManager.requestClientSideAds(adsRequest);
// Load your video contentawait player.load('https://your-video-url/master.m3u8');Waiting for User Interaction
If you don’t want ads to autoplay, wait for user interaction before requesting ads:
// Initialize the ad manageradManager.initClientSide(container, video);
// Load the video firstawait player.load('https://your-video-url/master.m3u8');
// Request ads only when user clicks playvideo.addEventListener('play', () => { const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = 'https://your-ad-server.com/vmap-tag'; adManager.requestClientSideAds(adsRequest);}, { once: true });Getting a VMAP Tag
Your ad server (like Google Ad Manager / DFP) generates VMAP URLs. The URL contains parameters that define:
- Which ads to play
- When to play them (pre-roll, mid-roll timestamps, post-roll)
- Targeting information
For testing, you can use Google’s sample tags:
- Pre-roll only:
https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator= - Pre + Mid + Post:
https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpost&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=
Listening for Ad Events
const adManager = player.getAdManager();
adManager.addEventListener('ad-started', () => { console.log('Ad started playing');});
adManager.addEventListener('ad-stopped', () => { console.log('Ad finished, content resuming');});
adManager.addEventListener('ad-error', (event) => { console.error('Ad error:', event);});