První pojišťovna platí čtení mamografu počítačem. Lékaře to ale nenahradí

24. 4. 2023

Sdílet

Autor: Depositphotos
Umělá inteligence proniká do zdravotnictví v čím dál větší míře a reagují na to i zdravotní pojišťovny. Poté, co začaly diabetologům hradit vyšetření očí pomocí speciálního softwaru, oznámila Oborová zdravotní pojišťovna úhradu mamografického čtení snímků pomocí počítače. Jde o tzv. třetí čtení a v rutinní praxi ho nabízí zatím jediná klinika v Česku.

Unikátní vyšetření nabízí Mamodiagnostické centrum v Praze na Waltrovce spadající pod zdravotnickou skupinu EUC. Jde o mamografickou prohlídku s rozšířeným vyhodnocením snímků pomocí tzv. umělé inteligence (AI). 

Standardně se při screeningu nádorů prsu uplatňuje tzv. dvojí čtení, kdy snímky nezávisle na sobě vyhodnocují dva lékaři – radiologové, specialisté na zobrazování prsu.

AI zvýší senzitivitu vyšetření až o 20 procent

„K tomu se dnes přidává ještě umělá inteligence, jejíž závěr představuje cennou informaci pro rozhodnutí lékařů: jestli je žena zdravá, či má na mamografických snímcích změny, které by mohly být projevem zhoubného nádoru. Je to tedy v podstatě takové další dodatečné (třetí) čtení,“ uvedl pro server Vitalia.cz profesor Jan Daneš, předseda Komise pro program screeningu karcinomu prsu v ČR a člen Odborné rady zdravotnické skupiny EUC. Toto zapojení umělé inteligence zvyšuje celkovou senzitivitu vyšetření až o 20 procent.

Od 1. dubna tohoto roku navíc tuto proceduru pacientkám hradí Oborová zdravotní pojišťovna (OZP). „Včasný nález nádoru prsu zvyšuje pravděpodobnost vyléčení u pacientek až o 95 procent. I proto jsme pevně přesvědčeni, že preventivní prohlídky by měly být dostupné všem ženám. Zároveň stále hledáme nové cesty, jak dostupnou nabídku procedur zefektivňovat. Z tohoto hlediska je pro nás podpora vyšetření s využitím umělé inteligence logickým krokem při rozvíjení zdravotnických služeb budoucnosti,“ řekl Radovan Kouřil, generální ředitel OZP.

Budou AI v mamografii hradit i další pojišťovny? 

„Hledá se optimální systém úhrady do budoucnosti. V dohadovacím řízení k úhradám v roce 2024 je navržena pro uživatele systémů určitá bonifikace. Pokud to bude schváleno, bude využití AI pro všechny ženy bezplatné, tedy hrazeno všemi zdravotními pojišťovnami. Pracujeme i s jinými modely, například s příspěvkem pro klientky z fondu prevence zdravotních pojišťoven, podobně jako je například u preventivní sonografie prováděné u mladých žen,“ uvedl profesor Jan Daneš.

Snímek čtou lékaři, až pak software

Samotných pacientek se úkon nijak nedotýká, nepředstavuje pro ně žádnou zátěž. Jen by měly získat větší jistotu ohledně výsledku. „Nejprve je provedena mamografie standardním způsobem. Ihned poté následuje vyhodnocení speciálním softwarem s umělou inteligencí. Během pár minut mají lékaři k dispozici mamografický snímek, kde jsou označena podezřelá místa a vyjádření jejich individuálního skóre rizikovosti. Na jeho základě mohou lékaři mnohem lépe ověřit, zda se jedná o nádor, nebo jen nevýznamnou změnu,“ popsal profesor Daneš.

Důležité je podotknout, že lékaři kontrolují vyhodnocení softwarem až poté, co snímek sami zhodnotí. Neměl by je proto nijak předem ovlivnit a snížit jejich koncentraci. Daneš ubezpečuje, že AI především dodává jistotu.

„Například v případě, že systém určí nízké riziko, je extrémně nízká pravděpodobnost nádoru. Pak lékaři nemusí provádět doplňující vyšetření, zejména sonografii. AI tak i šetří prostředky zdravotního pojištění. Naproti tomu v případě, že AI ukáže vysoce podezřelé místo, je tento výsledek návodem k podrobnějšímu zhodnocení oblasti všemi dostupnými metodami,“ přiblížil.

Mýty a fakta o mamografii: Kde je pravda? Přečtěte si také:

Mýty a fakta o mamografii: Kde je pravda?

