# PRESTOplay
> PRESTOplay is Castlabs' player SDK family for building streaming applications across Android, Apple (iOS/tvOS), web browsers, and React Native. These files cover PRESTOplay for Web. For the other SDKs, see https://players.castlabs.com/android/latest/docs/build/html/index.html (Android), https://players.castlabs.com/apple/latest/docs/index.html (Apple), and https://players.castlabs.com/react-native/1.4.1/docs/getting-started/setup (React Native).
## common-media-data
Common media data
*****************
Common Media Data standards for CDN cooperation: CMCD (CTA-5004,
player-to-server request metadata) and CMSD (CTA-5006,
server-to-player response metadata).
CMCD (Common Media Client Data)
===============================
See the CMCD specification (CTA-5004).
When CMCD is enabled, the player adds contextual playback metadata to
every media request, such as buffer level, selected bitrate, or recent
throughput. CDNs can use this metadata to prioritize requests,
prefetch the next segment, or diagnose delivery issues.
CMSD (Common Media Server Data)
===============================
See the CMSD specification (CTA-5006).
CMSD defines a standard way for media servers — origin servers and CDN
intermediaries — to return data with each media object response, such
as estimated throughput or the next object to fetch. The player
processes this data to improve delivery efficiency and the viewer's
quality of experience. Unlike CMCD, which travels from player to
server on requests, CMSD travels from server to player in HTTP
response headers.
Platform implementation guides
==============================
* PRESTOplay for web Common Media Data support
## glossary
Glossary
********
This page defines terms and abbreviations used throughout the
PRESTOplay documentation.
+----------------------------------------------------+----------------------------------------------------+
| Term | Definition |
|====================================================|====================================================|
| Advanced Encryption Standard (AES) | A symmetric encryption standard commonly used to |
| | encrypt content. |
+----------------------------------------------------+----------------------------------------------------+
| AES-128 content key | A symmetric key that encrypts and decrypts content |
| | using the AES algorithm with a 128-bit (16-byte) |
| | key length, in CBC or CTR mode. Treat the content |
| | key as the compound object "{ Key Value, ALGID }". |
+----------------------------------------------------+----------------------------------------------------+
| CBC mode | An AES encryption mode. Cipher block chaining |
| | (CBC) mode turns a block cipher into a stream |
| | cipher. |
+----------------------------------------------------+----------------------------------------------------+
| CBCS | An encryption mode of the Common Encryption |
| | standard. Uses AES CBC mode with pattern (partial) |
| | sample encryption — also called partial sample |
| | encryption. |
+----------------------------------------------------+----------------------------------------------------+
| CENC | An encryption mode of the Common Encryption |
| | standard. Uses AES CTR mode with full sample |
| | encryption — also called full sample encryption. |
+----------------------------------------------------+----------------------------------------------------+
| Certificate | A digitally signed binary document used to grant |
| | and revoke device and computer privileges to |
| | perform specific operations. |
+----------------------------------------------------+----------------------------------------------------+
| Certificate authority (CA) | An entity that issues digital certificates and |
| | provides trust in certificate chains. |
+----------------------------------------------------+----------------------------------------------------+
| Challenge | A request from a client. A challenge contains |
| | information about the client, a list of requested |
| | rights, and other information about the content, |
| | including the content header and key identifier. |
+----------------------------------------------------+----------------------------------------------------+
| Clear content | A media file that isn't encrypted. |
+----------------------------------------------------+----------------------------------------------------+
| Client | A content receiver — a device or an application. |
+----------------------------------------------------+----------------------------------------------------+
| Common Encryption (CENC) | An MPEG standard that defines encryption and |
| | container formats for protected media content, |
| | specified in ISO/IEC 23001-7:2016. |
+----------------------------------------------------+----------------------------------------------------+
| Common Media Application Format (CMAF) | A multimedia format specified in ISO/IEC |
| | 23000-19:2018. |
+----------------------------------------------------+----------------------------------------------------+
| conditional access system (CAS) | A system that controls subscriber access to |
| | protected broadcast content. |
+----------------------------------------------------+----------------------------------------------------+
| content decryption module (CDM) | The client component that provides DRM |
| | functionality, including decryption. |
+----------------------------------------------------+----------------------------------------------------+
| Content ID (CID) | The unique identifier of the content to decrypt. |
+----------------------------------------------------+----------------------------------------------------+
| Content Key Context (CKC) | In FairPlay DRM, a message the Key Security Module |
| | (KSM) generates in reply to the server playback |
| | context (SPC) message the playback app sends it. |
| | The KSM responds to every SPC message with a |
| | corresponding CKC message, whose payload contains |
| | the content key the Apple device uses to decrypt |
| | the media for playback. |
+----------------------------------------------------+----------------------------------------------------+
| CTR mode | An AES encryption mode. Counter (CTR) mode turns a |
| | block cipher into a stream cipher. |
+----------------------------------------------------+----------------------------------------------------+
| Decrypt | To convert encrypted content back into its |
| | original form. |
+----------------------------------------------------+----------------------------------------------------+
| Device | A physical unit such as a PC, mobile phone, or |
| | set-top box. |
+----------------------------------------------------+----------------------------------------------------+
| digital rights management (DRM) | A technology that protects digital content by |
| | encrypting it with a cryptographic key. Authorized |
| | recipients must acquire a license to unlock and |
| | consume the content. FairPlay, PlayReady, and |
| | Widevine are examples of DRM systems. |
+----------------------------------------------------+----------------------------------------------------+
| elliptic curve cryptography (ECC) | A public-key cryptography approach based on the |
| | algebraic structure of elliptic curves. |
+----------------------------------------------------+----------------------------------------------------+
| Encrypt | To programmatically disguise content to hide its |
| | substance. |
+----------------------------------------------------+----------------------------------------------------+
| Encrypted Media Extensions (EME) | A W3C standard for HTML interfaces that let HTML5 |
| | applications perform DRM operations. |
+----------------------------------------------------+----------------------------------------------------+
| FairPlay Streaming (FPS) | A DRM technology developed by Apple, typically |
| | used with HLS streams. |
+----------------------------------------------------+----------------------------------------------------+
| HTTP Live Streaming (HLS) | An adaptive streaming protocol introduced by |
| | Apple. See HTTP Live Streaming on Apple Developer |
| | and RFC 8216. |
+----------------------------------------------------+----------------------------------------------------+
| Initialization vector (IV) | A block of bits that lets multiple instances of a |
| | stream or block cipher produce unique streams |
| | despite using the same encryption key. |
+----------------------------------------------------+----------------------------------------------------+
| Key | A piece of data required to unlock a packaged |
| | media file. The key is included in a separate |
| | license. |
+----------------------------------------------------+----------------------------------------------------+
| Key identifier (KID) | A value that identifies the key for a protected |
| | media file. |
+----------------------------------------------------+----------------------------------------------------+
| Key rotation | A technique that seamlessly changes the encryption |
| | keys of a stream at specific times. |
+----------------------------------------------------+----------------------------------------------------+
| Key Security Module (KSM) | Part of FairPlay Streaming (FPS) technology that |
| | resides in a content provider's key server. It |
| | interprets an encrypted key request message from |
| | an Apple device and creates an encrypted response |
| | containing the key for the specified media, acting |
| | as the liaison between the playback app and the |
| | Apple device: the app sends a server playback |
| | context (SPC) message, the Apple device's |
| | operating system parses it and generates a content |
| | key context (CKC), and the KSM encrypts and |
| | delivers the content key to the device. |
+----------------------------------------------------+----------------------------------------------------+
| License | Data attached to protected content that describes |
| | how the content can be used. A license is a data |
| | structure that contains, but isn't limited to, |
| | policies and an encrypted content key. |
+----------------------------------------------------+----------------------------------------------------+
| License acquisition | The process of obtaining a license to play a |
| | packaged media file. The client requests a license |
| | from a license acquisition URL specified in the |
| | packaged media file. |
+----------------------------------------------------+----------------------------------------------------+
| License server | The function in the service backend that issues |
| | licenses. |
+----------------------------------------------------+----------------------------------------------------+
| MPEG-DASH (Dynamic Adaptive Streaming over HTTP) | An adaptive streaming protocol that's an MPEG |
| | standard. See the MPEG-DASH specification. |
+----------------------------------------------------+----------------------------------------------------+
| Player | A client program or control that plays digital |
| | media content streamed from a server or played |
| | from local files. PRESTOplay is an example of a |
| | player. |
+----------------------------------------------------+----------------------------------------------------+
| PlayReady | A DRM technology developed by Microsoft. |
+----------------------------------------------------+----------------------------------------------------+
| Policy | The description in a license of the actions |
| | permitted, or the restrictions, on the content. |
+----------------------------------------------------+----------------------------------------------------+
| Private key | The secret half of a public/private key pair used |
| | in cryptography. Private keys typically sign a |
| | message that's verified with the corresponding |
| | public key, or decrypt a message encrypted with |
| | the corresponding public key. |
+----------------------------------------------------+----------------------------------------------------+
| Protected content | Video, movie, audio, music, ebook, or executable |
| | content that may be downloaded, streamed, or both. |
+----------------------------------------------------+----------------------------------------------------+
| PSSH box | Protection System Specific Header box. An object |
| | defined in the Common Encryption standard that |
| | carries DRM-specific information. |
+----------------------------------------------------+----------------------------------------------------+
| Public key | The non-secret half of a public/private key pair |
| | used in cryptography. Public keys typically |
| | encrypt sessions, files, and messages that are |
| | then decrypted with the corresponding private key, |
| | or verify a digital signature created with the |
| | corresponding private key. |
+----------------------------------------------------+----------------------------------------------------+
| Revocation | The process of identifying clients that have |
| | compromised security and preventing them from |
| | getting additional licenses to decrypt protected |
| | content. |
+----------------------------------------------------+----------------------------------------------------+
| Robustness | Rules that specify whether a device is |
| | sufficiently robust to resist attacks. |
+----------------------------------------------------+----------------------------------------------------+
| Software development kit (SDK) | A set of tools, libraries, and documentation for |
| | building applications on a platform. |
+----------------------------------------------------+----------------------------------------------------+
| Security level (SL) | A classification of how robust a device or |
| | component is against attacks. |
+----------------------------------------------------+----------------------------------------------------+
| SL2000 | PlayReady security level 2000. |
+----------------------------------------------------+----------------------------------------------------+
| SL3000 | PlayReady security level 3000. |
+----------------------------------------------------+----------------------------------------------------+
| Server Playback Context (SPC) | In FairPlay DRM, a message the playback app sends |
| | to the key server to initialize a key session. |
+----------------------------------------------------+----------------------------------------------------+
| Stream | Digital media delivered in a continuous flow |
| | across a network. |
+----------------------------------------------------+----------------------------------------------------+
| Widevine | A DRM technology developed by Google. |
+----------------------------------------------------+----------------------------------------------------+
## index
PRESTOplay documentation
************************
PRESTOplay SDK documentation. Covers the web (browser) SDK. Android,
Apple (iOS/tvOS), and React Native docs are hosted separately (links
below). Features: adaptive streaming (HLS, DASH), DRM, subtitles,
analytics, and offline playback.
Get started
===========
* PRESTOplay for Android — Android (Java/Kotlin, Gradle)
* PRESTOplay for Apple — iOS, iPadOS, and tvOS (Swift, Xcode)
* PRESTOplay for Web Apps — Browsers (JavaScript, NPM)
* PRESTOplay for React Native — React Native (TypeScript,
cross-platform)
Core concepts
=============
* Thumbnails — Thumbnail formats, signaling, and authoring patterns
* Common media data — CMCD and CMSD standards for CDN cooperation
* Glossary — Definitions of DRM and streaming terms used throughout
this documentation
Core concepts
^^^^^^^^^^^^^
* Thumbnails
* What thumbnails provide
* Stream-signaled thumbnails
* Side-loaded thumbnail formats
* Authoring recommendations
* Platform implementation guides
* Common media data
* CMCD (Common Media Client Data)
* CMSD (Common Media Server Data)
* Platform implementation guides
* Glossary
Platforms
^^^^^^^^^
* PRESTOplay for Android
* PRESTOplay for Apple
* PRESTOplay for Web Apps
* Getting started
* Components
* License
* Player basics
* Player configuration
* Player surface
* Audio player
* Events
* Errors
* DRM
* Tracks and languages
* Subtitles
* Thumbnails
* Common media data
* Low latency and fast zapping
* Playlist
* Chromecast
* AirPlay
* Safari
* Smart TV
* Plugins
* Advertising
* Analytics
* Migration guide
* Docs for LLM agents
* Changelog
* PRESTOplay for React Native
## llm-docs
Docs for LLM agents
*******************
Plain-text exports of the PRESTOplay for web documentation, for LLM
agents.
+-----------------------------------+-----------------------------------+-----------------------------------+
| Platform | Index | Full text |
|===================================|===================================|===================================|
| Web | llms.txt | llms-full.txt |
+-----------------------------------+-----------------------------------+-----------------------------------+
Both files follow the llms.txt specification.
The files don't cover PRESTOplay for Android, Apple, or React Native
yet.
## thumbnails
Thumbnails
**********
Common thumbnail reference across PRESTOplay SDKs. Covers formats,
DASH/HLS signaling, side-loaded tracks, and authoring recommendations.
What thumbnails provide
=======================
Thumbnails are time-indexed preview images that map a playback
position to an image or image region.
* In-player use case: seek-bar preview while scrubbing
* Data model: timestamp range plus image source
* Rendering model: full image (single frame) or cropped tile from a
sprite grid
Stream-signaled thumbnails
==========================
Dynamic Adaptive Streaming over HTTP (DASH)
-------------------------------------------
In DASH, thumbnails are usually signaled as an image "AdaptationSet"
with tiled sprites.
"thumbnail_tile" declares the grid layout. In this example, each
sprite contains 25 thumbnails (5 x 5).
HTTP Live Streaming (HLS)
-------------------------
In HLS, thumbnails are signaled from the multivariant playlist with
"EXT-X-IMAGE-STREAM-INF", which points to an image media playlist.
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=200,CODECS="avc1,mp4a",RESOLUTION=960x540
video.m3u8
#EXT-X-IMAGE-STREAM-INF:RESOLUTION=240x135,CODECS="jpeg",BANDWIDTH=100,URI="image.m3u8"
Image playlists can reference single images or tiled images.
Side-loaded thumbnail formats
=============================
When a stream does not carry thumbnail signaling, you can side-load
one of these formats.
Web Video Text Tracks (WebVTT) index
------------------------------------
WebVTT cues map time ranges to image URLs.
WEBVTT
00:00:00.000 --> 00:00:09.999
thumb1.jpg
00:00:10.000 --> 00:00:19.999
thumb2.jpg
Grid coordinates can be appended to each cue target.
WEBVTT
00:00:00.000 --> 00:00:09.999
thumbs.jpg#xywh=0,0,320,180
00:00:10.000 --> 00:00:19.999
thumbs.jpg#xywh=320,0,320,180
Template-based images (single or grid)
--------------------------------------
Template URLs use an index token such as "$index$" and optional grid
metadata.
* Single-image mode: one image per index
* Grid mode: one image contains multiple thumbnails, addressed by grid
position
Binary Image Format (BIF)
-------------------------
Some SDKs support Binary Image Format (BIF) as a compact, indexed
thumbnail container.
Authoring recommendations
=========================
* Keep thumbnail interval consistent (for example, every 5 or 10
seconds)
* Prefer sprite grids when you need to reduce request count
* Keep grid dimensions practical for target devices
* Validate that cue timelines cover the intended seek range
* Use absolute URLs or preserve relative paths when packaging local
WebVTT files
Platform implementation guides
==============================
* PRESTOplay for Android documentation
* PRESTOplay for Apple documentation
* PRESTOplay for web thumbnail integration
* PRESTOplay for React Native documentation
## web/advertising
Advertising
***********
PRESTOplay web SDK advertising support. Covers the built-in ads API
and plugins for Google Interactive Media Ads (IMA), Yospace,
FreeWheel, and HLS interstitials.
PRESTOplay includes integrations for Google Interactive Media Ads
(IMA), Yospace, and FreeWheel AdManager, plus support for HLS
interstitials.
Ads API
=======
Ads manager
-----------
Call "getAdsManager()" on a "Player" instance to access "IAdsManager".
Call this method after the "open()" promise resolves. From that point,
you can control the currently playing ad.
Ad events
---------
When ads are active, the player emits ad-related events. Attach ad
event listeners to the player instance:
player.on(clpp.events.ADS_TIMELINE_CHANGED, event => {
console.log('==> ad-timeline-changed', event.adsTimeline.getCuePoints());
});
player.on(clpp.events.AD_LOADED, event => {
console.log('==> ad-loaded', event.ad);
});
Useful ad events include:
* "clpp.events.ADS_TIMELINE_CHANGED"
* "clpp.events.AD_LOADED"
* "clpp.events.AD_BREAK_STARTED"
* "clpp.events.AD_STARTED"
* "clpp.events.AD_BUFFERING"
* "clpp.events.AD_PROGRESS"
* "clpp.events.AD_FIRST_QUARTILE"
* "clpp.events.AD_MIDPOINT"
* "clpp.events.AD_THIRD_QUARTILE"
* "clpp.events.AD_PAUSED"
* "clpp.events.AD_RESUMED"
* "clpp.events.AD_SKIPPED"
* "clpp.events.AD_CLICKED"
* "clpp.events.AD_IMPRESSION"
* "clpp.events.AD_COMPLETED"
* "clpp.events.AD_STOPPED"
* "clpp.events.AD_BREAK_STOPPED"
See Events for general event-handling patterns.
Google IMA plugin
=================
The SDK includes a Google Interactive Media Ads (IMA) plugin for
client-side ads.
To get started, add the IMA library and player styles, and import the
IMA plugin:
import "@castlabs/prestoplay/cl.ima";
Pass a Video Multiple Ad Playlist (VMAP) ad tag to the player:
player.open({
// ...
ima: {
adTagUrl: '//pubads.g.doubleclick.net/...'
}
});
Pass a Video Ad Serving Template (VAST) ad tag to the player:
player.open({
// ...
ima: {
adTagUrl: '//pubads.g.doubleclick.net/...',
isVast: true
}
});
See "ImaConfiguration" for all available configuration options.
The Google IMA sample
(https://github.com/castlabs/prestoplay-web-code-samples/blob/main/examples/advertising/ima.html)
plays pre-roll, mid-roll, and post-roll ads from a VMAP ad tag and
logs ad events, including the ad details available through "IAd", on
the page.
IMA SDK on smart TVs
--------------------
For smart TV-specific limitations, including skippable ads, see Smart
TV.
IMA SDK on iOS
--------------
The IMA plugin is supported on iOS in experimental mode, for the same
reasons as on smart TVs.
Custom UI controls give a better user experience than built-in video
controls on iOS.
See "ImaConfiguration" and its "disableCustomPlayback" option to
disable ads on iOS devices if you run into issues.
Yospace plugin
==============
To get started with Yospace, download the Yospace ad management SDK
from the Yospace developer site. The currently supported version is
3.9.0. Other similar versions may also work, but compatibility is not
guaranteed.
Import the Yospace SDK:
Import the Yospace plugin:
import { clpp } from "@castlabs/prestoplay";
import "@castlabs/prestoplay/cl.yospace";
Enable the Yospace plugin when calling "open()" with a Yospace Central
Session Manager (CSM) uniform resource identifier (URI). This
automatically starts a Yospace session. "source.type" must be
specified:
await player.open({
source: {
// Yospace CSM URI
url: 'https://csm...',
type: clpp.Type.HLS,
},
yospace: {
enabled: true,
streamType: clpp.yospace.StreamType.VOD
}
});
Set up listeners for Yospace-related events:
player.on(clpp.events.YOSPACE_SESSION_STARTED, (e) => {
// e.detail contains the YospaceAdManagement.Session object
});
player.on(clpp.events.YOSPACE_SESSION_ENDED, (e) => {
// e.detail contains the YospaceAdManagement.Session object
});
await player.open({
source: '',
});
Once the video starts playing, call "getSession()" on the plugin
instance to get the "YospaceAdManagement.Session":
const plugin = player.getPlugin(clpp.yospace.YospacePlugin.Id);
const session = plugin.getSession();
FreeWheel plugin (beta)
=======================
To configure the FreeWheel plugin:
Add the FreeWheel AdManager SDK and player styles, and import the
FreeWheel plugin:
import "@castlabs/prestoplay/cl.freewheel";
Add the FreeWheel customer data to the player configuration:
const playerConfig = {
// ...
freewheel: {
networkId: 42015,
serverUrl: '//demo.v.fwmrm.net/ad/g/1',
profileId: '42015:js_allinone_profile',
videoAssetId: 'js_allinone_demo_video',
pods: [
{ id: 'Preroll_1', position: 0, type: clpp.ads.PodType.PREROLL },
{ id: 'Midroll_1', position: 3, type: clpp.ads.PodType.MIDROLL },
{ id: 'Midroll_2', position: 30, type: clpp.ads.PodType.MIDROLL },
{ id: 'Postroll_1', position: 60, type: clpp.ads.PodType.POSTROLL }
]
}
};
See "FreeWheelConfiguration" for all available configuration options.
The whole code can look like this:
Broadpeak SSAI ads
==================
The Broadpeak plugin also supports server-side ad insertion (SSAI)
tracking. See Broadpeak SSAI ads on the Analytics page.
HLS interstitials
=================
Support for HLS interstitials is limited to modern browsers. To enable
this feature on Safari, set "preferNativeHlsOnSafari" to "false":
const player = new clpp.Player('video', {
streaming: {
preferNativeHlsOnSafari: false,
}
});
You can disable this feature entirely:
const player = new clpp.Player('video', {
ads: {
hls: {
enable: false,
},
},
});
See "HlsAdsConfiguration" for other configuration options.
Playback session ID
-------------------
To give decisioning servers useful context, you can enable playback
session identification:
const player = new clpp.Player('video', {
mse: {
sendPlaybackSessionIdHeader: true,
}
});
With this in place, the player sends the "X-Playback-Session-Id" HTTP
header with every HTTP request related to primary playback, and the
"_HLS_primary_id" query parameter containing the same value with every
interstitial request.
Note:
For this to work, your primary content server must allow the HTTP
header "X-Playback-Session-Id" in "Access-Control-Allow-Headers".
Rendering UI
============
To render UI related to ads, listen to ad events and use the event
payload ("IAd") to get information about the currently playing ad.
player.on(clpp.events.AD_STARTED, event => {
const position = event.ad.getPositionInSequence();
const count = event.ad.getSequenceLength();
adLabel = `Ad ${position} / ${count}`;
});
player.on(clpp.events.AD_BREAK_STOPPED, () => {
adLabel = null;
});
To render a play/pause button, listen to play and pause events as well
as ad paused, resumed, and started. In all these cases the return
value of "isPaused()" may change.
function renderPlayButton() {
if (player.isPaused()) {
playButton.textContent = 'Play';
} else {
playButton.textContent = 'Pause';
}
}
player.on('play', () => {
renderPlayButton();
});
player.on('pause', () => {
renderPlayButton();
});
player.on(clpp.events.AD_STARTED, (e) => {
renderPlayButton();
});
player.on(clpp.events.AD_PAUSED, () => {
renderPlayButton();
});
player.on(clpp.events.AD_RESUMED, () => {
renderPlayButton();
});
Seek UI during ads
------------------
Some ad formats do not allow seeking. Use "canSeek()" on the current
ad ("IAd#canSeek") to determine whether the seek bar and any other
seek or playback rate controls should be enabled.
function renderSeekBar(ad) {
const seekEnabled = ad ? ad.canSeek() : true;
seekBar.disabled = !seekEnabled;
playbackRateSelect.disabled = !seekEnabled;
// Hide or disable any other seek or playback rate controls accordingly.
}
player.on(clpp.events.AD_STARTED, event => {
// Check and possibly disable seeking when the ad starts.
renderSeekBar(event.ad);
});
player.on(clpp.events.AD_BREAK_STOPPED, () => {
// Re-enable seek when the ad break ends.
renderSeekBar(null);
});
Skippable ads
-------------
Use "getSkipTimeOffset()" to determine whether an ad is skippable. It
returns the number of seconds of playback before the ad can be
skipped, or "-1" if the ad is not skippable.
To skip the current ad, call "skip()" on the ads manager.
Here's an example of rendering a skip button in the UI:
let currentAd = null;
player.on(clpp.events.AD_STARTED, event => {
currentAd = event.ad;
renderSkipButton();
});
player.on(clpp.events.AD_PROGRESS, () => {
renderSkipButton();
});
player.on(clpp.events.AD_BREAK_STOPPED, () => {
currentAd = null;
skipButton.style.display = 'none';
});
function renderSkipButton() {
if (!currentAd) return;
const skipOffset = currentAd.getSkipTimeOffset();
if (skipOffset === -1) {
// Ad is not skippable.
skipButton.style.display = 'none';
return;
}
const remaining = skipOffset - currentAd.getPosition();
if (remaining <= 0) {
skipButton.textContent = 'Skip Ad';
skipButton.disabled = false;
} else {
skipButton.textContent = `Skip in ${Math.ceil(remaining)}s`;
skipButton.disabled = true;
}
skipButton.style.display = 'block';
}
skipButton.addEventListener('click', () => {
player.getAdsManager().skip();
});
## web/airplay
AirPlay
*******
AirPlay support for PRESTOplay web SDK. Streams HLS from Apple devices
to AirPlay receivers via "AirPlayPlugin".
See "AirPlayPlugin" for the full API.
Using the AirPlay plugin
========================
This section shows how to integrate AirPlay with a custom UI.
Import the PRESTOplay AirPlay plugin:
import "@castlabs/prestoplay/cl.airplay";
Add an AirPlay button to your page:
Show the button when AirPlay is available:
const button = document.getElementById("airplay");
player.on(clpp.events.AIRPLAY_STATUS_CHANGED, (event) => {
if (event.canCast) {
button.style.display = "block";
} else {
button.style.display = "none";
}
});
Open the AirPlay target picker when the button is clicked:
button.addEventListener('click', function () {
const plugin = player.getPlugin(clpp.airplay.AirPlayPlugin.Id);
plugin.showCastMenu();
});
Listen for these events to detect the start and end of an AirPlay
session:
player.on(clpp.events.AIRPLAY_CASTING_STARTED, () => {
// AirPlay casting session started
});
player.on(clpp.events.AIRPLAY_CASTING_ENDED, () => {
// AirPlay casting session ended
});
AirPlay with DRMtoday and upfront authorization
===============================================
If your streams are protected with DRMtoday using upfront
authorization tokens, each playback session requires a new token.
Casting to a device over AirPlay counts as a new session.
Use "setDrmCustomDataModifier" to generate a new token for each DRM
license request (each playback session):
player.setDrmCustomDataModifier(async customData => {
customData.authToken = await createToken();
});
## web/analytics
Analytics
*********
PRESTOplay web SDK analytics plugins: Conviva, NPAW (Youbora),
Broadpeak, and Mux Data. Each plugin is added via an SDK import and a
player configuration key.
PRESTOplay includes analytics plugins for Conviva, NPAW, Broadpeak,
and Mux Data.
Conviva analytics
=================
The Conviva Core SDK isn't published on the public NPM registry —
Conviva provides it directly to customers. Add it to your page with a
"
Note:
The Conviva plugin depends on the Conviva Core SDK, so the core SDK
must be added to the page before the plugin. The minimum supported
version for this integration is "4.0.3".
Import the PRESTOplay Conviva plugin:
import "@castlabs/prestoplay/cl.conviva";
Provide the Conviva configuration as part of the player configuration:
const playerConfig = {
...
conviva: {
customerKey: 'YOUR_CONVIVA_CUSTOMER_KEY',
serviceUrl: 'https://company.testonly.conviva.com',
viewerId: 'YOUR_USER_ID',
enableAdInsights: false
}
};
The Conviva sample
(https://github.com/castlabs/prestoplay-web-code-samples/blob/main/examples/analytics/conviva.html)
shows the complete setup, including the asset name reported through
"source.name".
NPAW analytics
==============
To get started with NPAW analytics, install the NPAW SDK and NPAW
adapters.
Note:
The legacy Youbora v6 SDK integration is still available. To use it
instead, configure the player with a "youbora" key instead of
"npaw". It uses a separate "YouboraConfiguration" — its options
aren't identical to "npaw"'s.
npm install npaw-plugin@7.3.21
npm install npaw-plugin-adapters@7.3.21
Alternatively, to install the ES5 version of the NPAW library, run:
npm install npaw-plugin-es5@7.3.21
npm install npaw-plugin-adapters-es5s@7.3.21
Import the PRESTOplay Youbora plugin and the NPAW SDK:
import {clpp} from "@castlabs/prestoplay";
import "@castlabs/prestoplay/cl.mse";
import "@castlabs/prestoplay/cl.dash";
import "@castlabs/prestoplay/cl.youbora";
import * as NpawPlugin from 'npaw-plugin';
import * as NpawPluginAdapters from 'npaw-plugin-adapters';
window.NpawPlugin = NpawPlugin;
window.NpawPluginAdapters = NpawPluginAdapters;
For custom NPAW configuration, see the example below. For full
details, see the NPAW documentation.
const playerConfig = {
...
npaw: {
accountCode: '',
// ... other NPAW options
}
};
You can also pass additional NPAW options per source, in the "npaw"
key of the "Player.open" configuration.
The NPAW sample
(https://github.com/castlabs/prestoplay-web-code-samples/blob/main/examples/analytics/npaw_v7.html)
shows the complete setup with the NPAW v7 SDK, a custom "errorFilter",
and buttons that trigger recoverable and fatal errors.
Custom error and events reporting
---------------------------------
To report custom errors or events as described in the NPAW
documentation, access the underlying NPAW adapter:
const adapter = player.getPlugin(clpp.npaw.NpawPlugin.Id)
.getAdapter();
// The adapter may be null if there is no active session.
if (adapter) {
adapter.fireError(code, message);
// Report an error and send a /stop event to stop the current session.
adapter.fireFatalError(code, message);
// Fire a custom event.
adapter.fireEvent('eventName', dimensions, values, topLevelDimensions);
}
NPAW App Analytics
------------------
To use NPAW App Analytics with PRESTOplay, pass your NPAW plugin
instance to PRESTOplay via "setNpawPlugin". For App Analytics
configuration details, see the NPAW documentation.
Import packages:
import {clpp} from "@castlabs/prestoplay";
import "@castlabs/prestoplay/cl.mse";
import "@castlabs/prestoplay/cl.dash";
import "@castlabs/prestoplay/cl.youbora";
import * as NpawPlugin from 'npaw-plugin';
import * as NpawPluginAdapters from 'npaw-plugin-adapters';
window.NpawPlugin = NpawPlugin;
window.NpawPluginAdapters = NpawPluginAdapters;
Use the NPAW plugin:
const player = new clpp.Player('video', {
license: '',
viewerId: '',
npaw: {
accountCode: ''
// ... other NPAW options
}
});
const appAnalyticsPlugin = new NpawPlugin('');
player.getPlugin(clpp.npaw.NpawPlugin.Id)
.setNpawPlugin(appAnalyticsPlugin);
// Now you can start playback.
player.open({
source: 'http://example.com/Manifest.mpd',
});
// Start session logging.
sessionsPlugin.appAnalytics.newSession();
// Fire a session custom tracking event.
sessionsPlugin.appAnalytics.fireEvent(
'search', // Name of the event
{ // Dimensions
terms: 'searchedTerms'
},
{ // Values
foundItems: 25
});
Custom error filter
-------------------
Use the "npaw.errorFilter" config option to prevent specific errors
from being reported to the NPAW service, or to modify an error's
"code", "message", "severity", or add extra "metadata".
const player = new clpp.Player('video', {
license: '',
npaw: {
accountCode: '',
errorFilter: error => {
// Prevent error 3003 from being reported by returning null.
if (error.code === 3003) {
return null;
}
return {
code: `${error.code}`,
message: error.message,
severity: error.severity,
// metadata: { ... }, // Must be a serializable object.
};
},
// ... other NPAW options
}
});
Broadpeak analytics
===================
Broadpeak SmartLib integrates with PRESTOplay via NPM and script tag.
See the Broadpeak project setup documentation for Broadpeak-specific
setup details.
Install with NPM
----------------
The minimum SmartLib version supported by this integration is
"5.4.4-808048b".
Add the Broadpeak NPM registry:
npm config set @broadpeak:registry https://delivery-platform.broadpeak.tv/js/
Install SmartLib:
npm install @broadpeak/smartlib@5.4.4-808048b
npm install @broadpeak/smartlib-analytics@5.4.4-808048b
For other installation methods, see the Broadpeak project setup
documentation. If your project needs a pre-transpiled bundle, use
"@broadpeak/smartlib-all-compatibility" instead.
Import the SmartLib files and the PRESTOplay Broadpeak plugin:
import { SmartLib } from '@broadpeak/smartlib';
import '@broadpeak/smartlib-analytics';
import { clpp } from '@castlabs/prestoplay';
import '@castlabs/prestoplay/cl.broadpeak';
window.SmartLib = SmartLib; // Required by the PRESTOplay Broadpeak plugin.
Configuration
-------------
Add the Broadpeak configuration to your player. Set
"broadpeakDomainNames" to a comma-separated list of the CDN domains
that serve content through Broadpeak:
const playerConfig = {
...
broadpeak: {
broadpeakDomainNames: 'cdn.broadpeak.example,cdn2.broadpeak.example',
},
};
Two special values are also accepted: "'*'" if every URL the player
loads is served through Broadpeak, or "''" if none are.
See "BroadpeakConfiguration" for all available configuration options.
Session options
~~~~~~~~~~~~~~~
Pass session options via "broadpeak.sessionOptions", using
"StreamingSessionOptions" constants as keys:
const playerConfig = {
...
broadpeak: {
broadpeakDomainNames: '',
sessionOptions: {
[StreamingSessionOptions.GDPR_PREFERENCE]:
StreamingSessionOptions.GDPR_CLEAR,
[StreamingSessionOptions.SESSION_KEEPALIVE_FREQUENCY]: 5000,
[StreamingSessionOptions.SESSION_PRECACHE]: false, // Defaults to false when omitted.
},
},
};
See the Broadpeak documentation on session options for more
information.
Broadpeak SSAI ads
------------------
The Broadpeak plugin integrates server-side ad insertion (SSAI)
tracking into PRESTOplay, automatically handling ad tracking and
emitting client-side events.
To enable this feature, extend your Broadpeak analytics installation
with the Broadpeak ads module:
npm install @broadpeak/smartlib-ad@5.4.4-808048b
Then enable ad tracking in the Broadpeak config with "adTracking:
true" and, optionally, pass "adParameters" to enable ad
personalization. See the Broadpeak documentation for details about
supported ad parameters.
player.open({
source: {
url: 'https://stream.broadpeak.io/...',
type: clpp.Type.DASH,
},
broadpeak: {
broadpeakDomainNames: '...',
analyticsAddress: '...',
adTracking: true,
adParameters: {
deviceType: 'desktop',
userId: 'user123',
contentGenre: 'sports',
// ... any additional targeting parameters
},
},
});
For ad click-through to work properly, the default HTML5 video
controls ("