Skip to main content

WebTV SDK 5.5

This guide explains how to integrate DIVA into a webTV application.

Release information

View all examples and basic WebTV integration information tagged by SDK versions.

A VXP GitHub account is required to gain access.

A more complete backend integration example is available here:

https://github.com/deltatre-vxp/diva-web-compatibility-layer-demo

Requirements​

Our SDK is designed to be used on:

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

The SDK self-contains every dependency except:

  • ReactJS, the host application most provide ReactJS 16+
  • The video player, which loads dynamically based on target device and content type

Provisioning​

The Settings, with which DIVA will be configured.
The Dictionary, which will provide DIVA with the translations and localisations for the application.
The VideoMetaData, which provides DIVA with information about the playback for a specific item.

For more information about these items, please consult the Documentation.

This data can be provided as the application developer requires, but will need to return SettingClean, DictionaryClean and VideoMetaDataClean objects respectively in order to work with the DIVA configuration and initialise the player objects.

For the purpose of this example we will be using raw json, but the provision of the data can be provided from any available source.

We can as an example instantiate a mock 'video' item, from a potential video catalog. Crucial to DIVA 5 is the provision of an ID with which to retrieve settings information and a videoID to retrieve the VideoMetaData.

const videos = {
data: [
{
id: "item-1",
image: "./images/fifa-world-cup.jpg",
title: "France vs Croatia (minimal)",
videoId: "c6455bff-945f-42b2-af99-81dcd5aeba29",
settingId: "full",
},
],
};

Settings​

Setting for the application can be provided in various different formats and are used to provide configuration with which to run a particular video, for example:

