Operátoři o DAB+: Musíme vydržet první roky a doufat v rozvoj digitálního rádia

9. 6. 2025
Doba čtení: 7 minut

Sdílet

Posluchačka, rádio, DAB+, hudba, sluchátka, audio
Autor: Filip Rožánek, Internet Info s použitím Google Gemini
Zavedená rádia chystají nové stanice pro digitální vysílání. Nedělají to kvůli nadšení z DAB+, ale spíš kvůli strategii. Malá rádia trápí vysoké poplatky.

Rok a půl po rozdělení kmitočtů na DAB+ na českém trhu stále převažuje počet sítí nad počtem digitálně šířených stanic. Některá rádia využívají služby víc operátorů. Boom nových projektů se dosud nekoná a například čistě digitální stanici Radio Energic převezme operátor Fiera Touch. Na obzoru jsou klony zavedených komerčních rádií, které mají velkým mediálním skupinám posloužit jako strategické jištění prostoru na další distribuční platformě.

„Velké mediální domy mají výhodu v odbornosti a znalosti trhu. Spolupráce s našimi stávajícími zákazníky, kterým zajišťujeme FM distribuci, byla přirozená volba. Ukázalo se, že to byla správná strategie. Vědí, jaký obsah nabídnout a umí připravit kvalitní program. Zároveň nás ale kontaktují i úplně noví zájemci o vstup na trh. Pro ně je to samozřejmě těžší,“ řekl na konferenci Digimedia 2025 Marcel Procházka z Českých Radiokomunikací.

Právě tento operátor získal do své celoplošné sítě nejposlouchanější stanice a další začne šířit v dohledné době. Budou to čtyři programy společnosti Media Bohemia.

„Poměrně dlouho jsme zvažovali, jak se k DAB+ postavit. Hlavní problém, který u něj vidíme, je, že je to pořád jen jiná forma lineární, jednosměrné distribuce. Neposouvá nás to dál, pokud jde o zlepšení způsobu prodeje. Přesto si myslíme, že DAB+ má na trhu své místo,“ vysvětlil manažer Media Bohemia Jan Neuman.

Společnost zaujala možnost dosáhnout celoplošného pokrytí, rozvoj poslechu v autech a podobně. Na základě interní analýzy jsme se rozhodli, že ke každému z našich stávajících FM programů přidáme jeden nový, čistě digitální. Ale děláme to tak, že tyto programy zároveň šíříme přes stream a vytváříme inventory pro programatický prodej reklamy,“ objasnil Neuman.

České Radiokomunikace přidaly do své DAB+ sítě další rádia Přečtěte si také:

České Radiokomunikace přidaly do své DAB+ sítě další rádia

V jeho očích je DAB+ už zastaralá technologie, zvlášť ve srovnání s možnostmi, kterými při analýze posluchačů disponuje internetová distribuce. 

„Máme čtyři stávající produkty: Fajn Radio, Rock Radio, Hitrádio a Blaník. Ke každému jsme vytvořili jednoho ‚DABového sourozence‘. Ale ne primárně kvůli DAB+. Jde o snahu udržet si posluchačské portfolio. Průměrný posluchač v Česku denně ladí 2,6 stanice. A my víme, že naši posluchači občas přelaďují na Impuls a jeho posluchači k nám. Snažíme se těm našim nabídnout alternativu v rámci vlastního brandu, pokud mají možnost příjmu přes DAB+. Takže vždy jeden nový program ke stávajícímu – čtyři plus čtyři,“ popsal Neuman.

Těchto osm digitálně šířených stanic se rozdělí do dvou celoplošných sítí, které provozují České Radiokomunikace a plzeňská firma RTI CZ. 

„Dlouho jsme vyjednávali s oběma operátory, zejména o regionální struktuře. Naše skupina má velkou část příjmů z regionální reklamy, a bohužel současné nastavení multiplexů není pro soukromá rádia ideální – nejsme schopni odpojovat podle potřeb jednotlivých územních celků. Proto jsme vybírali operátora podle schopnosti cílit na regiony. Multiplex RTI je v tomhle ohledu specifický a lépe se hodí pro programy, kde je regionalita klíčová,“ zdůraznil Neuman.

