Skip to main content

Web TV BO Adapter 5.7

This guide explains how to integrate DIVA with DIVA BO using DIVA BoAdapter into your Web based SmartTV application.

Requirements​

Our SDK is designed to use on modern SmartTV devices with support for backward compatibility, up to:

  • SmartTV
    • Tizen 2015 and up
    • WebOS 2.0 and up
  • Sky Boxes
    • Amidala
    • XiOne / Beethoven

The sdk requires DIVA sdk to run.

If using npm and a bundler, React and React DOM are peer dependecies so npm will try to use your versions, the other dependencies are downloaded. If it is not supposed to bundle diva and dependencies toghether a version with everything bundled is available in index.reactBundled.min.js

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 { DivaWebTvBoAdapter } from "@deltatre-vxp/diva-sdk/diva-webtv-bo-adapter";

// css needs to be takend from diva sdk
import "@deltatre-vxp/diva-sdk/diva-webtv-sdk/index.min.css";

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

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

const init = {
videoId:VIDEO_ID
}

const 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',
}

export const App = () => (
<DivaWebTvBoAdapter
settingsUrl={SETTINGS_URL}
languageCode={"en-US"}
init={init}
libs={libs}
/>
)

Properties​

PropertyTypeDefaultDescription
Mandatory
Property: settingsUrltype:
string
Default: NAurl to reach diva bo adapter settings for the specific project
Property: languageCodetype:
string
Default: NApushengine language
Property: inittype:Default: NAinitialization data for DIVA BO adapter
Property: el (only vanilla js/react embedded)type:
HTML div element reference
Default: NAHTML div element where diva should be started into
Property: libstype:Default: NAlibraries required
Optional
Property: languageDictionarytype:
string
Default: NAdictionary language, defaults to `languageCode`
Property: mediaAnalyticsParamtype:Default: undefinedproperties useful to implement media analytics
Property: entitlementConfigurationtype:Default: undefinedproperties useful to implement entitlement
Property: accessibilitytype:Default: undefinedaccessibility options
Property: navigationActivetype:
boolean (reactive on React)
Default: trueflag to enable or disable navigation inside the component
Property: keyboardActivetype:
boolean (reactive on React)
Default: trueflag to enable/disable keyboard navigation support
Property: remoteActivetype:
boolean (reactive on React)
Default: trueflag to enable/disable navigation through remote
Property: gamepadActivetype:
boolean (reactive on React)
Default: trueflag to enable/disable gamepad navigation support
Property: noTransitionstype:
boolean
Default: falseflag to disable css transitions
Property: noControlsGradientBackgroundtype:
boolean
Default: falseflag to disable css gradient backgrounds
Property: unfreezeShakaAtMediaQualityChangestype:
boolean
Default: falseflag to toggle play pause in case of bitrate switches. Hack for sky xione and harmonic stream. It needs at least shaka 3.3.19
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)
Property: setAPItype:
(apiRef: DivaAPI) => void
Default: undefinedprovide as soon as possible an imperative api to interact with the player
Property: onVideoErrortype:
(error: VideoError, videoMetadata: VideoMetadata) => void
Default: undefinednotify about video playing 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: onAnalyticstype:
(event: GenericEvent) => void
Default: undefinednotify analytics events
Property: onMediaAnalyticstype:
(event: MediaEvent)  =>  void
Default: undefinednotify media analytics events
Property: onTtsMessagetype:
(data: TtsData)  =>  void
Default: undefinednotify text to be converted to speech fo accessibility
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: undefined Called 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
Property: onPreferredAudioTracktype:
(value: string) => void
Default: undefinednotify about changes in the audiotrack selected by the user
Property: onPreferredCCTracktype:
(value: string) => void
Default: undefinednotify about changes about cc selected by the user
Property: onVideoEndtype:
()=>void
Default: undefinednotify when the playing video reaches the end

Typescript interfaces for Properties​