Setting Example
{
"general":{
"audioSelectionMethod":"lang",
"closedCaptionSelectionMethod":"lang",
"expectedLiveDuration":3600000,
"increaseLiveDuration":600000,
"isMiddleTimelineEventsLineEnabled":true,
"isTimelineEventsVisibleWithCommentaryOpen":false,
"isVideoThumbnailPreviewEnabled":true,
"jumpLargeGaps":true,
"liveBackOff":30000,
"minimalLayoutWidth":600,
"pipMode":true,
"relevantCommentaryStartsVisible":false,
"resolveManifestUrl":true,
"smallGapLimit":0,
"trackVideoDataManifest":false,
"videoAnalyticsEventFrequency":60000,
"culture":"en-GB"
},
"alerts":{
"alertsPath":"https://<url>/alerts_demo.json",
"displayTime":10000
},
"customPlayByPlay":[
{
"key":"FirstExtraTimeEnd_Big",
"value":"https://<url>/icons/{p.density}/phase_end_big.png"
},
{
"key":"FirstExtraTimeEnd_Mini",
"value":"https://<url>/icons/{p.density}/phase_end_small.png"
},
{
"key":"FirstExtraTimeStart_Big",
"value":"https://<url>/icons/{p.density}/phase_start_big.png"
},
{
"key":"FirstExtraTimeStart_Mini",
"value":"https://<url>/icons/{p.density}/phase_start_small.png"
},
{
"key":"FirstHalfEnd_Big",
"value":"https://<url>/icons/{p.density}/phase_end_big.png"
},
{
"key":"FirstHalfEnd_Mini",
"value":"https://<url>/icons/{p.density}/phase_end_small.png"
},
{
"key":"FirstHalfStart_Big",
"value":"https://<url>/icons/{p.density}/phase_start_big.png"
},
{
"key":"FirstHalfStart_Mini",
"value":"https://<url>/icons/{p.density}/phase_start_small.png"
},
{
"key":"Goal_Big",
"value":"https://<url>/icons/{p.density}/goa_big.png"
},
{
"key":"Goal_Mini",
"value":"https://<url>/icons/{p.density}/goa_small.png"
},
{
"key":"OwnGoal_Big",
"value":"https://<url>/icons/{p.density}/ogo_big.png"
},
{
"key":"OwnGoal_Mini",
"value":"https://<url>/icons/{p.density}/ogo_small.png"
},
{
"key":"PenaltyEnd_Big",
"value":"https://<url>/icons/{p.density}/phase_end_big.png"
},
{
"key":"PenaltyEnd_Mini",
"value":"https://<url>/icons/{p.density}/phase_end_small.png"
},
{
"value":"https://<url>/icons/{p.density}/png_big.png",
"key":"PenaltyGoal_Big"
},
{
"key":"PenaltyGoal_Mini",
"value":"https://<url>/icons/{p.density}/png_small.png"
},
{
"key":"PenaltyStart_Big",
"value":"https://<url>/icons/{p.density}/phase_start_big.png"
},
{
"key":"PenaltyStart_Mini",
"value":"https://<url>/icons/{p.density}/phase_start_small.png"
},
{
"key":"PenaltyWrong_Big",
"value":"https://<url>/icons/{p.density}/ppw_big.png"
},
{
"key":"PenaltyWrong_Mini",
"value":"https://<url>/icons/{p.density}/ppw_small.png"
},
{
"key":"PhasePenaltyGoal_Big",
"value":"https://<url>/icons/{p.density}/ppg_big.png"
},
{
"value":"https://<url>/icons/{p.density}/ppg_small.png",
"key":"PhasePenaltyGoal_Mini"
},
{
"key":"PhasePenaltyWrong_Big",
"value":"https://<url>/icons/{p.density}/ppw_big.png"
},
{
"value":"https://<url>/icons/{p.density}/ppw_small.png",
"key":"PhasePenaltyWrong_Mini"
},
{
"key":"RedCard_Big",
"value":"https://<url>/icons/{p.density}/rc_big.png"
},
{
"key":"RedCard_Mini",
"value":"https://<url>/icons/{p.density}/rc_small.png"
},
{
"key":"SecondExtraTimeEnd_Big",
"value":"https://<url>/icons/{p.density}/phase_end_big.png"
},
{
"key":"SecondExtraTimeEnd_Mini",
"value":"https://<url>/icons/{p.density}/phase_end_small.png"
},
{
"key":"SecondExtraTimeStart_Big",
"value":"https://<url>/icons/{p.density}/phase_start_big.png"
},
{
"key":"SecondExtraTimeStart_Mini",
"value":"https://<url>/icons/{p.density}/phase_start_small.png"
},
{
"key":"SecondHalfEnd_Big",
"value":"https://<url>/icons/{p.density}/phase_end_big.png"
},
{
"key":"SecondHalfEnd_Mini",
"value":"https://<url>/icons/{p.density}/phase_end_small.png"
},
{
"key":"SecondHalfStart_Big",
"value":"https://<url>/icons/{p.density}/phase_start_big.png"
},
{
"key":"SecondHalfStart_Mini",
"value":"https://<url>/icons/{p.density}/phase_start_small.png"
},
{
"key":"Substitution_Big",
"value":"https://<url>/icons/{p.density}/sb_big.png"
},
{
"key":"Substitution_Mini",
"value":"https://<url>/icons/{p.density}/sb_small.png"
},
{
"key":"YellowCard_Big",
"value":"https://<url>/icons/{p.density}/yc_big.png"
},
{
"key":"YellowCard_Mini",
"value":"https://<url>/icons/{p.density}/yc_small.png"
}
],
"ecommerce":{
"feedUrl":"https://<url>/ecommerce/index.html?eventId={v.eventId}&amp;culture={d.culture}",
"wordTag":"shop",
"ecommerceId":"e-commerce",
"iconUrl":"https://<url>/img/shop_icon_white.png",
"toleranceWindow":5000,
"showNotificationsOnce":false
},
"highlights":{
"startMode":"short",
"shortFilter":[
"GOAL",
"OwnGoal",
"PenaltyGoal"
],
"mediumFilter":[
"Goal",
"OwnGoal",
"PenaltyGoal",
"YellowCard",
"RedCard"
],
"longFilter":[
"*"
],
"liveFilter":[
"Goal",
"OwnGoal",
"PenaltyGoal",
"YellowCard",
"RedCard",
"Substitution"
]
},
"liveLike":{
"clientId":"WV6W1rkAJAAXAS9l0LpqHzjDyEcPbuGJjX7Kc2hk",
"chatEnabled":true,
"widgetThemeUrl":"https://<url>/LiveLike/customWidgetThemeUpdated.json"
},
"pushEngine":{
"configUrl":"https://<url>/DIVAProduct/www/Data/DivaDemoIBC/PushEngine/pushengineConfig_HBS.json",
"eCommerceCollectionName":"eCommerceDemo",
"eCommerceCollectionEnabled":false,
"editorialCollectionName":" "
},
"syncDataPanels":{
"dataFolderUrl":"https://<url>/DIVAProduct/www/Data/Diva5.0Test/output/OverlayLiteData/{V.EventId}.{d.Culture}/{OverlayID}.xml",
"renderingFolderUrl":"https://<url>/DIVAProduct/www/Data/Diva5.0Test/output/RenderingLiteData{n:ResourceURI}",
"trustedOrigins":"https://divadoc.deltatre.net,https://<url>"
},
"videoCast":{
"castBackground":"https://<url>/img/diva_chromecast.jpg",
"chromecastAppID":"<appID>"
}
}

