Skip to main content

Web Chromeless BO Adapter 5.8

Legacy documentation

This page contains deprecated documentation and is no longer actively maintained. A new version of this documentation is now available here.

This guide explains how to integrate DIVA Chromeless with DIVA BO using DIVA BoAdapter into your web / webTV application. application.

Requirements​

Refer to DIVA Web Chromeless SDK documentation.

SDK Setup​

  1. Add @deltatre-vxp:registry=https://npm.pkg.github.com to your .npmrc file
  2. Install the SDK
       npm install @deltatre-vxp/diva-sdk

Initialization​

Diva BO Adapter gives programmatic access to the standard providers and to common plugins used by the DIVA player SDK when connected to DIVA BO.

import React, { useEffect, useState } from "react";

// bo adapter sdk
import { DivaChromelessBoAdapter } from "@deltatre-vxp/diva-sdk/diva-web-chromeless-bo-adapter";

// bo settings link
const SETTINGS_URL = "https://example.com/settings.json";

// id of the video to be runned
const VIDEO_ID = "123456789890";

const isWebTV = false;

const muted = false;
const volume = 1;

const config = {
videoId:VIDEO_ID,
webTv: isWebTV,
libs: {
mux: 'https://cdnjs.cloudflare.com/ajax/libs/mux.js/6.2.0/mux.min.js',
shaka: 'https://cdnjs.cloudflare.com/ajax/libs/shaka-player/4.3.7/shaka-player.compiled.js',
hlsJs: 'https://cdn.jsdelivr.net/npm/hls.js@1.5.7',
googleIMA: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
googleDAI: 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js',
googleCast: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1',
threeJs: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.148.0/three.min.js',
}
};

const entitlementConfiguration = {
entitlementUser: () => 'token',
entitlementPayloadMap: (type, payload) => {
// Modify the payload
return payload;
},
version: "1",
};

const mediaAnalyticsParam = {
viewerId: 'DivaWebUser',
userName: 'DivaWebUser',
playerVersion: '5.8.0',
cdnName: 'AKAMAI',
playerType: 'HTML5',
omLibs: {
omWeb: 'omweb-v1.js',
omSessionClient: 'omid-session-client-v1.js',
},
setPALNonce: (nonceRequest: NonceRequest) => {
nonceRequest.sessionId = 'xyz'
return Promise.resolve(nonceRequest);
},
};

export const App = () => (
<DivaChromelessBoAdapter
settingsUrl={SETTINGS_URL}
entitlementConfiguration={entitlementConfiguration}
mediaAnalyticsParam={mediaAnalyticsParam}
config={config}
muted={muted}
volume={volume}
/>
)

Properties​

PropertyTypeDefaultDescription
Mandatory
Property: settingsUrltype:
string
Default: NAurl to reach diva bo adapter settings for the specific project
Property: configtype:Default: NAinitialization data for DIVA BO adapter
Property: el (vanilla js/react embedded)type:
HTML div element reference
Default: NAHTML div element where diva should be started into
Optional
Property: mutedtype:
boolean
Default: falseif trues it starts the adapter muted
Property: volumetype:
number
Default: 1starting volume [0-1]
Property: adCovertype:
boolean
Default: trueit says if the advertisement should fit or fill the chromeless container. Default fill.
Property: videoCovertype:
boolean
Default: trueit says if the video should fit or fill the chromeless container. Default fill.
Property: mediaAnalyticsParamtype:Default: undefinedproperties useful to implement media analytics
Property: entitlementConfigurationtype:Default: undefinedproperties useful to implement entitlement
Middleware
Property: videoMetadataMaptype:
(videoMetadata: VideoMetadata) => Promise<VideoMetadata>
Default: undefinedasynchronous middleware for the app to interact and modify the videoData as soon as videoData is returned from the request (passthrough if not defined)
Callbacks
Property: onDivaBoAdapterErrortype:
(e: unknown) => void
Default: undefinednotify errors on bo adapter start (React)

Typescript interfaces for Properties​