BoAdapterWebTvProps and BoAdapterWebTvVanillaProps
interface BoAdapterWebTvNoComponentProps {
/**
* url to reach diva bo adapter settings for the specific project
*/
settingsUrl: string;
/**
* pushengine language
*/
languageCode: string;
/**
* dictionary language
*/
languageDictionary?: string;
/**
* notify errors on bo adapter start
*/
onDivaBoAdapterError?: OnDivaBoAdapterError;

/**
* initialization data for DIVA BO adapter
*/
init: BoAdapterWebTvNoComponentInitProps;

/**
* 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?: BoEntitlementConfiguration;

/**
* callback used to notify video errors during reproduction
*/
onVideoError?: OnVideoError;
/**
* flag to enable or disable navigation inside the component
*/
navigationActive?: boolean;
/**
* actually used only for cases when the user is leaving the player with `BACK_PRESS_OUTSIDE`
*/
onEvent?: OnEventType;
/**
* provide asynchronously an imperative api to interact with the player
*/
setAPI?: SetApi;
/**
* notify about changes in the audio-track selected by the user
*/
onPreferredAudioTrack?: OnPreferredAudioTrack;
/**
* notify about changes about cc selected by the user
*/
onTextTrackSelected?: OnTextTrackSelected;
/**
* notify analytics events
*/
onAnalytics?: OnAnalytics;
/**
* notify media analytics events
*/
onMediaAnalytics?: OnMediaAnalytics;
/**
* text to provide assistive text support
*/
onTtsMessage?: TtsCb;
/**
* notify the position of the playback
*/
onPlayerPosition?: OnPlayerPosition;
/**
* accessibility options
*/
accessibility?: AccessibilityOptions;
/**
* libraries required
*/
libs: Libs;
/**
* flag to enable/disable keyboard navigation support
*/
keyboardActive?: boolean;
/**
* flag to enable/disable navigation through remote
*/
remoteActive?: boolean;
/**
* flag to enable/disable gamepadNavigation support
*/
gamepadActive?: boolean;
/**
* flag to disable css transitions to speed up the player, default false
*/
noTransitions?: boolean;
/**
* flag to disable css gradient below controls, default false
*/
noControlsGradientBackground?: boolean;
/**
* flag to toggle play pause in case of bitrate switches
* Hack for sky xione and harmonic stream.
* It needs at least shaka 3.3.19
*/
unfreezeShakaAtMediaQualityChanges?: boolean;
}

interface BoAdapterWebTvProps extends BoAdapterWebTvNoComponentProps {
DivaWebTV: (props: DivaWebTVProps) => JSX.Element | null;
}

interface BoAdapterWebTvVanillaProps extends BoAdapterWebTvNoComponentProps {
el: HTMLElement;
createDivaWebTV: CreateDivaWebTV;
}

Init​

BO Adapter initProps are the same as those in the DIVA webTV SDK, excluding setting property, because it's extracted from BO settings response.

PropertyTypeDefaultDescription
Mandatory
Property: videoIdtype:
string
Default: NAid of the video to play
Property: autoplaytype:
boolean
Default: NAflag to start the video as soon as possible
Optional
Property: deepLinkTypetype:
DeepLinkType
Default: NAtype of the deep link
Property: deepLinkValuetype:
string
Default: undefinedvalue of the deep link in milliseconds
Property: hdrModetype:
boolean
Default: undefinedif HDR is enabled or not
Property: preferredCCTrackNametype:
string
Default: undefinedCC track to start with (if present)
Property: preferredAudioTrackNametype:
string
Default: undefinedAudio track to start with (if present)
Property: hlsJsConfigOverridestype:
any
Default: undefined--
Property: shakaConfigOverridestype:
any
Default: undefined--
Property: bitratePreferencestype:Default: undefined--

Typescript interfaces for InitProps​

BoAdapterWebTvNoComponentInitProps
interface BoAdapterWebTvNoComponentInitProps {
/**
* id of the video to play
*/
videoId: string;
/**
* type of the deep link type
*/
deepLinkType?: DeepLinkType;
/**
* value of the deep link in milliseconds
*/
deepLinkValue?: string;
/**
* if HDR is enabled or not
*/
hdrMode?: boolean;
/**
* CC track to start with (if present)
*/
preferredCCTrackName?: string;
/**
* Audio track to start with (if present)
*/
preferredAudioTrackName?: string;
/**
*
*/
hlsJsConfigOverrides?: any;
/**
*
*/
shakaConfigOverrides?: any;
/**
*
*/
bitratePreferences?: BitratePrefs;
}

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
Middlewares
Property: entitlementUsertype:
(data) => string
Default: undefineda middleware to provide user token when requested

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;
}

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

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;
};
}

BitratePrefs​

PropertyTypeDefaultDescription
Optional
Property: maxtype:
number
Default: -1kbps (-1 means disabled)
Property: mintype:
number
Default: -1kbps (-1 means disabled)
Property: startingtype:
number
Default: -1kbps (-1 means disabled)
Property: useLasttype:
boolean
Default: falseif true it makes DIVA using last bitrate from the previous session.

Typescript interfaces for BitratePrefs​

BitratePrefs
export interface BitratePrefs {
/**
* kbps (-1 means disabled)
*/
max?: number;
/**
* kbps (-1 means disabled)
*/
min?: number;
/**
* kbps (-1 means disabled)
*/
starting?: number;
/**
*
*/
useLast?: boolean;
}

Platform detection​

It is possible to detect the actual platform running in a consistent way with DIVA WebTV Bo Adapter using the methods exposed here:

functiontypedescription
isSkyQ()=>booleantrue if SkyQ box is detected
isTizen()=>booleantrue if Tizen TV is detected
isWebOS()=>booleantrue if WebOS TV is detected
getSmartTvPlatform()=>WebTvPlatformTypesreturn the platform detected

Note:

type WebTvPlatformTypes = 'Tizen' | 'WebOs' | 'SkyQ' | 'Generic';

import { isSkyQ } from "@deltatre-vxp/diva-sdk/diva-webtv-bo-adapter";
import type { BoAdapterWebTvProps } from "@deltatre-vxp/diva-sdk/diva-webtv-bo-adapter";

