Hra o 5G kmitočty vrcholí. Může z ní vzejít ČEZký Telecom

3. 7. 2020
Doba čtení: 6 minut

Sdílet

Autor: DepositPhotos
V sobotu 4. července končí lhůta na podání připomínek k podmínkám aukce tzv. 5G kmitočtů. Za uplynulý rok jde už o jejich třetí variantu. Tato odvolává to, co ČTÚ odvolal ve variantě číslo dvě. Titul „telekomunikační Kocourkov roku“ má Česko jistý.

Zdálo se, že nejabsurdnější moment si novodobé tuzemské telekomunikace prožily v roce 2013, když tehdejší předseda Rady Českého telekomunikačního úřadu (ČTÚ) Pavel Dvořák zrušil probíhající aukci LTE kmitočtů s překvapivým zdůvodněním, že operátoři nabízejí za kmitočty příliš moc peněz. Jenže současný tanec kolem aukce 5G kmitočtů má všechny předpoklady vysoce nastavenou laťku bez větší námahy přeskočit.

Ještě před rokem to vypadalo, že je vše na dobré cestě – ČTÚ vydal ke konzultaci návrh podmínek, který podporoval vstup nového operátora jeho zvýhodněním v celoplošném pásmu 700 MHz. Pak se do aukce vložil ministr průmyslu a obchodu Karel Havlíček, který postupně několikrát změnil své vysvětlení toho, co mu na podmínkách vadí, aby na konci letošního ledna zorganizoval dramatický (ale právně zpackaný) pokus o odvolání šéfa Rady ČTÚ Jaromíra Nováka. Ten nakonec kvůli tlaku raději sám rezignoval.

Návrh podmínek číslo 2, se kterým v březnu přišla nová šéfka Rady Hana Továrková, podporu silného nového hráče vypustil a frekvenci 700 MHz v podstatě přenechal stávající mobilní trojce, přičemž se soustředil na zvýhodnění menších operátorů, kteří mají zájem o pásmo 3500 MHz. Navíc se zde objevil návrh vyčlenit 40 MHz pro průmyslové podniky. Šlo o nápad tak nepromyšlený, že nemohl pocházet odjinud než z ministerstva průmyslu. Podniky jako Siemens a Škoda Auto pak do připomínek ochotně psaly, jak vyčlenění podporují – i když o konkrétním provozování sítí či jejich využití měly jen velmi mlhavé představy. Pro ilustraci: nejkonkrétnější informaci o možném použití 5G, kterou jsem dostal ze Škodovky, bylo „v současné době se připravují Use Cases v rámci koncernu Volkswagen“.

Jenže v červnu ČTÚ opět překvapil. Veřejnou konzultaci k návrhu číslo 2 zrušil s tím, že se nebude k připomínkám vůbec vyjadřovat. Na jednu stranu se nebylo co divit – úřadu se totiž povedlo téměř celý trh sjednotit v názoru, že je návrh číslo 2 strašlivě špatný (i když se důvody jednotlivých hráčů samozřejmě výrazně lišily). ČTÚ zároveň vydal návrh číslo 3, do kterého se – světě div se – vrátilo vyhrazení části kmitočtů v pásmu 700 MHz pro nového hráče. Moc práce to asi nedalo – dotyčné pasáže jsou v návrhu číslo 3 často doslova stejné jako v dříve zatracovaném návrhu číslo 1 (jen třeba místo „Nového operátora“ se mluví o „zájemcích, kteří nejsou Stávajícími operátory“). Zároveň v návrhu zůstala podpora menších operátorů, kteří by uspěli v pásmu 3500 MHz  hlavně jejich nárok na národní roaming v pásmu 700 MHz. A kupodivu vypadl nápad na vyčlenění 40 MHz pro průmysl (nahradil jej rozumnější závazek velkoobchodní nabídky pro průmyslové využití sítí).