Stanice se objeví v digitálním éteru zřejmě od července. Rada pro rozhlasové a televizní vysílání už obdržela žádosti o licence například pro kanály Český Blaník nebo Hitrádio 90. „Počítáme s tím, že v prvních čtrnácti dnech července spustíme vysílání v rámci těch osmi ‚celoplošných‘ okruhů. Během letních měsíců poběží testovací provoz. Od 1. září plánujeme další fázi a cílový stav je, že od 1. ledna budeme mít ve všech programech v obou multiplexech plně regionalizované vysílání,“ popsal zástupce Media Bohemia.

O digitální licence pro své stávající programy brzy požádá také Rádio Impuls, ke kterému patří ještě stanice RockZone a Český Impuls. V síti Českých Radiokomunikací jsou tyto programy sice už od konce dubna, po právní stránce to je ale převzaté vysílání. „Byly tu legislativní překážky, proto jsme zvolili toto řešení. Se zákazníky jsme dohodnutí, že jde o dočasný stav. Plánují si zažádat o vlastní digitální licence,“ řekl k tomu Marcel Procházka z Českých Radiokomunikací. Kromě toho vznikne už dříve potvrzený nový čistě digitální produkt Impulsu. Generální ředitel Jiří Hrabák připustil, že to bude „možná ještě v létě“.

Tereza Landová (Ochranná asociace zvukařů) a Jan Neuman (Media Bohemia)

Tereza Landová (Ochranná asociace zvukařů) a Jan Neuman (Media Bohemia) na konferenci Digimedia 2025

Autor: AČRA-MK/Jiří Matula

Jak utáhnout rozjezd

Jiným operátorům se klienti hledají hůř. „Jednání s novými rádii, která chtějí přejít z internetu na DAB+, se vždy točí kolem financí. Provoz je finančně náročný, ať už jde o vstup do sítě, nebo distribuční poplatky. Většina zájemců ale jako hlavní problém označuje autorské poplatky. Máme tři konkrétní případy, kdy jsme se s internetovými rádii dohodli na podmínkách. Po dvou až třech týdnech ale přišli s tím, že DAB+ pro ně není udržitelný. Nedokázali to finančně zvládnout už v rozjezdové fázi,“ přiblížil situaci Pavel Hájek ze společnosti Fiera Touch.

DAB+ nejsou jenom poplatky za šíření signálu, upozorňuje majitel malého rádia Přečtěte si také:

DAB+ nejsou jenom poplatky za šíření signálu, upozorňuje majitel malého rádia

„Říkáme otevřeně, že DAB+ je ve fázi rozjezdu. Pokud chceme, aby to fungovalo, musíme spolupracovat s provozovateli malých rozhlasových stanic a domluvit podmínky, které jsou pro ně přijatelné. Ale zároveň nesmí jít o dumping. Cena musí pokrýt alespoň náklady provozu sítě, plus případné investice. Zatím se nám daří s novými stanicemi domlouvat a síť rozvíjet. Výrazně nám pomáhá synergie s televizní infrastrukturou. Většinu vysílačů stavíme na lokalitách, kde už máme televizní vysílání, což přináší ekonomické výhody,“ dodal Pavel Hájek.

„Dvě regionální rádia uvažují o vstupu do DAB+. Ale celá debata se vždy točí kolem nákladů, zejména autorských poplatků. Vážně zvažují, jestli do toho jít, nebo ne,“ připustil.

Fiera Touch převezme prostřednictvím firmy Radio Content značku hudebního Rádia Energic. Původní koncesi současný provozovatel vrátí. „Cílová skupina je zajímavá a už teď se nám daří získávat klienty přes přímé kontakty. V tuto chvíli víme, že máme pokryté náklady na provoz zhruba na půl roku dopředu, což považuji za klíčové. Pokud uvidíme, že má smysl portfolio rozšířit, zvážíme to. Ale teď je prioritou dotáhnout Rádio Energic do úspěšného startu,“ zdůraznil Pavel Hájek. Rada pro rozhlasové a televizní vysílání by o udělení licence mohla rozhodnout na svém zasedání 17. června.