const skyFixes: Partial<BoAdapterWebTvProps> = {
noControlsGradientBackground: true,
noTransitions: true,
unfreezeShakaAtMediaQualityChanges: true,
};

// props will contain sky fixes only if diva notice that the app is running on supported Sky boxes
const getPropsWithSkyFixes = (props:BoAdapterWebTvProps):BoAdapterWebTvProps => ({
...props,
...isSkyQ() ? skyFixes : {}
})
note
  • {targetEnv}: .min (production), (empty string) development

DivaAPI​

Imperative API to interact with the player.

Typescript interfaces for DIVA API​

DIVA API
interface DivaAPI {
/**
* It will force DIVA to request a new VideoMetadata through videoMetadataProvider
*/
requestVideoMetadataUpdate: (videoId?: string) => 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 };

// Actions

/**
* It pauses video playback..
*/
pause: () => void;

/**
* It starts the video playback.
* @returns the videoElement play promise.
*/
play: () => Promise<void>;

/**
* It seeks the video playback.
* @param value number, milliseconds value relative to the video start time.
* @returns A promise usefull to check when the action is done.
*/
seek: (value: number) => Promise<void>;

/**
* It seeks back the video playback by the value get from videoMetadata.behaviour.seekInterval. Default 10 seconds.
*/
skipBack: () => Promise<void>;

/**
* It seeks forward the video playback by the value get from videoMetadata.behaviour.seekInterval. Default 10 seconds.
* @returns A promise usefull to check when the action is done.
*/
skipForward: () => Promise<void>;

/**
* It seeks the video playback by percentage.
* @param value number, percentage from 0 to 100.
* @returns A promise usefull to check when the action is done.
*/
seekPercentage: (value: number) => Promise<void>;

/**
* It seeks the video playback by Date object.
* @param value Date
* @returns A promise usefull to check when the action is done.
*/
seekAbsolute: (value: Date) => Promise<void>;

/**
* It sets the minimum distance between icons on timeline.
* @param value number, in pixels. Default 40. Take in considerations 1080p resolution..
*/
setTimelineIconsMinDistance: (value: number) => void;

// Advanced UI actions

/**
* It opens audio panel.
*/
openAudioPanel: () => void;

/**
* It opens subtitles panel.
*/
openSubtitlePanel: () => void;

/**
* It opens settings panel.
*/
openSettingsPanel: () => void;

/**
* It opens videolist view.
*/
openVideoList: () => void;

/**
* It sends a custom key press.
*/
sendCustomKeypress: (key: Key, e?: KeyboardEvent) => 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?: {
videoId?: string; // 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 {
videoId?: string;
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',
}

Disable Lazy Loading​

DIVA allows skipping the lazy loading of a third-party library by inserting the value 'false' (boolean) instead of the string containing the library's URL.
By doing so, the player assumes that the library has already been loaded and avoids loading it again.
This can improve startup performances.
Note: It is the integrator's responsibility to ensure the preloading of the necessary libraries.

Example disabling lazy loading for shaka and mux

{
// video libraries
hlsJs: 'https://cdn.jsdelivr.net/npm/hls.js@1.0.4',
shaka: false,
mux: false,

// 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',
}

Accessibility Options​

PropertyTypeDefaultDescription
Optional
Property: darkerBackgroundCctype:
boolean
Default: falseclosed captions with special style to improve legibility
Property: enlargedCcstype:
boolean
Default: falseclosed captions bigger font size to improve legibility
Property: opaqueBackgroundtype:
boolean
Default: falsebackground of transparent system opaque to improve legibility
Property: ccEnhancementsDisabledtype:
boolean
Default: falseif true disable the possibility to change enlargedCcs and darkerBackgroundCc
Property: hideTransparencyDisabledtype:
boolean
Default: falseif true disable the possibility to change opaqueBackground
Callbacks
Property: onAccessibilityUpdatetype:
(data: {darkerBackgroundCc:boolean, enlargedCcs:boolean, opaqueBackground:boolean }) => void
Default: undefinednotify when there are changes on accessibility configuration

Typescript interfaces for Accessibility Options​

AccessibilityData and AccessibilityData

export interface AccessibilityData {
/**
* closed captions with special style to improve legibility
*/
darkerBackgroundCc?: boolean;
/**
* closed captions bigger font size to improve legibility
*/
enlargedCcs?: boolean;
/**
* background of transparent system opaque to improve legibility
*/
opaqueBackground?: boolean;
}

export interface AccessibilityOptions extends AccessibilityData {
/**
* if true disable the possibility to change enlargedCcs and darkerBackgroundCc
*/
ccEnhancementsDisabled?: boolean;
/**
* if true disable the possibility to change opaqueBackground
*/
hideTransparencyDisabled?: boolean;
/**
* notify when there are changes on accessibility configuration
*/
onAccessibilityUpdate?: (data: AccessibilityData) => void;
}