Bezdrátová sluchátka Huawei FreeBuds 5: odvážný tvar s vynikajícím zvukem (recenze)

Sdílet

 Autor: Cnews
Po dlouhé pauze se na pulty obchodů dostala nová generace sluchátek Huawei FreeBuds s číslovkou 5. Novinka přichází s vylepšeným ANC, hutnější basovou složkou a celkově lepším zvukem. Je tu však jedno velké ALE.

Obsah balení:

Mimo sluchátka s nabíjecím pouzdrem v balení najdete také přibližně 25cm USB-C/USB-A nabíjecí kabel, příručku rychlého spuštění, záruční kartu a v neposlední řadě dva páry silikonových návleků. Tyto návleky mají zvětšit objem sluchátek a pomoci v případě, kdy díky lesklému plastovému tělu sluchátka vypadávají z uší.

Obsah balení nových FreeBuds 5 nijak nepřekvapí, zároveň ani neurazí Obsah balení nových FreeBuds 5 nijak nepřekvapí (zdroj: Cnews)

Parametry:

Frekvenční rozsah: 16–40 000 Hz
Velikost měniče: 11 mm s dvojitými magnety
Připojení: Bluetooth 5.2 (podpora kodeků LDAC, AAC, SBC)
Kapacita baterie:
  • sluchátka: 42 mAh
  • pouzdro: 505 mAh
Nabíjení:
  • sluchátka: cca 20 minut
  • pouzdro: cca 40 minut (bezdrátově cca 240 minut)
Výdrž:
  • ANC zapnuto: 3,5 h + 20 h
  • ANC vypnuto: 5 h + 30 h
ANC: aktivní ANC, režim volání, dynamický EQ
Zvýšená odolnost: IP54
Funkce:
  • Hi-Res Audio
  • automatické pozastavení hudby
  • paralelní připojení ke 2 zařízením
  • podpora gest – přijmutí hovoru, přepínání mezi hudbou
Rozměry a hmotnost:
  • sluchátko: 32,4 × 17,6 × 22,8 mm; 5,4 g
  • pouzdro: 66,6 × 50,1 × 27,3 mm; 45 g

Vzhled:

Pokud bych měl říci, kde se Huawei na nových FreeBuds 5 nejvíce vyřádil, bude to bezesporu design. Zatímco předchozí generace se jakž takž držela léty nastaveného konvenčního designu, FreeBuds 5 na to jdou z opačného konce. Samotné pouzdro vypadá spíše jako zploštělé vajíčko doprovázené nápisem Huawei na výklopné části a signalizační diodou umístěnou vespod. Úplně vespod se nachází napájecí USB-C konektor, mimo to můžete sluchátka nabíjet také bezdrátově. Pochválit musím kvalitu a pevnost pantu, který nemá žádnou vůli a pevně spojuje obě části pouzdra.

A nyní k samotným sluchátkům. Ta prošla razantní změnou a jejich vzhled se slovy jen těžko popisuje. Jasné rysy nahradily ladné křivky, které by se daly nejlépe přirovnat k slze od náušnic či kapce vody stékávající z vrchní peckovité části. Ze strany Huawei je vidět jasná snaha odlišit se od konkurence. Podobně zvláštní tvar měly například i Galaxy Buds Live od Samsungu. V konečném důsledku je však na vás, zdali se vám nový design sluchátek líbí či nikoliv.

Tělo ochranného pouzdra je vyrobeno z matného plastu a plastové je i tělo sluchátek samotných. K dispozici jsou hned tři barevné varianty. Konzervativní bílou a stříbřitě černou doplňuje světle červená, až oranžová varianta. Na těle pouzdra se nachází mimo napájecí USB-C konektor pouze tlačítko pro aktivaci párování. Pochvalu zaslouží Huawei za zvýšenou odolnost IP54 a nízkou hmotnost samotných sluchátek po 5,4 g, potažmo 45 g v případě nabíjecího pouzdra.

Barevné varianty sluchátek Huawei FreeBuds 5 Barevné varianty sluchátek Huawei FreeBuds 5 (zdroj: Huawei)

Kvalita hudby:

Co se výsledného zvuku týče, byly pro mě Huawei FreeBuds 5 příjemným překvapením. Dvojice 11mm dynamických měničů s dvojitými magnety hraje na poměry malých pecek velmi kvalitně. Zvuk ze sluchátek je čistý a nechybí mu řádná dynamická složka. Sluchátka se navíc pyšní Hi-Res audiem a algoritmem DNN. Huawei nezapomnělo ani na řádnou podporu audio kodeků, konkrétně AAC a pro mnohé lepší LDAC s přenosovou rychlostí až 990 kbps.

Huawei dostal do každého sluchátka 11m dynamické měniče s dvojitými magnety Huawei dostal do každého sluchátka 11m dynamické měniče s dvojitými magnety (zdroj: Huawei)

Z další výbavy sluchátek se nabízí ultraširokoúhlý ekvalizér a funkce snižování odporu membrány při vibracích, čímž bylo dosaženo i v tak malém těle poměrně výrazných basů. I přestože fyzikální zákony nelze oklamat a takto malá sluchátka nebudou nikdy podávat stejné výsledky jako sluchátka náhlavní, je toto podle mého názoru správný krok k zlepšení kvality hudby u TRW sluchátek.

Aplikace a ANC:

