Leoš Kyša: První recenzi na moji knihu o AI napsala umělá inteligence

17. 3. 2025
Doba čtení: 28 minut

Sdílet

Autor: Internet Info, vlastní foto
Dokáže AI napsat stejně dobrý román jako člověk? Bude to někdo číst? A sehraje umělá inteligence v našich životech spíš roli klaďase, nebo záporáka? Se spisovatelem sci-fi jsme mluvili o AI, psaní i budoucnosti.

AI sehraje v našich životech pozitivní roli, věří spisovatel Leoš Kyša. Bez ní se nám nepodaří vyřešit třeba problémy spojené s nepříznivým demografickým vývojem naší společnosti, vysvětluje autor píšící také pod pseudonymem František Kotleta, který se umělou inteligencí zaobírá ve své loňské knize Syndikát.

„Moji studenti budou žít ve světě, kdy jim bude 50 let a každý bude živit čtyři důchodce. A za současných technologických podmínek by to nezvládli. Narazili bychom do útesu,“ popisuje svou představu role AI v budoucnosti.

Má podle něj používání AI také nějaká rizika? Jak se dnešní velké jazykové modely dají využít při psaní knih? Proč Kyša přestal na obálkách svých knížek používat obrázky vygenerované AI? A co říká na spory kolem využívání knih k trénování umělé inteligence? 

Rozhovor s Leošem Kyšou si můžete poslechnout ve formě podcastu na svých oblíbených podcastových službách nebo přímo zde:

Nabízíme vám také přepis části podcastového rozhovoru do textu. Podporovatelé Lupa.cz zde mají k dispozici kompletní přepis (využíváme k němu AI služby Whisper a Claude, text je poté redakčně upraven).

Outstream Placeholder

„Tohle není sci-fi, to je příběh, co se stane.“ Nebo: „Příběh z budoucnosti tak blízké, že než knihu dočtete, určitě se stane.“ To jsou věty z anotace na knihu Syndikát, která vyšla v loňském roce. My o ní budeme dnes mluvit, ale nebude to úplně jednoduché, protože se pokusím neprozrazovat nic podstatného z jejího děje. Když tak mě hlídejte. Na začátek ale asi můžu prozradit, že kniha je o umělé inteligenci.

Ano.

Dobře. Co ještě můžeme o Syndikátu bez spoilování říct?

Pro nás spisovatele science fiction je typické nebo symptomatické, že vymýšlíme alternativní scénáře. Vymýšlíme scénáře alternativních realit, alternativních světů, alternativní historie a také vymýšlíme scénáře budoucnosti. Syndikát je moje snaha predikovat, co bude za tři roky v oblasti umělé inteligence. Protože jsem samozřejmě autor žánrové literatury a miluju akční a dobrodružné příběhy, vyprávím to způsobem dobrodružného kriminálního románu. Všechno se přitom motá kolem toho, co bude za tři roky, jaké věci se můžou stát a co nás může za ty tři roky třeba potkat.

Tři roky nejsou moc dlouhá doba. Je tahle lhůta daná tím, že vývoj AI jde hrozně rychle dopředu?

My jako spisovatelé sci-fi milujeme, když to je třeba za dvacet, za třicet, za padesát let, protože realita, kterou konstruujeme, je pak zajímavější a zábavnější. Napsal jsem román Underground třeba z roku 2100. Jenomže u umělé inteligence jste za dva, tři roky v úplně jiném světě. Všichni to známe: co jsme před třemi lety o umělé inteligenci věděli? Co umělá inteligence před třemi lety dokázala? Spousta lidí se smála a říkala: tohle má být gamechanger? Vždyť je to úplně pitomé! 

Myslím, že i já jsem se před třemi lety na umělou inteligenci díval skrz prsty. Najednou uplyne rok a vy si říkáte, to je neuvěřitelné, co umělá inteligence dokáže. Tři roky jsou v umělé inteligenci to, co v jakékoliv jiné oblasti deset let. Je to strašně rychlé, neuvěřitelné, všichni, kterých se nás to aspoň trochu dotýká, se musíme o tu věc zajímat a sledovat, co se děje, když tam si dáte měsíc šlofíka, ujede vám vlak.

Pravda je, že vývoj je opravdu hodně překotný. Co vlastně všechno jste o AI před psaním Syndikátu věděl a co jste třeba musel nastudovat? Viděl jsem, že v knize jmenujete odborné poradce, kteří vám při psaní knihy pomáhali nebo radili.