ChromelessBoAdapterWebComponentProps and ChromelessBoAdapterWebVanillaProps
interface ChromelessBoAdapterWebComponentProps {
/**
* url to reach diva bo adapter settings for the specific project
*/
settingsUrl: string;
/**
*
*/
onDivaBoAdapterError?: OnDivaBoAdapterError;

/**
* a middleware for the app to interact and modify the videoData as soon as videoData is returned from the request (passthrough if not defined)
*/
videoMetadataMap?: VideoMetadataMap;

/**
*properties useful to implement media analytics
*/
mediaAnalyticsParam?: MediaAnalyticsProps;

/**
*properties useful to implement entitlement
*/
entitlementConfiguration?: EntitlementConfiguration;

/**
* initialization config for DIVA BO adapter
*/
config: BoAdapterWebComponentConfig;

/**
* starting muted
*/
muted?: boolean;

/**
* starting volume [0-1]
*/
volume?: number;

/**
* it says if the advertisement should fit or fill the chromeless container. Default fill.
*/
adCover?: boolean;

/**
* it says if the video should fit or fill the chromeless container. Default fill.
*/
videoCover?: boolean;
}

interface ChromelessBoAdapterWebVanillaProps
extends Omit<ChromelessBoAdapterWebComponentProps, "onDivaBoAdapterError"> {
el: HTMLElement;
}

Config​

BO Adapter config are the same as those in the DIVA Chromeless SDK, excluding for videoMetadataProvider, dictionary, entitlementProvider, setting, fairplayCertificatePath properties, because they are provided by BO adapter.

PropertyTypeDefaultDescription
Mandatory
Property: videoIdtype:
string
Default: NAid of the video to play
Property: webTVtype:
boolean
Default: NAit specifies if the component is used ina webTV or not
Property: libstype:Default: NAlibraries required
Optional
Property: looptype:
boolean
Default: falseIf true automatic replay is executed when video reaches the end
Property: debugtype:
boolean
Default: falseIt enables debug panel in chromecast
Property: videoDebugtype:
boolean
Default: falseIt enables debug mode of the video libraries (hlsjs / shaka)
Property: detectAdBlocktype:
boolean
Default: falseIf true it raises an error if there's an AD and it's blocked by an ad blocker.
Property: googleImaDAITagParameterstype:
{ [key: string]: string }
Default: {}Additional tag params for google DAI. For example tfua: 1 (Tag For Users under the Age of Consent in Europe) and npa: 1
Property: preferredCCTrackNametype:
string
Default: undefinedCC track to start with (if present)
Property: preferredAudioTrackNametype:
string
Default: undefinedAudio track to start with (if present)
Property: deepLinkTypetype:
DeepLinkType
Default: NAtype of the deep link
Property: deepLinkValuetype:
string
Default: undefinedvalue of the deep link in milliseconds
Property: hdrActivetype:
boolean
Default: falseif HDR is enabled or not
Property: maxBitrateKbpstype:
number
Default: -1max bitrate in Kbps
Property: minBitrateKbpstype:
number
Default: -1min bitrate in Kbps
Property: startingBitrateKbpstype:
number
Default: -1starting bitrate in Kbps
Property: useLastBitratetype:
boolean
Default: falseif true it makes DIVA using last bitrate from the previous session
Property: capLevelToPlayerSizetype:
boolean
Default: falseif true it adjusts bitrate depending video size
Property: hlsJsConfigOverridestype:
any
Default: undefined--
Property: shakaConfigOverridestype:
any
Default: undefined--
Property: useCredentialtype:
boolean
Default: falseUsed by hls.js for xhrSetup.
Property: widevineOverridestype:
{ requestParams: Record<string, any>}
Default: {}Overrides for widevine DRM
Property: fairplayCertificatePathtype:
string
Default: NAPath of the fairplay certificate
Property: fairplayOverridestype:
{
   requestQueryParams?: Record<string, string>;
   requestHeaders?: Record<string, string>;
   skipLicenseRequestParsing?: boolean;
}
Default: {}Overrides for fairplay DRM: headers, query params, license request parsing
Property: parameterstype:
[key: string]: string
Default: undefinedMap of additional keys to add to the path resolver. Input keys will be saved inside resolver as "settings.<key>"
Callbacks
Property: setAPItype:
(apiRef: DivaAPI) =>  void
Default: undefinedprovide as soon as possible an imperative api to interact with the player
Property: onVideoMetadataChangestype:
(videoMetadata: VideoMetadataClean) => void
Default: undefinedCalled when videometadata of the main video changes
Property: onVideoErrortype:
(error: DivaError, videoMetadata: VideoMetadataClean) => void
Default: undefinedCalled on DIVA errors
Property: onEventtype:
(event: { type: 'BACK_PRESS_OUTSIDE' }) => boolean | Promise<boolean>
Default: undefinedactually used only for cases when the user is leaving the player with BACK_PRESS_OUTSIDE
Property: onAnalyticEventtype:
(event: GenericEvent)  =>  void
Default: undefinednotify analytics events
Property: onMediaAnalyticEventtype:
(event: MediaEvent)  =>  void
Default: undefinednotify media analytics events
Property: onPlayerPositiontype:
(position: { relativePosition: number; absolutePosition: Date }) => void
Default: undefinednotify as frequent as possible the position reached by the player in the playing video
Property: onPlayerMaxPositiontype:
(position: { relativePosition: number; absolutePosition: Date }) => void
Default: undefinedCalled when player max position (both relative to the video logical start and unix timecode) of the main video changes
Property: onPlaybackRatetype:
(rate: number) => void
Default: undefinedCalled when playback speed of the main video changes
Property: onPlayerStatetype:
(state: PlayerState) => void;
Default: undefinedCalled when player state of the main video changes. PlayerState = 'buffering' | 'end' | 'error' | 'pause' | 'play' | 'unstart';
Property: onVolumetype:
(value: number) => void;
Default: undefinedCalled when player volume changes
Property: onVideoEndtype:
()=>void
Default: undefinednotify when the playing video reaches the end
Property: onPlayerActionRequesttype:
(value: DivaAction) => void;
Default: undefinedCallback for actions called by API: play, pause, seek, seekBack, seekFroward, seekPercentage, seekAbsolute

