Web SDK 5.1 (Angular)
This guide explains how to integrate DIVA into your web application.
View all examples and basic Web 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​
DIVA is currently provided as a standalone web component .js file. Please view the current releases in order to download the latest version. The component is implemented using Angular 13.0.2.
No issues have been found integrating with other frameworks or other versions of Angular. In case of any issues please report to Platforms.Team.DivaPlayer@deltatre.com
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}&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.
DIVA Configuration​
Initialization​
Once the data has been provisioned, we combine the variables into a set of parameters to instantiate DIVA
const divaParams = {
videoId: video.videoId.split(","),
setting,
dictionary,
videoMetadataProvider: createVideoMetadataProvider(),
onAnalyticEvent: ({ type, eventArguments, interactive }) =>
console.log(`[AnalyticEvent] ${type}`, eventArguments),
onMediaAnalyticEvent: (event) => {
console.log(
`[MediaAnalyticEvent] ${event.type}`,
event.payload ? event.payload : ""
);
if (mediaAnalyticPlugin) {
mediaAnalyticPlugin.handleEvent(event);
}
},
onVideoError: console.error,
};
Using the necessary params, construct your Diva object using the element identifier of the video container:
const { element: divaElement, api: divaAPI } = new Diva(
".diva-player-container",
divaParams
);
Once DIVA has loaded and is ready, the 'diva-ready' event is fired.
divaElement.addEventListener("diva-ready", function () {
console.log("diva-ready");
});