For more information about setting and the available options click here.

Dictionary​

Dictionary must be provided based on the locale and will resemble something like the following:

Dictionary Example
{
"messages":{
"diva_go_live":"Go Live",
"diva_video_error":"This video is not working or not available in your region.",
"diva_error_button_ok":"OK",
"diva_menu_full_stats_button":"All Stats",
"diva_playbutton":"Play",
"diva_pausebutton":"Pause",
"diva_seekforward_button":"+{n}",
"diva_seekback_button":"-{n}",
"diva_alternate_timeline":"Alternate Timeline",
"diva_alternate_timeline_show_all":"See all events",
"diva_spoil":"SHOW EVENTS",
"diva_fullscreen":"Full Screen",
"diva_exitfullscreen":"Exit Full Screen",
"diva_alert":"Alerts",
"diva_multicam":"MULTICAM",
"diva_360clips":"360 CLIPS",
"diva_360multicam":"360 MULTICAM",
"diva_no_multicam":"Videos will appear as soon as they are published, please retry in a short while",
"diva_back_button":"Back",
"diva_chapters_open":"Chapters",
"diva_chapters_close":"Close Chapters",
"diva_theater_mode":"Theater Mode",
"diva_exit_theater_mode":"Exit Theater Mode",
"diva_mute":"Mute",
"diva_unmute":"Unmute",
"diva_show_multiview":"Show in sideBySide",
"diva_collapse_this_video":"Collapse video",
"diva_close_this_video":"Close video",
"diva_chromecast":"Chromecast",
"diva_close_stats_button":"",
"diva_audio_is_muted":"Audio is muted",
"diva_vr_start_video_loading":"VR loading ...",
"diva_button_close":"Close",
"diva_gck_connect_to_device":"Cast to",
"diva_gck_stop_casting":"Stop casting",
"diva_gck_cancel":"Cancel",
"diva_videometadata_error":"The video metadata are corrupted. Please try another video",
"diva_overlay_load_failure":"Could not load data panel",
"diva_drm_error":"Content protection error",
"diva_ssai_request_error":"This video is not working right now. Please disable any AdBlocker and then try again. In case this error persist please contact the Customer Care at help@diva.com",
"diva_no_highlights_error":"No key moments available at the moment. Please try later",
"diva_settings":"Settings Panel",
"diva_settings_button":"Settings",
"diva_error_title":"Error",
"diva_audio":"Audio Tracks",
"diva_cc_panel_title":"Subtitles",
"diva_closed_caption":"Closed Caption",
"diva_cc_disabled":"Disabled",
"diva_cc_d3608":"Enable CC",
"diva_cc_english":"English",
"diva_cc_french":"FRENCH",
"diva_cc_spanish":"Spanish",
"diva_cc_#1 Fre":"French",
"diva_cc_#2 Eng":"English",
"default_audio_selected":"Default Audio",
"diva_settings_hdr_enable":"Enable HDR",
"diva_adResumeTime":"Your video will resume in {remTime} s",
"diva_adResumeAt":"Your video will resume after the following advertisements {cVideo}/{totVideo}",
"diva_ad_loading_text":"Ad loading",
"diva_adblock":"You need to disable AdBlock to view the content",
"diva_adClickToEnableAudio":"Enable ad audio",
"diva_select_chapter":"Chapter List",
"diva_alert_replay":"Replay",
"diva_alert_back":"Back to",
"diva_highlightsmode_loading":"Highlights cards processing...",
"diva_highlightsmode_howto":"How do you want to watch this match?",
"diva_highlightsmode_short":"Short",
"diva_highlightsmode_medium":"Medium",
"diva_highlightsmode_long":"Long",
"diva_highlightsmode_live":"Live",
"diva_highlightsmode_full":"Full Match",
"diva_highlightsmode_resume":"Resume Highlights",
"diva_highlightsmode_next":"Next",
"diva_highlightsmode_highlights":"Highlights",
"diva_highlightsmode_youarein":"You are in highlights mode",
"diva_highlightsmode_notification_title":"Don't miss {n} key moments",
"diva_highlightsmode_notification_subtitle":"Would you like to watch them?",
"diva_highlightsmode_notification_watch":"Watch",
"diva_highlightsmode_highlights_title":"Highlights duration:",
"diva_hours":"h",
"diva_minutes":"m",
"diva_seconds":"s",
"diva_playbyplay":"Commentary",
"diva_noplaybyplay":"First message will be displayed shortly after the start of the session",
"diva_recommendation_watch_again":"Watch again",
"diva_recommendation_watch_next_video":"Watch the next video",
"diva_recommendation_next_videos":"Next videos",
"diva_recommendation_video_autoload":"Next video will start in {sec} sec",
"shop":"Shop",
"diva_ecommerce_rotate_device":"Rotate your screen to view the shop",
"diva_settings_close":"",
"diva_cc_enabled":"Enabled",
"diva_settings_pip_enable":"Enable Picture-In-Picture",
"diva_enterpip":"Enter pip mode",
"diva_exitpip":"Exit pip mode",
"diva_novideoavailable":"",
"diva_airplay_error":"Error trying to cast to AirPlay",
"diva_airplay_forbiden_error":"AirPlay cast disabled in Diva settings",
"diva_live":"Live Now",
"diva_settings_title":"Settings",
"diva_settings_hdr_label":"HDR",
"diva_settings_hdr_description":"Disable HDR if you are experiencing problems seeing the colours in the video",
"diva_at_button_tooltip":"Audio",
"diva_at_settings_title":"Audio tracks",
"diva_cc_button_tooltip":"Subtitles",
"diva_cc_settings_title":"Subtitles",
"diva_cc_eng":"english (lang)",
"diva_cc_en":"english (lang)",
"diva_airplay_forbidden_error":"AirPlay cast disabled in Diva settings",
"diva_timeline_events_title":"Key moments",
"diva_videolist_watching":"WATCHING",
"diva_videolist_live":"LIVE",
"diva_cc_enhancements_button":"Caption style",
"diva_cc_enhancements_button_subtitle":"Change text size and style",
"diva_cc_enlarge_label":"Enlarge text",
"diva_cc_caption_style_title":"Caption style",
"diva_cc_enlarge_subtitle":"Enlarge text",
"diva_cc_enlarge_description":"Activate for a significant increase of the subtitles text, for better readability",
"diva_cc_style_subtitle":"Style",
"diva_cc_style_description":"Activate to enable a darker background behind the subtitles text for increased visibility",
"diva_cc_style_label":"Style",
"diva_settings_hdr_ON_value":"On",
"diva_settings_hdr_OFF_value":"Off",
"diva_eop_starts_in_seconds":"Starts in {seconds} sec",
"diva_eop_reccomandation_title":"Recommendations",
"diva_eop_rewind":"Replay",
"diva_ccat_panel_title":"Audio and Subtitles",
"diva_accessibility_high_contrast_title":"Increase contrast",
"diva_accessibility_high_contrast_description":"Turn on increase contrast mode if you are having trouble seeing the menu",
"diva_accessibility_high_contrast_label":"Increase contrast",
"diva_videolist_default_title":"Default Title",
"diva_videolist_title_highlight":"Highlights",
"diva_fullmatch_highlights_button_label":"Full Match",
"diva_next_highlights_button_label":"Next",
"diva_videolist_highlight":"HIGHLIGHTS",
"diva_highlights_title_medium":"Highlights medium",
"diva_highlights_title_long":"Highlights long",
"diva_highlights_title_short":"Highlights short",
"diva_cc_caption_style_header":"Caption style",
"diva_cc_settings_header":"Subtitles",
"diva_cc_settings_subheader":"Style",
"diva_cc_enlarge_subheader":"Enlarge text",
"diva_highlights_title_live":"Live highlights",
"diva_highlights_notification":"Match Highlights",
"diva_highlights_badge_live":"Live Highlights",
"diva_highlights_badge_short":"Short Highlights",
"diva_highlights_badge_medium":"Medium Highlights",
"diva_highlights_badge_long":"Long Highlights",
"diva_highlights_alert_seek_unavailable":"Return to the full match to use rewind and fast forward",
"diva_pinned":"Pinned",
"diva_menu_button":"MENU",
"diva_data_panel_close_button":"Close Data Panel",
"diva_menu_close_button":"Close Menu",
"diva_data_panel_button_tooltip":"Stats",
"diva_data_panel_no_data_available_title":"No data available yet",
"diva_data_panel_no_data_available_description":"Please check back here shortly after the game has started!",
"diva_eop_replay":"Replay",
"diva_swap_video":"Swap video"
}
}