Proč ČTÚ (potažmo ministerstvo průmyslu) najednou prosazuje dříve zavrženou podporu nového hráče v pásmu 700 MHz? Hana Továrková oficiálně říká, že zájem o aukci projevil „významný počet subjektů, které mají potenciální zájem o získání rádiových kmitočtů v pásmu 700 MHz s cílem stát se celoplošným novým operátorem“. Konkrétně má jít o Nordic Telecom, České Radiokomunikace, Sazku či ČEZ. Jenže: o zájmu těchto firem se ví už dlouho a účastnily se i předchozí veřejné konzultace v létě 2019. Měly sice k návrhu číslo 1 méně připomínek než k návrhu číslo 2, ale to je vzhledem ke kvalitám „dvojky“ dost logické.

Jedinou výjimkou je ČEZ. Zástupci státního energetického obra do loňské veřejné konzultace ničím nepřispěli a zájem o 5G kmitočty poprvé veřejně zmínili v polovině března 2020, jen den poté, co ČTÚ zveřejnil svůj návrh číslo 2. Když se podíváme na připomínky ČEZu, zjistíme navíc, že jim ČTÚ v návrhu číslo 3 vyšel dost často vstříc: ať už jde o zrušení vyhrazení 40 MHz pro průmysl, umožnění odstoupení z aukce, pokud zájemce nezíská kmitočty jak v pásmu 700 MHz, tak v pásmu 3500 MHz (kromě toho ČEZ v připomínkách připomněl, že je nejlepší praxí v podobných aukcích také vyhrazení frekvencí pro nového operátora – takže vlastně taky úspěch) nebo o povinnost velkoobchodní nabídky v pásmu 3500 MHz. Podoba těchto připomínek s připomínkami, které zaslalo ministerstvo průmyslu a obchodu, asi nepřekvapí. V některých bodech ovšem (zatím) ČEZ neuspěl – chtěl třeba zavést spektrální limit napříč pásmy 700, 800 a 900 MHz (stejně jako ministerstvo průmyslu), uvolnit některá rozvojová kritéria nebo zavést možné vynucení sdílení sítě s jinými operátory, pokud by ti stávající s novým hráčem odmítli spolupracovat.

Vznikne ČEZký Telecom?

Dává ale vůbec smysl, aby se kýženým čtvrtým hráčem, který má rozhýbat český mobilní trh, stal právě polostátní ČEZ? Určité technologické předpoklady tady jsou: v telekomunikacích působí od roku 2013 prostřednictvím dceřinky ČEZ Prodej jako virtuální operátor v síti O2, který podle svých prohlášení provozuje asi 125 tisíc SIM karet. Kromě toho jeho další dceřiná firma Telco Pro Services staví páteřní optickou síť, která momentálně obsahuje přes 8500 km optických kabelů.


Autor: Telco Pro Services

Mapa optické sítě Telco Pro Services

Jenže na druhé straně ČEZ nemá s provozováním vlastní mobilní sítě žádné zkušenosti. Uznává to i šéf firmy Daniel Beneš, který v rozhovoru pro Seznam Zprávy řekl, že firma jedná o spojení s partnerem, který by přinesl potřebné know-how. ČEZ by tak kromě poskytnutí páteřní infrastruktury mohl působit zřejmě více méně jako investor, který zafinancuje miliardy korun potřebné pro výstavbu celoplošné sítě. Při 18miliardovém zisku jen za loňský rok si to nejspíš může dovolit – pokud tedy odhlédneme od plánovaných obřích investic do jaderných elektráren. Detaily o plánech ČEZu nejsou známy – jen doufám, že aspoň na ministerstvu financí existuje ekonomický rozbor toho, jestli dává vstup ČEZu do aukce smysl.

To je totiž podstatná otázka: proč by se měla polostátní firma, jejímž hlavním byznysem je energetika, pouštět do mnohamiliardového experimentu v mobilních sítích? Proč se najednou hrne do hry o celoplošného operátora, když o ni za obdobných podmínek (návrh číslo 1) neměl zájem žádný z velkých operátorů z ciziny – jak ještě na jaře, při odvolávání ex-šéfa Rady ČTÚ, tvrdil ministr Havlíček

MM Influenceři