Typescript interfaces for Config​

BoAdapterWebComponentConfig
interface DivaWebChromelessConfiguration {
// WEB TV
// ========================================================================
videoId: string;

// WEB TV
// ========================================================================
webTv: boolean;

// DEBUG
// ========================================================================
debug?: boolean;
videoDebug?: boolean;

// AD
// ========================================================================
detectAdBlock?: boolean;
/**
* Additional tag params for google DAI
* For example tfua: 1 (Tag For Users under the Age of Consent in Europe) and npa: 1
*/
googleImaDAITagParameters?: unknown;

// LAZY LOADED LIBS
// ========================================================================
libs: Libs;

// AUDIO AND CC
// ========================================================================
preferredAudioTrackName?: string;
preferredCCTrackName?: string;

// DEEP LINK
// ========================================================================
deepLinkType?: DeepLinkType;
deepLinkValue?: number | string;

// HDR
// ========================================================================
hdrActive?: boolean;

// BITRATE LIMITATIONS
// ========================================================================
maxBitrateKbps?: number;
minBitrateKbps?: number;
startingBitrateKbps?: number;
maxVideoWidth?: number;
useLastBitrate?: boolean;
capLevelToPlayerSize?: boolean;

// SETTING AND PROVIDERS
// ========================================================================
setting: Setting;
videoMetadataProvider: VideoMetadataProvider;
entitlementProvider?: EntitlementProvider;

// MEDIA PLAYER CONFIGS
// ========================================================================
// eslint-disable-next-line @typescript-eslint/no-explicit-any
hlsJsConfigOverrides?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
shakaConfigOverrides?: any;
useCredential?: boolean;
widevineOverrides?: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
requestParams: any;
};
fairplayCertificatePath?: string;
fairplayOverrides?: {
requestQueryParams?: Record<string, string>;
requestHeaders?: Record<string, string>;
skipLicenseRequestParsing?: boolean;
};
unfreezeShakaAtMediaQualityChanges?: boolean;



loop?: boolean;

// CALLBACKS
// ========================================================================

/**
* It exposes DIVA APIs
*/
setAPI?: (apiRef: DivaWebChromelessAPI) => void;