For more information about dictionary and the available options click here.

VideoMetaData​

In order to support decoupled OVP provision, DIVA 5 requires that video meta data is retrieved by the integrating application and passed to DIVA 5 as part of the initialisation parameters, an example of which is as follows:

VideoMetadata Example
{
"title":"Video title",
"image":"https://<thumbnail_url>.jpg",
"eventId":"108606",
"programDateTime":"2018-07-15T13:40:15.681Z",
"trimIn":4680858,
"trimOut":11641166,
"ad":"https://<vast_url>/skippable2.xml",
"sources":[
{
"uri":"https://<url>/<video_id>.ism/manifest(format=m3u8-aapl,filter=hls)",
"format":"HLS"
}
],
"audioTracks":[
{
"label":"English",
"id":"English1",
"selector":"English"
}
],
"defaultAudioTrackId":"English1",
"videoLists":[
{
"feedUrl":"https://<url>/rss/108606.xml",
"menu":"Other cameras",
"message":"Watch the live match from different angles",
"behaviour":"multistreamSwitch",
"id":"multistream",
"pollingInterval":30
},
{
"menu":"Other matches",
"message":"Watch other live mathes",
"highlightColor":"0xE65100",
"highlightColorLight":"0xff0000",
"id":"videolist",
"feedUrl":"https://<url>/rss/videolistSwitchDemo.xml"
}
],
"customAttributes":{
"chatId":"444ecf59-dbf2-43db-ae09-99926714022a",
"chatType":"influencer"
},
"recommendation":{
"feedUrl":"https://<url>/rss/videolist_recommendation_short.xml",
"autoLoadTime":0
},
"behaviour":{
"spoilerMode":"highlights"
},
"videoId":"<video_id>"
}
VideoMetadata Provider
// Type definition
export type VideoMetadataProvider = (
videoId: string,
currentVideoMetadata: VideoMetadataClean | undefined,
playbackState?:
| {
chromecast?: boolean | undefined;
hdrMode?: boolean | undefined;
}
| undefined
) => Promise<VideoMetadata>;

