# 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 ("