/**
* Logs callback
*/
// onLog?: (log: LogEntry) => void;

/**
* VideoMetadataChanges callback
*/
onVideoMetadataChanges?: (videoMetadata: VideoMetadataClean) => void;

/**
* Callback for generic analytic events
*/
onAnalyticEvent?: (event: GenericEvent) => void;

/**
* Callback for media analytic events
*/
onMediaAnalyticEvent?: (event: MediaEvent) => void;

/**
* Called when playback speed of the video changes
*/
onPlaybackRate?: (rate: number) => void;

/**
* Callback for actions called by API: play, pause, seek, seekBack, seekFroward, seekPercentage, seekAbsolute
*/
onPlayerActionRequest?: (value: DivaAction) => void;

/**
* Called when player position (both relative to the video logical start and unix timeCode) of the video changes
*/
onPlayerPosition?: (position: { relativePosition: number; absolutePosition: Date }) => void;

/**
* Called when player max position (both relative to the video logical start and unix timeCode) of the video changes
*/
onPlayerMaxPosition?: (position: { relativePosition: number; absolutePosition: Date }) => void;

/**
* Called when player state of the video changes
*/
onPlayerState?: (state: PlayerState) => void;

/**
* Called in case of errors
*/
onError?: (error: DivaError, videoMetadata: VideoMetadataClean | undefined) => void;

/**
* Called when video end is reached
*/
onVideoEnd?: () => void;

/**
* Called in case of volume changes
*/
onVolume?: (volume: number) => void;
}


type BoAdapterWebComponentConfig = Omit<
DivaWebChromelessConfiguration,
'videoMetadataProvider' | 'dictionary' | 'entitlementProvider' | 'setting' | 'fairplayCertificatePath'
>;

Entitlement​

PropertyTypeDefaultDescription
Optional
Property: entitlementPlatformtype:
string
Default: ""platform parameter used to request entitlement token
Property: otherParameterstype:
Record<string, string>
Default: ""other parameters used to request entitlement token
Property: entitlementPlayerTypetype:
string
Default: ""player type parameter used to request entitlement token
Property: versiontype:
string
Default: undefinedEntitlement service version. If the version is set, `Data` will be included in the request body
Middlewares
Property: entitlementUsertype:
(data) => string
Default: undefineda middleware to provide user token when requested
Property: entitlementPayloadMaptype:
(type: 'token' | 'heartbeat', payload: any) => Promise<any>
Default: undefineda middleware to modify the payload before sending it to the entitlement service

Typescript interfaces for Entitlement configuration​

BoEntitlementConfiguration
interface BoEntitlementConfiguration {
/**
* platform parameter used to request entitlement token
*/

entitlementPlatform?: string;
/**
*
*/
otherParameters?: Record<string, string>;

/**
* function that returns the user token
*/
entitlementUser?: () => string;

/**
* default to "HTML5", used in the entitlement "PlayerType" request parameter
*/
entitlementPlayerType?: string;

/**
* Entitlement service version. If the version is set, `Data` will be included in the request body
*/
version?: string;

/**
* Function type definition that can be used to modify the payload of an entitlement at runtime.
*
* @param {('token' | 'heartbeat')} entitlementType - The type of the entitlement.
* @param {any} payload - The original payload of the entitlement.
*
* @returns {Promise<any>} The Promise object represents the modified payload of the entitlement.
*/
entitlementPayloadMap: (
entitlementType: "token" | "heartbeat",
payload: any
) => Promise<any>;
}

Media Analytics​