Mám výhodu, že jako bývalý novinář znám spoustu lidí, kteří se zabývají byznysem a vědou. A tím, že dělám popularizaci vědy, samozřejmě narážím na spoustu úžasných lidí a neustále se s nimi o těch věcech bavím. Umělá inteligence je téma, které se v mém podcastu Jadrná věda točí pořád dokola. Každé tři měsíce musíme natočit nový díl o umělé inteligenci, protože každé tři měsíce už je všechno jinak. 

Takže to je první základ. Druhý je, že jsem se nadrzo ptal lidí: píšu knihu, potřebuji se o tom s tebou pobavit, myslíš si, že tohle dává smysl, myslíš si, že to bude fungovat? Mimo jiné jsem v knížce poděkoval známému byznysmenovi Václavu Dejčmarovi, který investuje do umělé inteligence a to téma je mu blízké. Dalším byl Honza Tyl, který dělal třeba DigiHavla a který je vizionář, hrozný blázen do umělé inteligence a taky trochu cvok, protože já se s normálníma lidma nebavím. Pomohl mi v podstatě vytvořit zápletku. 

Pořád jsem je chudáky otravoval, ptal jsem se jich: dává to smysl? Může to tak být? Co tohle? A co tohle? Samozřejmě jsem chtěl, aby si knihu také přečetli a Honza Tyl ji nechal otestovat umělou inteligencí, aby nám řekla, jestli jsem někde neudělal chybu. Chtěl jsem, aby to dávalo smysl. Je to budoucnost, která je prostě možná.

Museli vás tito odborníci, s kterými jste mluvil, ve vašich nápadech spíš brzdit, nebo naopak jste naopak držel při zemi a oni vám říkali, že příběh může být ještě daleko šílenější nebo daleko rozvinutější?

Držel jsem se spíš při zemi. Tím, jak jsem dělal novinařinu a stýkám se s odborníky, uvědomuji si, jak je moje znalost povrchní. Takže jsem odborníky opravdu až obsedantně obtěžoval s tím: a co tato věta? Dává smysl? A není to moc? Naopak oni mi říkali svoje vize a svoje nápady a pomáhali mi ty věci udělat šílenější, než jsem si sám myslel, což pro mě bylo hrozně fajn. A pak mě Václav Dejčmar donutil přepsat konec, což bylo, myslím, skvělé. Některým lidem vadí, což je zajímavé a já vím proč. Jiní jsou z něj zase nadšení, ale to už tak s knihami bývá.

To je zajímavá situace, že se autor sci-fi drží při zemi a odborníci na AI nebo lidé, kteří s tou technologií pracují, mu říkají „ještě přidej, ještě přidej, ještě to může být daleko šílenější“.

To je na tom děsivé. Přestože jsem schopen v knihách psát různé šílenosti a vymýšlet bláznivé mimozemské rasy a bláznivé situace, u Syndikátu se mi stalo to, že jsem se instinktivně držel při zemi, abych moc neustřelil, protože jsem opravdu chtěl být realistický, ale narážel jsem na to, že mi odborníci říkali: jestli chceš být realistický, tak se ale nesmíš tolik držet při zemi.

Říkal jste, že tu knihu i nějaká umělá inteligence posuzovala. Předpokládám, že to byl nějaký chatbot. Jaká byla jeho reakce?

Šlo o umělou inteligenci vytvořenou Honzou Tylem, takže to byl některý z jeho umělých minionů. Takže vlastně první recenzi napsala umělá inteligence. Honza říká, že má IQ asi 180, tak jsem jí celkem věřil (smích).

A pochválila vás?

Líbilo se jí to. Jinak bychom to nevydali, kdyby to neschválila (smích).

Dobře, takže nám tady vzniká nový žánr knih psaných pro umělou inteligenci. Tím se také docela zásadně rozšiřuje počet čtenářů…

Teď ještě donutit umělou inteligenci platit a myslím si, že to zachrání knižní trh (smích).

Lupa píše o technologiích, takže se budu hodně ptát na technologie. Používáte při psaní knížek nějaké technologické pomůcky? A teď nemyslím AI chatboty, k těm bych se rád dostal později. Samozřejmě předpokládám, že píšete na počítači, a ne rukou, ale máte jiné technologické pomůcky, které používáte při psaní?

No, používám umělou inteligenci.

Říkal jsem si, jestli si třeba, nevím, nenahráváte myšlenky na nějaké…