Dojmu, že ČEZ jedná na politickou objednávku, se nejde ubránit. A pokud o ni skutečně jde, je to špatný důvod pro vstup do aukce. V důsledku může vést k tomu, že se polostátní firmě v boji se zavedenou trojkou operátorů nebude dařit a případné ztráty nakonec zaplatíme ve snížených příjmech státu nebo ve zvýšených cenách elektřiny. Riziko vstupu na mobilní trh by na sebe neměl z pochybných důvodů brát polostátní moloch, ale výhradně soukromá firma, která neinvestuje na úkor daňových poplatníků.

Budoucnost aukce 5G kmitočtů bude jasnější po 4. červenci, kdy končí lhůta pro podávání připomínek k návrhu číslo 3. Vzhledem k průtahům a evropskému závazku, že by Česko mělo kmitočty pro mobilní sítě uvolnit ještě v letošním roce (pásmo 700 MHz mělo být přiděleno dokonce do konce června), je to s největší pravděpodobností návrh poslední. I když – dosavadní kroky Havlíčkova úřadu a ČTÚ zaručují jen to, že se stát může ještě úplně cokoli.

Autor článku

Šéfredaktor Lupa.cz a externí spolupracovník Českého rozhlasu Plus. Dříve editor IHNED.cz, předtím Aktuálně.cz a Českého rozhlasu. Najdete mě na Twitteru nebo na LinkedIn