Základní párování a ovládání sluchátek pomocí gest zvládnete i bez mobilní aplikace. Pro jakoukoliv další interakci je zapotřebí přítomnost mobilní aplikace AI life. Na App Store nebo v Google Play byste ji hledali marně. Aplikace se nachází pouze v obchodě s aplikacemi od Huawei. Nejdříve je nutné stáhnout obchod s aplikacemi Huawei a v něm následně stáhnout cílovou aplikaci AI Life.

Orientace v aplikaci AI Life je poměrně jednoduchá. Po vybrání sluchátek se dostanete do přehledného rozhraní s oválnými okny zobrazujícími stav baterie, nastavení ANC, efektů apod. Zajímavostí je nalezení sluchátek skrze mobilní aplikaci nebo nastavení vlastního zvukového efektu skrze vestavěný ekvalizér.

Skrze mobilní aplikaci můžete sluchátkům povolit vícenásobné připojení k až dvěma zařízením současně, nastavit ANC režim, vybrat některý z předdefinovaných hudebních režimů nebo si případně vytvořit vlastní. V aplikaci je také možné nastavit gesta a aktivovat detekci nošení (což doporučuji).

Sluchátka FreeBuds 5 disponují celkem 3 režimy potlačení hluku:

  • režim Obecné: ideální pro hlučná místa,
  • režim Příjemné: vhodný pro málo hlučná místa,
  • režim Dynamické: automatická úprava potlačení hluku na základě okolí.

Po testování a osobní zkušenosti mohu říci, že u loňských FreeBuds 4 fungovalo ANC poměrně obstojně. 5ky s trojicí mikrofonů na každém sluchátku posouvají ANC na novou úroveň (byť z podstaty věci se nemohou rovnat například náhlavním sluchátkům) a skutečně ruší okolní hluk natolik, abyste si cestu MHD nebo chůzi po rušné ulici užili se svojí oblíbenou hudbou bez všudypřítomného hučení aut a lidí.

Ovládání:

Ovládací gesta sluchátek jsou jednoduchá a intuitivní. Skrze aplikaci je možná jejich úprava Nastavení gest (zdroj: Cnews)

Po prvotním spárování sluchátek s telefonem stačí jedno či obě sluchátka pouze vyjmout z pouzdra a nasadit do uší. Dojde k automatickému připojení, jak už je u takového typu sluchátek zvykem. Pochválit musím Huawei i za jednoduchá, a hlavně intuitivní gesta, což je ne vždy zvykem.

Dvojitým poklepáním na kterékoliv sluchátko pozastavíte nebo spustíte přehrávanou hudbu, pro změnu hlasitosti pak stačí potáhnout nahoru či dolů, opět na kterémkoliv sluchátku. Pro aktivaci a následné přepínání mezi ANC režimy stačí podržet prst na vrchní straně sluchátka po dobu přibližně 2 sekund. Příchozí hovor přijmete dvojím poklepáním, podržením dojde k jeho odmítnutí.

 

Výdrž:

Vzhledem k velikosti sluchátek je celková výdrž příjemným překvapením. Huawei se chlubí výdrží až 30 hodin při vypnutém ANC, což je samozřejmě hodnota s nabíjecím pouzdrem. Samotná sluchátka vydrží s vypnutým ANC hrát přibližně 5 hodin. Pokud ANC zapnete, klesne výdrž sluchátek přibližně na 3,5 hodin, potažmo 20 hodin po započítání baterie v pouzdře.

ANC zapnuto: ANC vypnuto:
3,5 + 20 hodin 5 + 30 hodin

Uvnitř každého sluchátka se nachází 42mAh baterie, uvnitř nabíjecího pouzdra byste pak našli 505mAh baterii. Z 0 na 100% se sluchátka v pouzdře nabijí za 20 minut, což je opravdu slušný výsledek. Nabíjení pouzdra pak dle výrobce trvá asi 40 minut, z mé zkušenosti počítejte spíše se 45 až 50 minutami skrze USB-C. V případě bezdrátového nabíjení stoupá doba nabití až na 4 hodiny.

Hodnocení:

I přestože jsem velký odpůrce peckových sluchátek, snažil jsem se k novým Huawei FreeBuds 5 zachovat maximálně neutrální názor. Zatímco předchozí 4ky cílí svým vzhledem na širokou masu lidí, nové FreeBuds 5ky se naopak snaží zaujmout neotřelým vzhledem. A právě ten může být pro mnohé kamenem úrazu. Osobně se mi nový design sluchátek moc nelíbí, jedná se však o subjektivní dojem a posouzení je čistě na vás.

zabbix_tip

Nic to ale nemění na faktu, že za cenu přibližně 3 700 Kč dostanete výborná pecková sluchátka s vynikajícím zvukem, který nad ostatními peckami vyniká zejména hlubokou a dynamickou basovou složkou. Pokud k tomu připojíme funkční ANC, Hi-Res certifikaci a podporu LDAC audio kodeku, převýší FreeBuds 5 kdejaká sluchátka i v dražší cenové kategorii.

Líbilo se mi: Nelíbilo se mi:
+ vzhledem k rozměrům vynikající zvuk s basovou složkou - specifický design, který nemusí sedět každému
+ Bluetooth 5.2 s LDAC kodekem - krkolomnější cesta k aplikaci AI Life
+ zvýšená odolnost IP54  - pecky
+ použitelné ANC  - použitý lesklý plast sluchátek
+ intuitivní a funkční gesta
+ dobrá výdrž a podpora rychlonabíjení

 

Autor článku

Šéfredaktor portálu Cnews.cz.

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