// Implementation example
export const requestVideometadata: VideoMetadataProvider = (videoId, currentVideoMetadata, playbackState) => {
videoId = decodeURIComponent(videoId);

const platform = playbackState?.chromecast === true ? 'chromecast' : 'html5';
const hdrType = playbackState?.hdrMode === true ? 'hdr10' : 'none';

const url = `https://<videoMetadataServiceUrl>/${videoId}?platform=${platform}&hdrType=${hdrType}`;

return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();

xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject(new Error(`${this.status} ${xhr.statusText}`));
}
};
xhr.onerror = function () {
reject(xhr.statusText);
};
xhr.send();
});
};

Provision must be done with the same signature as above so that DIVA internally is able to call the VideoMetaData provider and if necessary recall based on interval polling if the application requires data to be refreshed, i.e.

if (!isNaN(divaParams.videoPolling) && divaParams.videoPolling > 0) {
setInterval(function () {
divaAPI.requestVideoMetadataUpdate();
}, divaParams.videoPolling * 1000);
}

With the ability to return VMD, we then have all the elements required to instantiate a DIVA session.

For more information about Video Meta Data please click here.

Entitlement​

Entitlement and Entitlement Provider 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-webtv-sdk

DIVA Configuration​

Once the data has been provisioned, we combine the variables into a set of parameters to instantiate DIVA.