PropertyTypeDefaultDescription
Optional
Property: viewerIdtype:
string
Default: ""viewer id passed down to media analytics platforms
Property: userNametype:
string
Default: ""user name passed down to media analytics platforms
Property: playerVersiontype:
string
Default: ""player version parameter passed down to media analytics platforms
Property: playerTypetype:
string
Default: ""player type parameter passed down to media analytics platforms
Property: cdnNametype:
string
Default: ""cdn name parameter passed down to media analytics platforms
Property: omLibstype:
object
Default: undefinedIt's an object of type:
{omWeb: string; omSessionClient: string;}.
It contains the libs urls for OpenMeasurement hosted by project.
It's mandatory to make OM work.
Download libs files
Callbacks
Property: mediaAnalyticsEventHandlertype:
(event: MediaEvent)  =>  void
Default: undefinedadditional callback for notifying media analytics events
Middlewares
Property: customTagtype:
(videoMetadata: VideoMetadataClean)  => Record<string, string>
Default: undefinedcustom tag generator
Property: customDimensionstype:
(videoMetadata: VideoMetadataClean) => string[]
Default: undefinedcustom dimensions generator
Property: customDeviceMetadatatype:Default: undefinedcustom device metadata generator for Conviva
Property: setPALNoncetype:
(nonceRequest: NonceRequest) => Promise<NonceRequest>
Default: undefineda middleware to modify the NonceRequest before requesting it to PAL.

Typescript interfaces for Media Analytics Configuration​

MediaAnalyticsProps
export interface MediaAnalyticsProps {
/**
* custom tag generator
*/
customTag?: CustomTagGenerator;

/**
* custom dimensions
*/
customDimensions?: CustomDimensionsGenerator;

/**
* custom device metadata generator for Conviva
*/
customDeviceMetadata?: CustomDeviceMetadataGenerator;

/**
* additional callback for media analytics events.
*/
mediaAnalyticsEventHandler?: OnMediaAnalyticsEventHandler;

/**
* viewer id passed down to media analytics platforms
*/
viewerId?: string;

/**
* user name passed down to media analytics platforms
*/
userName?: string;

/**
* player version passed down to media analytics platforms
*/
playerVersion?: string;

/**
* player type parameter passed down to media analytics platforms
*/
playerType?: string;

/**
* cdn name parameter passed down to media analytics platforms
*/
cdnName?: string;

/**
* urls for OpenMeasurement libs hosted by project
*/
omLibs?: {
omWeb: string;
omSessionClient: string;
};

/**
* Function add properties to the PAL NonceRequest object
*/
setPALNonce?: (nonceRequest: NonceRequest) => Promise<NonceRequest>;
}

DivaAPI​

Imperative API to interact with the player.

Typescript interfaces for DIVA API​

DIVA API

/**
* It will force DIVA to request a new VideoMetadata through videoMetadataProvider
*/
requestVideoMetadataUpdate: () => void;

// Getters

/**
* It returns the player position (both relative to the video logical start and unix timeCode as Date) of the video.
*/
getPlayerPosition: (videoId?: string) => { relative: number; absolute: Date };

/**
* It returns the player duration (both relative to the video logical duration and absolute end point as a Date) of the video.
*/
getPlayerDuration: (videoId?: string) => { relative: number; absolute: Date };

/**
* It returns the current video playback rate.
*/
getPlaybackRate: () => number;

/**
* It returns the current video state. Possible value: 'buffering', 'end', 'error', 'pause', 'play', 'unstart'.
*/
getPlayerState: () => PlayerState;

/**
* It returns the current video volume. Values could be from 0 to 1.
*/
getVolume: () => number;

/**
* It returns the Diva version in this format: 'major.minor.patch'.
*/
getVersion: () => string;

// Actions

/**
* It mute/unmute the video.
* @param value boolean, true to mute, false to unmute.
*/
mute: (value: boolean) => void;

/**
* It pauses video playback.
* @param interactive boolean, for analytics track, true if with user interaction.
*/
pause: (interactive?: boolean) => void;

/**
* It starts the video playback.
* @param interactive boolean, for analytics track, true if with user interaction.
* @returns the videoElement play promise.
*/
play: (interactive?: boolean) => Promise<void>;

/**
* It seeks the video playback.
* @param value number, milliseconds value relative to the video start time.
* @param interactive boolean, for analytics track, true if with user interaction.
* @returns A promise usefull to check when the action is done.
*/
seek: (value: number, interactive?: boolean) => Promise<void>;

/**
* It seeks back the video playback by the value get from videoMetadata.behaviour.seekInterval. Default 10 seconds.
* @param interactive boolean, for analytics track, true if with user interaction.
* @returns A promise usefull to check when the action is done.
*/
skipBack: (interactive?: boolean) => Promise<void>;