'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }
Upozorníme vás na články, které by vám neměly uniknout (maximálně 2x týdně).
'; document.getElementById('outstream-iframe').onload = function () { setupIframe(); } replayScreen = document.getElementById('iinfoOutstreamReplay'); iinfoOutstreamPosition = document.getElementById('iinfoOutstreamPosition'); outstreamContainer = document.getElementsByClassName('outstream-container')[0]; setupReplayScreen(); } function setupIframe() { outstreamDocument = document.getElementById('outstream-iframe').contentWindow.document; let el = outstreamDocument.createElement('style'); outstreamDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:-5px;right:25px}"; videoContent = outstreamDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; if ( location.href.indexOf('rejstriky.finance.cz') !== -1 || location.href.indexOf('finance-rejstrik') !== -1 || location.href.indexOf('firmy.euro.cz') !== -1 || location.href.indexOf('euro-rejstrik') !== -1 || location.href.indexOf('/rejstrik/') !== -1 || location.href.indexOf('/rejstrik-firem/') !== -1) { outstreamDirectPlayed = true; soundAllowed = true; iinfoVastUrlIndex = 0; } if (!outstreamDirectPlayed) { console.log('OUTSTREAM direct'); setUpIMA(true); } else { if (soundAllowed) { const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('OUTSTREAM sound allowed'); setUpIMA(false); }).catch(function () { console.log('OUTSTREAM sound forbidden'); renderBanner(); }); } } else { renderBanner(); } } } function getWrapper() { let articleWrapper = document.querySelector('.rs-outstream-placeholder'); // Outstream Placeholder from RedSys manipulation if (articleWrapper && articleWrapper.style.display !== 'block') { articleWrapper.innerHTML = ""; articleWrapper.style.display = 'block'; } // Don't render OutStream on homepages if (articleWrapper === null) { if (document.querySelector('body.p-index')) { return null; } } if (articleWrapper === null) { articleWrapper = document.getElementById('iinfo-outstream'); } if (articleWrapper === null) { articleWrapper = document.querySelector('.layout-main__content .detail__article p:nth-of-type(6)'); } if (articleWrapper === null) { // Euro, Autobible, Zdravi articleWrapper = document.querySelector('.o-article .o-article__text p:nth-of-type(6)'); } if (articleWrapper === null) { articleWrapper = document.getElementById('sidebar'); } if (!articleWrapper) { console.error("Outstream wrapper of article was not found."); } return articleWrapper; } function setupDimensions() { outstreamWidth = Math.min(iinfoOutstreamPosition.offsetWidth, 480); outstreamHeight = Math.min(iinfoOutstreamPosition.offsetHeight, 320); } /** * Sets up IMA ad display container, ads loader, and makes an ad request. */ function setUpIMA(direct) { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); if (direct) { adsRequest.adTagUrl = directVast; console.log('Outstream DIRECT CAMPAING advert: ' + directVast); videoContent.muted = true; videoContent.volume = 0; outstreamDirectPlayed = true; } else { adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Outstream advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; } // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = outstreamWidth; // adsRequest.linearAdSlotHeight = outstreamHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function setupReplayScreen() { replayScreen.addEventListener('click', function () { iinfoOutstreamPosition.remove(); iinfoVastUrlIndex = 0; outstreamInit(); }); } /** * Sets the 'adContainer' div as the IMA ad display container. */ function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. outstreamDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( outstreamDocument.getElementById('adContainer'), videoContent); } function unmuteAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); outstreamDocument.getElementById('adMuteBtn').innerHTML = ''; } } /** * Loads the video content and initializes IMA ad playback. */ function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(outstreamWidth, outstreamHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } /** * Handles the ad manager loading and sets ad event listeners. * @param { !google.ima.AdsManagerLoadedEvent } adsManagerLoadedEvent */ function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } /** * Handles actions taken in response to ad events. * @param { !google.ima.AdEvent } adEvent */ function onAdEvent(adEvent) { // Retrieve the ad from the event. Some events (for example, // ALL_ADS_COMPLETED) don't have ad object associated. const ad = adEvent.getAd(); console.log('Outstream event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: // This is the first event sent for an ad - it is possible to // determine whether the ad is a video ad or an overlay. if (!ad.isLinear()) { // Position AdDisplayContainer correctly for overlay. // Use ad.width and ad.height. videoContent.play(); } outstreamDocument.getElementById('adContainer').style.width = '100%'; outstreamDocument.getElementById('adContainer').style.maxWidth = '640px'; outstreamDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); // This event indicates the ad has started - the video player // can adjust the UI, for example display a pause button and // remaining time. if (ad.isLinear()) { // For a linear ad, a timer can be started to poll for // the remaining time. intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } outstreamDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (outstreamLastError === 303) { if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } } break; case google.ima.AdEvent.Type.COMPLETE: // This event indicates the ad has finished - the video player // can perform appropriate UI actions, such as removing the timer for // remaining time detection. if (ad.isLinear()) { clearInterval(intervalTimer); } if (isBanner) { renderBanner(); } else { replayScreen.style.display = 'flex'; } break; } } /** * Handles ad errors. * @param { !google.ima.AdErrorEvent } adErrorEvent */ function onAdError(adErrorEvent) { // Handle the error logging. console.log(adErrorEvent.getError()); outstreamLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { renderBanner(); } } function renderBanner() { if (isBanner) { console.log('Outstream: Render Banner'); iinfoOutstreamPosition.innerHTML = ""; iinfoOutstreamPosition.style.height = "330px"; iinfoOutstreamPosition.appendChild(bannerDiv); } else { console.log('Outstream: Banner is not set'); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoOutstreamPosition.remove(); outstreamInit(); } else { return false; } adVolume = 1; return true; } /** * Pauses video content and sets up ad UI. */ function onContentPauseRequested() { videoContent.pause(); // This function is where you should setup UI for showing ads (for example, // display ad timer countdown, disable seeking and more.) // setupUIForAds(); } /** * Resumes video content and removes ad UI. */ function onContentResumeRequested() { videoContent.play(); // This function is where you should ensure that your UI is ready // to play content. It is the responsibility of the Publisher to // implement this function when necessary. // setupUIForContent(); } function onActiveView() { if (outstreamContainer) { const containerOffset = outstreamContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (outstreamPaused) { adsManager.resume(); outstreamPaused = false; } return true; } else { if (!outstreamPaused) { adsManager.pause(); outstreamPaused = true; } } } return false; } let outstreamInitInterval; if (typeof cpexPackage !== "undefined") { outstreamInitInterval = setInterval(tryToInitializeOutstream, 100); } else { const wrapper = getWrapper(); if (wrapper) { let outstreamInitialized = false; window.addEventListener('scroll', () => { if (!outstreamInitialized) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { outstreamInit(); outstreamInitialized = true; } } }); } } function tryToInitializeOutstream() { const wrapper = getWrapper(); if (wrapper) { const containerOffset = wrapper.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight / 1 && containerOffset.bottom > 0.0) { if (cpexPackage.adserver.displayed) { clearInterval(outstreamInitInterval); outstreamInit(); } } } else { clearInterval(outstreamInitInterval); } } }
OSZAR »