Systémy pro hodnocení mamografických snímků umělou inteligencí zkoušelo více screeningových pracovišť v Česku, nicméně v rutinní praxi je zatím používá jen zmíněné centrum Waltrovka. „Před tím jsme programy testovali a hledali ten, který splňuje všechny podmínky a zároveň vyhovuje našim lékařům. Také jsme instalaci připravovali a přizpůsobovali jsme systémy pro prohlížení snímků tak, aby práce s AI byla pro lékaře co možná nejjednodušší. Vždy trvá určitou dobu, než se lékaři naučí se systémem pracovat,“ řekl profesor Daneš.

Kdy má žena nárok na mamograf?

Podle vyhlášky Ministerstva zdravotnictví ČR má na bezplatnou preventivní (screeningovou) mamografii nárok každá žena od 45. roku věku, a to ve dvouletých intervalech. Podmínkou je žádanka od ambulantního gynekologa či praktického lékaře.

Při vyšším riziku vzniku nádorů prsu, například při výskytu nádoru prsu či vaječníků v rodině, je vhodné dle genetického doporučení provádět mamografii každoročně a od mladšího věku.

Mladší žena může jako samoplátkyně podstoupit sonografické vyšetření prsu. Většina pojišťoven pak na vyšetření přispívá.

Lékařka: AI je dobrý sluha, ale zlý pán

Nadšení z využití AI v praxi lehce mírní doktorka Regina Šírová, ředitelka Mammacenter skupiny Medicon. Umělá inteligence podle ní může být dobrý sluha, ale i zlý pán. A pacientky i odborníky zbytečně vystresovat.

„Obecně lze říci, že kombinace AI a dvou radiologů ukazuje nejlepší výsledky. Podstatné ale je, že rozdíl není nikterak zásadní. Toto však je jeden aspekt. Na jedné straně je tedy zjištění určité diskrétní abnormality, která může být projevem rakoviny prsu, a kterou tedy teoreticky nezaznamenáme my radiologové, ale AI ano, ale to neznamená, že jde hned o rakovinu prsu – proces teprve začíná. Zachycenou abnormalitu je potřeba dále analyzovat, tzv. dovyšetřit, a zde hraje největší roli zkušenost nás radiologů (mamodiagnostiků) při současném využití moderní technologie. Tu dnes představuje především 3D mamografie (tzv. tomosyntéza). Právě tato funkcionalita pomůže, díky zobrazení prsní tkáně v jednotlivých vrstvách, buď malý nádor v prsu najít a potvrdit, nebo naopak vyloučit,“ sdělila serveru Vitalia.cz.

Využití AI tak podle ní může v určitém směru zvýšit tzv. falešnou pozitivitu vyšetření. To znamená, že ukáže na abnormalitu, která nakonec žádným nádorem není. „A to naopak může stres jak pacientek, tak nás odborníků lehce zvyšovat,“ poznamenala radiodiagnostička.

AI lékaře v nejbližší době nenahradí

Jako nejlepší řešení se tak podle Šírové jeví v prvé řadě zmíněné využití 3D mamografie. „Domnívám se, že role AI bez využívání 3D mamografie je neúplná, lépe řečeno poloviční. Totiž v případě, že skutečně AI zachytí něco, co nezachytíme my, napomůže 3D mamografie a opět v kombinaci s AI a našimi zkušenostmi diagnózu stanovit. Bohužel, na rozdíl od vyspělých zemí, je tato metoda v ČR standardně využívána jen na nemnoha pracovištích a není dosud hrazená zdravotními pojišťovnami, ačkoliv se o jejím přínosu pro screening rakoviny prsu ví již řadu let,“ dodala lékařka.

Rakovina prsu v ČR

V ČR je ročně diagnostikováno kolem 7000 nových případů rakoviny prsu. Pravidelné mamografické vyšetřování žen v kombinaci s moderní onkochirurgickou léčbou snižuje úmrtnost na rakovinu prsu o 35 až 40 procent, protože jen včas odhalený zhoubný nádor je dobře léčitelný.

Že by se v dohledné době vyhodnocování mamografických snímků obešlo zcela bez lékařů, se rozhodně nestane. „I nadále má rozhodující slovo radiolog, nikoliv AI, a záleží tedy na každém z nás, jak zodpovědně s informací, kterou nám AI poskytuje, naložíme, Zároveň se domnívám, že pouze v rukou zkušených odborníků najde AI své využití správným způsobem,“ podotkla Šírová.

V současnosti ostatně platí evropská doporučení o využívání AI ve screeningu, ale pouze jako podpora dvojího čtení dvěma specializovanými radiology, nikoliv jako jejich náhrada. Definitivní doporučení, na které podle Danešových slov čekala i pražská klinika, vydala Evropská komise v lednu 2022.

Autor článku

Redaktorka serveru Vitalia.cz. Zaměřuje se především na zdravý životní styl, pohyb a zdraví dětí. Mimo novinařinu pracuje také jako lektorka pohybových kurzů pro děti a rodiče.

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