PropertyTypeDefaultDescription
Mandatory
initDivaWebTVInitTypeNAinit config for DIVA
dictionaryDictionaryNADIVA dictionary
videoMetadataProviderProviderNAFunction used by DIVA to retrieve videoMetadata
libsobjectNA

Object containing the external libraries' url lazy loaded by DIVA only when needed.
Libs reference

Optional
entitlementProviderentitlementNAFunction used by DIVA to perform entitlement and heartbeat calls
keyboardActivebooleantrue

flag to enable/disable keyboard navigation support

navigationActivebooleantrue

flag to enable or disable navigation inside the component

remoteActivebooleantrue

flag to enable/disable navigation through remote

gamepadActivebooleantrue

flag to enable/disable gamepadNavigation support

accessibilityAccessibilityOptions

undefined

accessibility options.

setAPIfunctionNA

It exposes DIVA APIs
(apiRef: DivaAPI) => void;
API reference

unfreezeShakaAtMediaQualityChangesbooleanfalseHack to overcome to Sky XiOne issue that freezes when quality level changes with Harmonic streams. When level switch occurs a micro seek is performed to unfreeze the video.
noTransitionsbooleanfalseflag to disable css transitions
noControlsGradientBackgroundbooleanfalseflag to disable css gradient backgrounds
uiDelaynumber0delay to show the player UI in milliseconds (from version 5.5.5)
Callbacks
onAnalyticEventfunctionNA

Callback for generic analytic events
(event: GenericEvent) => void;

onMediaAnalyticEventfunctionNA

Callback for media analytic events
(event: MediaEvent) => void;

onPlayerPositionfunctionNA

Called when player position (both relative to the video logical start and unix timecode) of the main video changes

(position: { relativePosition: number; absolutePosition: Date } ) => void;

onPreferredAudioTrackfunctionNA

Called when the user select an audiotrack
(value: string) => void;

onTextTrackSelectedfunctionNA

Called when the user select a closed caption
(value: string) => void;

onVideoErrorfunctionNA

Called on DIVA errors

(videoError: VideoError, videoMetadata: VideoMetadataClean | undefined) => void;

onEventfunctionNA

it's actually used only for cases when the user is leaving the player with BACK_PRESS_OUTSIDE
(event: PlayerEvent) => boolean | Promise<boolean>

onTtsMessagefunctionNA