Ne, ale mám mozek propojený s klávesnicí. Na počátku 90. let jsem studoval obchodní akademii a profesorka Tohnová nás pomocí velmi prvorepublikových metod učila psát všemi deseti, takže mám nějakých 260 čistých úhozů za minutu. Za ty roky, co jsem psal články, se mi nějakým způsobem propojil mozek s klávesnicí.

Jednou jsem běhal na LARPu a spadl jsem ze skály a zlomil jsem si ruku, až mi vylezly z levé ruky kosti. A protože jsem měl rozepsaný rukopis, zkoušel jsem ho jedné kamarádce diktovat. Tu knihu jsem celkem dodělal, ale je to do dneška moje nejhorší kniha. Nebudu ji schválně jmenovat. Potom jsem ji upravoval a nebylo to špatné. Třeba Hašek, když už byl nemocný, diktoval konec Švejka, ale když jsem to zkusil já, nebylo to ono. Můj mozek je prostě spojený s klávesnicí a já už skrze ni uvažuju a lépe přes ni formuluju myšlenky.

Moje žena Kristýna Sněgoňová se třeba na něco zeptá a já to nemůžu říct, musím to napsat a pak jí to přečtu. Mozek mi opravdu funguje skrze klávesnici, v podstatě skrze automatické psaní. Jsem úplně propojený s notebookem a naživo se vyjadřuju hůř. Psát, tvořit příběh je pro mě přirozené, ale musím ťukat.

Svého času se hodně debatovalo o tom, nakolik psaní na klávesnici ovlivňuje mozek. A že psaní rukou, které si možná někteří z našich posluchačů ještě pamatují, je kreativnější, že se při něm aktivují jiné části mozku. Ale vy už máte tedy mozek upgradovaný na klávesnici.

Navíc mám problém, že jsem dysgrafik. Klávesnice mi texty opraví a pak mi pomůže i redaktorka. Ale když píšu rukou, často to sám po sobě nepřečtu. Něco si napíšu do diáře, velice často navíc špatně, takže to má být ve čtvrtek, ale já to napíšu do úterka, a pak zjistím, že mám najednou tři akce… 

Často se mi stává, že vyfotím, co jsem do diáře napsal, a posílám to Kristýně a říkám, prosím tě, nevíš, co jsem si tam napsal? Cokoliv napsat rukou je pro mě opravdu veliký problém. Na obchodní akademii jsem dokonce psal těsnopisem a paradoxně občas těsnopis po sobě přečtu líp, než když píšu normálně. Ale těsnopis už si určitě nikdo nepamatuje (smích). My jsme tady tak staří, že jsme ještě psali těsnopisem, v Opavě jsme byli hodně pozadu, takže jsem opravdu ještě v roce 1995 skládal zkoušky z těsnopisu.

To je krásné. Mě už tedy těsnopis minul a přešel jsem rovnou na elektrické psací stroje a pak už samozřejmě na počítač.

To bylo taky vtipné. Elektrické psací stroje nám na obchodní akademii přivezli jako velkou novinku, používali jsme je asi rok a pak už jsme měli počítač. Elektrické psací stroje byly super, ale šlo o naprosto mrtvou vývojovou větev.

MM Influenceři

Mluvil jste o tom, že při psaní používáte nějaké AI nástroje, takže se samozřejmě nabízí jednoznačná provokativní otázka: jakou část Syndikátu jste napsal vy a jakou AI chatbot?

99,99 procenta jsem napsal já. Nepoužívám AI pro psaní textu. Zkoušel jsem s tím různě experimentovat, testoval jsem asi deset různých umělých inteligencí, a akorát mě to štvalo a zdržovalo. Tím, jak v hlavě vytvářím příběh, jak plynule vychází z podvědomí a vědomí přes klávesnici do obrazovky a do paměti počítače, jde mi to velmi snadno. Ale umělá inteligence nezná moje podvědomí a neví, kam mířím, takže mi pořád nabízela možnosti, které jsem nechtěl. Chovala se jako hospodský povaleč, který sedí a dává mi rady, o které vůbec nemám zájem. 

Přepis podcastu je dostupný pouze našim podporovatelům

Můžete se jím stát i vy. Získáte tak nejen přístup k přepisům všech našich podcastů, ale také Lupu bez bannerů, newsletter o zákulisí českého internetu a další výhody.

Seriál: Rozhovory
Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


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 »