From 188f29b2ef807d928b32156c7e218c93971afc7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=CC=81lvaro=20Velad=20Galva=CC=81n?= Date: Mon, 28 Aug 2023 14:49:30 +0200 Subject: [PATCH 1/2] feat(Ads): Allow use a custom playhead tracker in CS --- demo/common/message_ids.js | 2 ++ demo/config.js | 10 ++++++++++ demo/locales/en.json | 2 ++ demo/locales/source.json | 8 ++++++++ externs/ima.js | 2 +- externs/shaka/player.js | 8 +++++++- lib/ads/client_side_ad_manager.js | 33 +++++++++++++++++++++++++++++-- lib/util/player_configuration.js | 4 +++- 8 files changed, 64 insertions(+), 5 deletions(-) diff --git a/demo/common/message_ids.js b/demo/common/message_ids.js index ebec947d9e..99de27b8a2 100644 --- a/demo/common/message_ids.js +++ b/demo/common/message_ids.js @@ -153,6 +153,7 @@ shakaDemo.MessageIds = { /* Config panel. */ ADAPTATION_RESTRICTIONS_SECTION_HEADER: 'DEMO_ADAPTATION_RESTRICTIONS_SECTION_HEADER', ADAPTATION_SECTION_HEADER: 'DEMO_ADAPTATION_SECTION_HEADER', + ADS_SECTION_HEADER: 'DEMO_ADS_SECTION_HEADER', ALWAYS_STREAM_TEXT: 'DEMO_ALWAYS_STREAM_TEXT', ALWAYS_STREAM_TEXT_WARNING: 'DEMO_ALWAYS_STREAM_TEXT_WARNING', AUDIO_CHANNEL_COUNT: 'DEMO_AUDIO_CHANNEL_COUNT', @@ -179,6 +180,7 @@ shakaDemo.MessageIds = { CMCD_SECTION_HEADER: 'DEMO_CMCD_SECTION_HEADER', CONNECTION_TIMEOUT: 'DEMO_CONNECTION_TIMEOUT', CONTENT_ID: 'DEMO_CONTENT_ID', + CUSTOM_PLAYHEAD_TRACKER: 'DEMO_CUSTOM_PLAYHEAD_TRACKER', DASH_SEQUENCE_MODE: 'DEMO_DASH_SEQUENCE_MODE', DEFAULT_AUDIO_CODEC: 'DEMO_DEFAULT_AUDIO_CODEC', DEFAULT_PRESENTATION_DELAY: 'DEMO_DEFAULT_PRESENTATION_DELAY', diff --git a/demo/config.js b/demo/config.js index 6070b3c36f..568dd5e0a2 100644 --- a/demo/config.js +++ b/demo/config.js @@ -98,6 +98,7 @@ shakaDemo.Config = class { shakaDemo.MessageIds.RESTRICTIONS_SECTION_HEADER); this.addCmcdSection_(); this.addLcevcSection_(); + this.addAdsSection_(); } /** @@ -328,6 +329,15 @@ shakaDemo.Config = class { .addBoolInput_(MessageIds.LCEVC_DRAW_LOGO, 'lcevc.drawLogo'); } + /** @private */ + addAdsSection_() { + const MessageIds = shakaDemo.MessageIds; + const docLink = this.resolveExternLink_('.AdsConfiguration'); + this.addSection_(MessageIds.ADS_SECTION_HEADER, docLink) + .addBoolInput_(MessageIds.CUSTOM_PLAYHEAD_TRACKER, + 'ads.customPlayheadTracker'); + } + /** * @param {string} category * @param {!shakaDemo.MessageIds} sectionName diff --git a/demo/locales/en.json b/demo/locales/en.json index 044476e90a..13c9bdb287 100644 --- a/demo/locales/en.json +++ b/demo/locales/en.json @@ -5,6 +5,7 @@ "DEMO_AD_SEARCH": "Filters for assets that have advertisements.", "DEMO_AD_TAG_URL": "Ad Tag URL", "DEMO_ADS_TAB": "Ads", + "DEMO_ADS_SECTION_HEADER": "Ads", "DEMO_ALL_CONTENT": "ALL CONTENT", "DEMO_ALWAYS_STREAM_TEXT": "Always Stream Text", "DEMO_ALWAYS_STREAM_TEXT_WARNING": "Text must always be streamed while native controls are enabled, for captions to work.", @@ -53,6 +54,7 @@ "DEMO_CUSTOM_INTRO_ONE": "Try Shaka Player with your own content!", "DEMO_CUSTOM_INTRO_THREE": "Custom assets will remain even after reloading the page.", "DEMO_CUSTOM_INTRO_TWO": "Press the button below to add a custom asset.", + "DEMO_CUSTOM_PLAYHEAD_TRACKER": "Custom playhead tracker", "DEMO_DASH": "DASH", "DEMO_DASH_IF": "DASH-IF", "DEMO_DASH_SEQUENCE_MODE": "Enable DASH sequence mode", diff --git a/demo/locales/source.json b/demo/locales/source.json index 87ddde1b7b..be6c8e64c0 100644 --- a/demo/locales/source.json +++ b/demo/locales/source.json @@ -15,6 +15,10 @@ "description": "The header for a tab within the custom asset creation dialog.", "message": "Ads" }, + "DEMO_ADS_SECTION_HEADER": { + "description": "The header for a section of configuration values.", + "message": "Ads" + }, "DEMO_AD_SEARCH": { "description": "A tooltip for an optional search term.", "message": "Filters for assets that have advertisements." @@ -215,6 +219,10 @@ "description": "The second part of a message instructing users on how to add custom content.", "message": "Press the button below to add a custom asset." }, + "DEMO_CUSTOM_PLAYHEAD_TRACKER": { + "description": "The name of a configuration value.", + "message": "Custom playhead tracker" + }, "DEMO_DASH": { "description": "Text that describes an asset that is packaged in a DASH manifest.", "message": "[PROPER_NAME:DASH]" diff --git a/externs/ima.js b/externs/ima.js index 0db047e385..b23fb10bd3 100644 --- a/externs/ima.js +++ b/externs/ima.js @@ -119,7 +119,7 @@ google.ima.AdsManager = class { /** @const */ google.ima.AdsManagerLoadedEvent = class extends Event { /** - * @param {!HTMLElement} video + * @param {!(HTMLElement|{currentTime: number})} video * @param {!google.ima.AdsRenderingSettings=} adsRenderingSettings * @return {!google.ima.AdsManager} */ diff --git a/externs/shaka/player.js b/externs/shaka/player.js index bf0a684820..7602122fe9 100644 --- a/externs/shaka/player.js +++ b/externs/shaka/player.js @@ -1246,11 +1246,17 @@ shaka.extern.MediaSourceConfiguration; /** - * @typedef {Object} + * @typedef {{ + * customPlayheadTracker: boolean + * }} * * @description * Ads configuration. * + * @property {boolean} customPlayheadTracker + * If this is true, we create a custom playhead tracker for + * Client Side. This value defaults to false. + * * @exportDoc */ shaka.extern.AdsConfiguration; diff --git a/lib/ads/client_side_ad_manager.js b/lib/ads/client_side_ad_manager.js index 321f644588..056a295411 100644 --- a/lib/ads/client_side_ad_manager.js +++ b/lib/ads/client_side_ad_manager.js @@ -188,8 +188,37 @@ shaka.ads.ClientSideAdManager = class { this.onEvent_(new shaka.util.FakeEvent(shaka.ads.AdManager.ADS_LOADED, (new Map()).set('loadTime', loadTime))); - this.imaAdsManager_ = e.getAdsManager(this.video_, - this.adsRenderingSettings_); + if (!this.config_.customPlayheadTracker) { + this.imaAdsManager_ = e.getAdsManager(this.video_, + this.adsRenderingSettings_); + } else { + const videoPlayHead = { + currentTime: this.video_.currentTime, + }; + + this.imaAdsManager_ = e.getAdsManager(videoPlayHead, + this.adsRenderingSettings_); + + if (this.video_.muted) { + this.imaAdsManager_.setVolume(0); + } else { + this.imaAdsManager_.setVolume(this.video_.volume); + } + + this.eventManager_.listen(this.video_, 'timeupdate', () => { + if (!this.video_.duration) { + return; + } + videoPlayHead.currentTime = this.video_.currentTime; + }); + this.eventManager_.listen(this.video_, 'volumechange', () => { + if (this.video_.muted) { + this.imaAdsManager_.setVolume(0); + } else { + this.imaAdsManager_.setVolume(this.video_.volume); + } + }); + } this.onEvent_(new shaka.util.FakeEvent( shaka.ads.AdManager.IMA_AD_MANAGER_LOADED, diff --git a/lib/util/player_configuration.js b/lib/util/player_configuration.js index 6233a9349e..d1a1696ec1 100644 --- a/lib/util/player_configuration.js +++ b/lib/util/player_configuration.js @@ -312,7 +312,9 @@ shaka.util.PlayerConfiguration = class { forceTransmux: false, }; - const ads = {}; + const ads = { + customPlayheadTracker: false, + }; const AutoShowText = shaka.config.AutoShowText; From 653a19a61c5c08dc7d9d6b66453378d31d016b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?A=CC=81lvaro=20Velad=20Galva=CC=81n?= Date: Tue, 29 Aug 2023 09:09:24 +0200 Subject: [PATCH 2/2] Update comment --- externs/shaka/player.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/externs/shaka/player.js b/externs/shaka/player.js index 7602122fe9..2d6d79b6ba 100644 --- a/externs/shaka/player.js +++ b/externs/shaka/player.js @@ -1255,7 +1255,9 @@ shaka.extern.MediaSourceConfiguration; * * @property {boolean} customPlayheadTracker * If this is true, we create a custom playhead tracker for - * Client Side. This value defaults to false. + * Client Side. This is useful because it allows you to implement the use of + * IMA on platforms that do not support multiple video elements. + * This value defaults to false. * * @exportDoc */