it notifies text to be converted to speech fo accessibility
(data: TtsData) => void<boolean>

DivaWebTVInitType​

PropertyTypeDefaultDescription
Mandatory
videoIdstringNAid of a specific videoMatadata
settingSettingNADIVA setting
autoplaybooleanNAIt specifies whether to autoplay DIVA (on webtv this should always be true).
Optional
deepLinkTypestring: 'relative' | 'absolute''relative'

Type of deeplink to apply at startup: relative to the video start (or trimIn) or absolute.

deepLinkValuestring[]

Value of deeplink to apply at startup:
type relative -> number of milliseconds
type absolute -> ISO 8801 datetime.

hdrModeboolean[]

It specifies whether to activate HDR or not at startup.

preferredAudioTrackNamestringNAStarting selector for the audiotracks
preferredCCTrackNamestringNAStarting selector for the closed captions
bitratePreferences

{
max?: number;
min?: number;
starting?: number;
useLast?: boolean;
}

{
max: -1,
min:-1,
starting: -1,
useLast: false
}

max, min, starting bitrate (-1 means disabled).
useLast: if true it makes DIVA using last bitrate from the previous session.

shakaConfigOverridesany{}Overrides for shaka video library setup config
hlsJsConfigOverridesany{}Overrides for hls.js video library setup config
parameters{ [key: string]: string }undefined

Map of additional keys to add to the path resolver.


Input keys will be saved inside resolver as "settings.<key>"

Accessibility Options​