/**
* It seeks forward the video playback by the value get from videoMetadata.behaviour.seekInterval. Default 10 seconds.
* @param interactive boolean, for analytics track, true if with user interaction.
* @returns A promise usefull to check when the action is done.
*/
skipForward: (interactive?: boolean) => Promise<void>;

/**
* It seeks the video playback by percentage.
* @param value number, percentage from 0 to 100.
* @param interactive boolean, for analytics track, true if with user interaction.
* @returns A promise usefull to check when the action is done.
*/
seekPercentage: (value: number, interactive?: boolean) => Promise<void>;

/**
* It seeks the video playback by Date object.
* @param value Date, in ISO 8601 format. (YYYY-MM-DDThh:mm:ssZ)
* @param interactive boolean, for analytics track, true if with user interaction.
* @returns A promise usefull to check when the action is done.
*/
seekAbsolute: (value: Date, interactive?: boolean) => Promise<void>;

/**
* It sets the rate at which the video is being played back.
* @param value number, a value of 1 indicates normal speed.
*/
setPlaybackRate: (value: number) => void;

/**
* It sets the video volume.
* @param value number, from 0 to 1, where 0 is effectively muted and 1 is the loudest possible value.
*/
setVolume: (value: number) => void;

/**
* Fires an event of the specified type with an optional payload.
* Used for Ad beaconing.
* @param type - The type of the event.
* @param payload - The payload associated with the event.
*/
fireEvent: (type: AnalyticsMediaEventType, payload?: { ad: Ad }) => void;

// Exposed path resolver
resolve(
value: string,
options?: {
; // if not provided it will fallback to main item
data?: Record<string, string>;
dontApplyDefault?: boolean;
}
): string;

Single command entry point for: mute, pause, play, set playback rate, seek, seek absolute

sendPlayerCommand: (command: DivaCommand, interactive: boolean) => void | Promise<void>;

// DIVA Commands interfaces
export enum DivaCommandName {
MUTE = 'mute',
PAUSE = 'pause',
PLAY = 'play',
PLAYBACK_RATE = 'playback-rate',
SEEK = 'seek',
SEEK_ABSOLUTE = 'seek-absolute',
}

interface DivaCommandBase {
;
command: DivaCommandName;
}

export interface DivaCommandMute extends DivaCommandBase {
command: DivaCommandName.MUTE;
value: boolean;
}

export interface DivaCommandPause extends DivaCommandBase {
command: DivaCommandName.PAUSE;
}

export interface DivaCommandPlay extends DivaCommandBase {
command: DivaCommandName.PLAY;
}

export interface DivaCommandPlaybackRate extends DivaCommandBase {
command: DivaCommandName.PLAYBACK_RATE;
value: number;
}

export interface DivaCommandSeek extends DivaCommandBase {
command: DivaCommandName.SEEK;
value: number; // Milliseconds relative to trim in
}

export interface DivaCommandSeekAbsolute extends DivaCommandBase {
command: DivaCommandName.SEEK_ABSOLUTE;
value: Date;
}

export type DivaCommand =
| DivaCommandMute
| DivaCommandPause
| DivaCommandPlay
| DivaCommandPlaybackRate
| DivaCommandSeek
| DivaCommandSeekAbsolute;

Libs​

Object containing the external libraries' url lazy loaded only when needed by DIVA Web SDK.

The following block of code is an example of value pointing to public CDNs.

{
// video libraries
hlsJs: 'https://cdn.jsdelivr.net/npm/hls.js@1.5.7',
shaka: 'https://ajax.googleapis.com/ajax/libs/shaka-player/4.7.11/shaka-player.compiled.js',
mux: 'https://cdnjs.cloudflare.com/ajax/libs/mux.js/6.2.0/mux.min.js',

// Advertisement
googleIMA: 'https://imasdk.googleapis.com/js/sdkloader/ima3.js',
googleDAI: 'https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js',

// Chromecast
googleCast: 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1',

// Used for 360 videos
threeJs: 'https://cdnjs.cloudflare.com/ajax/libs/three.js/0.148.0/three.min.js',
}