Proč je nutná nová licence? „Náš záměr je mít rádio plně pod kontrolou, vyvarovat se předchozích chyb a vrátit projekt na správnou kolej. Zároveň chceme mít volnost při úpravách obsahu a celkovém směřování stanice. A upřímně, mám rád, když jsou věci od začátku transparentní,“ vysvětlil Pavel Hájek.

Pro rádio využije některé formáty z vysílání svých televizních stanic TV R a i-Vysočina.cz. „Jsou to talk show a víme, že se dají přizpůsobit do rozhlasové podoby. Ale zároveň připravujeme i několik samostatných formátů jenom pro Energic, čistě rozhlasových. Rozhodně to nebude tak, že bychom vzali veškerý obsah, co máme, vyexportovali ho do audiostopy a pustili mezi písničkami. To by nefungovalo. Ale u formátů, kde to dává smysl – třeba u zpravodajství – víme, že jsme schopni ho doplnit citacemi, synchrony, které už máme k dispozici v televizi. A to jsou věci, které by začínající rádio samo těžko vyrábělo,“ popsal Hájek.

Hlavně vydržet

Složité je hledání klientů i pro tak zkušeného provozovatele vysílačů jako je příbramská společnost Teleko. „Ale nesnažíme se podbízet. Naším cílem je nabízet službu co nejefektivněji. Říkáme, že naše síť je chytrá a zdravá. Chytrá proto, že vysíláme z lokalit, které zákazníci opravdu potřebují. A zdravá proto, že ji budujeme postupně, v takovém tempu, jaké si naši klienti mohou dovolit,“ podotkl majitel firmy Tomáš Řapek.

„Zatím máme jen pár stanic, což je vlastně výhoda. Umožňuje nám přizpůsobit výběr lokalit jejich potřebám. Dovedu si představit, že s deseti klienty by to bylo výrazně složitější než se třemi, čtyřmi nebo pěti,“ dodal optimisticky.

Blíže neupřesněného klienta pro svou regionální síť získala firma Broadcast Services z mediální skupiny Pohoda. Dosud v ní šířila vlastní programy Radio Čas a Radio Čas Rock. Připravenou má také mutaci Radio Čas Rock Natvrdo, ta zatím vysílá na internetu. Jak na konferenci řekl zástupce operátora Roman Jeřábek, dalším klientem v digitální síti bude jedna z už existujících FM stanic. Distribuce začne v následujících týdnech.

CIF25 SE debata

„Před rokem jsem říkal, že DAB+ je pro mě dobrodružství a že ho budu moci hodnotit až po dvou letech. Takže mám ještě rok, než budu vědět, jak zábavné to vlastně je,“ glosoval situaci Pavel Hájek z Fiera Touch. V některých lokalitách jsou v jeho síti stanice, které přitom patří provozovateli další digitální sítě, Miroslavu Pýchovi. „V první řadě je to dohoda o tom, že se pokusíme společně přežít ten první rok a půl nebo dva roky a rozhýbat trh s DABem,“ vysvětlil Hájek. „Ale zatím to není součást žádné dlouhodobé strategie. Je to spíš o tom, že jsme si řekli, že není čas vymýšlet zbytečnosti, ale že to musíme prostě rozběhnout,“ doplnil.

„Chce to čas. Trvalo nám deset let, než jsme reálně rozjeli DAB+ od spuštění prvního vysílače pro Český rozhlas. U komerčních rádií to bude podobné. Trh teprve vzniká. Penetrace DAB+ přijímačů je zatím asi 20 %, což je málo. DAB+ si teď mohou dovolit jen silní hráči, pro které je to doplněk. Nové subjekty by na něm byly závislé, což je složité. Až se DAB+ rozšíří a přijímače budou běžnější, začne být tento typ vysílání zajímavý i pro nová rádia,“ věří Marcel Procházka z Českých Radiokomunikací.

  • Chcete mít Lupu bez bannerů?
  • Chcete dostávat speciální týdenní newsletter o zákulisí českého internetu?
  • Chcete mít k dispozici strojové přepisy podcastů?
  • Chcete získat slevu 1 000 Kč na jednu z našich konferencí?

Staňte se naším podporovatelem

Autor článku

Novinář se zaměřením na média. Dlouholetý účastník i pozorovatel českého mediálního cirkusu. Pracoval v Marketing & Media, Hospodářských novinách a Českém rozhlase.

'; 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 »