PropertyTypeDefaultDescription
Optional
darkerBackgroundCcboolenfalseclosed captions with special style to improve legibility
enlargedCcsboolenfalseclosed captions bigger font size to improve legibility
opaqueBackgroundboolenfalsebackground of transparent system opaque to improve legibility
ccEnhancementsDisabledboolenfalseIt disables cc enhancements (darkerBackgroundCc, enlargedCcs) and disables the possibility to have this accessibility feature to be updated by the user
hideTransparencyDisabledboolenfalseIt disables opaqueBackground and disables the possibility to have this accessibility feature to be updated by the user
onAccessibilityUpdateboolenfalseit returns the values of darkerBackgroundCc, enlargedCcs and opaqueBackground each time on of this are updated by the user
Configuration example
{
init: {
videoId: "VIDEO_ID"
autoplay: true,
bitratePreferences: {
max: -1,
min: -1,
starting: -1,
useLast: false
},
deepLinkType: "relative",
deepLinkValue: "1200000",
hdrMode: false,
setting: {
general: {
culture: "en-GB",
isCommentaryFilteredByChapter: false
}
}
},
dictionary: {
messages: {
default_audio_selected: "Default Audio",
diva_360clips: "360 CLIPS",
diva_360multicam: "360 MULTICAM",
...
},
libs: {
googleCast: "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1",
googleDAI: "https://imasdk.googleapis.com/js/sdkloader/ima3_dai.js",
googleIMA: "https://imasdk.googleapis.com/js/sdkloader/ima3.js",
hlsJs: "https://cdn.jsdelivr.net/npm/hls.js@1.0.4",
mux: "https://cdnjs.cloudflare.com/ajax/libs/mux.js/6.2.0/mux.min.js",
shaka: "https://ajax.googleapis.com/ajax/libs/shaka-player/4.3.1/shaka-player.compiled.js",
threeJs: "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.148.0/three.min.js",
},
onAnalyticEvent: console.log,
onMediaAnalyticEvent: console.log,
onVideoError: console.log,
setAPI: (api) => {
// Here you can save a reference to DIVA APIs
window.divaAPI = api;
},
videoMetadataProvider: (videoId, currentVideoMetadata, playbackState) => {
// returning a Promise of a VideoMetadata
return new Promise((resolve, reject) => {
resolve({
title: "<video_title>",
videoId: '<video_id>',
sources: [
{
format: "HLS",
uri: "https://<url>"
}
],
...
});
});
}
}

Initialization​

import React, { useEffect, useState } from "react";
import { DivaWebTV } from "@deltatre-vxp/diva-webtv-sdk/{platform}/index{targetEnv}.js";
import "@deltatre-vxp/diva-webtv-sdk/{platform}/index{targetEnv}.css";

const SETTINGS_URL = "https://example.com/settings";
const DICTIONARY_URL = "https://example.com/dictionary";
const VIDEO_METADATA_URL = "https://example.com/metadata";
const VIDEO_ID = "42";

const videoMetadataProvider = async (videoId) => {
return await fetch(`${VIDEO_METADATA_URL}/${videoId}`);
};

const getSettings = async () => {
const data = await fetch(SETTINGS_URL);
return await data.json();
};

const getDictionary = async () => {
const data = await fetch(DICTIONARY_URL);
return await data.json();
};

export function App() {
const [setting, setSettings] = useState(null);
const [dictionary, setDictionary] = useState(null);

useEffect(() => {
Promise.all([getSettings, getDictionary]).then(([setting, dictionary]) => {
setSettings(setting);
setDictionary(dictionary);
});
}, []);

if (!(setting && dictionary)) {
return null;
}
return (
<div className="app">
<DivaWebTV
init={{
setting,
videoId: VIDEO_ID,
autoplay: true,
}}
dictionary={dictionary}
videoMetadataProvider={videoMetadataProvider}
entitlementProvider={entitlementProvider}
/>
</div>
);
}
note
  • {platform}: tizen, webos, generic
  • {targetEnv}: .min (production), (empty string) development

API​

The property setAPI inside DIVA Configuration is intended to be a function that returns an object containing all the APIs for the current DIVA instance.

DIVA API reference list:


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

// Getters

/**
* It returns the current video time in milliseconds relative to the video start time.
*/
getCurrentPosition: () => number;

/**
* It returns the current video time as absolute Date object NOT relative to the video start time.
*/
getCurrentPositionAbsolute: () => Date;

/**
* It returns the video duration in milliseconds taking into account of any trimIn and trimOut.
*/
getCurrentDuration: () => number;

/**
* It returns the video end time as absolute Date object taking into account of any trimOut.
*/
getCurrentDurationAbsolute: () => 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;

/**
* 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;

Plugins compatibility matrix​

DIVA WEBTVNAVIGATIONCONVIVATTSYOUBORA
5.5.01.2.01.2.21.1.01.0.5
5.4.21.2.01.2.01.1.01.0.3
5.4.11.2.01.2.01.1.01.0.0 (ii)
5.4.01.2.01.2.01.1.01.0.0 (ii)
5.3.01.1.01.1.0 (i)1.0.1--
5.2.01.1.01.1.0 (i)1.0.1--
5.0.0--------
  • (i) old plugin naming
  • (ii) before NPAW certification

Packages names:​

  • DIVA WEBTV: @deltatre-vxp/diva-webtv-sdk
  • NAVIGATION: @deltatre-vxp/diva-plugin-webtv-navigation
  • CONVIVA: @deltatre-vxp/diva-web-conviva-plugin (old is @deltatre-vxp/diva-plugin-conviva)
  • TTS: @deltatre-vxp/diva-plugin-tts
  • YOUBORA: @deltatre-vxp/diva-web-youbora-plugin

Logging​

It is possible to attach to DIVA logs or even to use DIVA logger by:

import { LogEntry, onLog, getLogger } from "@deltatre-vxp/diva-webtv-sdk/{platform}/index{targetEnv}.js";

// Attach to DIVA logs
const unsubscribe = onLog((log: LogEntry) => {
console.log(log.message, log);
});

// Make use of DIVA logger
const { logDebug, logError, logInfo, logWarning } = getLogger('GENERIC:APP');
logDebug('log message', {
whatever: 'details'
});

// Unsubscribe from DIVA logs
unsubscribe();
note
  • {platform}: tizen, webos, generic
  • {targetEnv}: .min (production), (empty string) development