Vysílání po Internetu - MS NetShow Theater Server 3.0

1. 8. 1999

Sdílet

Multimédia ve spojení se sítí Internet se stala oblastí, které se připisujevelká budoucnost a proto není divu, že se v ní intenzivně angažuje i firma Microsoft. Jedním z jejích produk...
Multimédia ve spojení se sítí Internet se stala oblastí, které se připisuje
velká budoucnost a proto není divu, že se v ní intenzivně angažuje i firma
Microsoft. Jedním z jejích produktů v této oblasti je NetShow Theater Server
3.0 (první verze programu byla uvedena na trh v roce 1996). Tento produkt
umožňuje používat audiovizuální vysílání prostřednictvím Internetu a intranetu,
a také vývoj multimediálních aplikací v prostředí Windows NT Serveru (a Windows
95/98 či NT na straně klienta). Použití programu je rozsáhlé, ostatně stejně
jako použití multimédií vůbec, a sahá od oblasti školení a videokonferencí až
po vysílání internetovské televize. Aplikace na něm založené najdou uplatnění
jako různé prezentační a prodejní systémy, v zábavním průmyslu, a pochopitelně
pro společnosti zabývající se službami (hotely, cestovní kanceláře, aerolinie,
reklamní agentury).

Instalační disk obsahuje vlastní software pro server a dále program Microsoft
Windows Media Player k přehrávání multimediálních souborů pro stranu klienta.
Microsoft Windows Media Player podporuje všechny běžně používané formáty (MPEG,
RealAudio a RealVideo, WAV, VOD, QuickTime a další), a také vlastní formát ASF
(Advanced Streaming Format) umožňující tzv. vysílání proudem (streamování), při
kterém není třeba audiovizuální soubor nejdříve nahrát na
klientskou stanici. Tato technologie pochopitelně šetří místo na disku počítače
a také čas, protože k vysílání dojde takřka bezprostředně (přesněji po nahrání
dat do vyrovnávací paměti). Pro vytváření vlastních multimediálních aplikací
jsou k dispozici komponenty ActiveX balíku Software Developer\s Kit (SDK); pro
použití interaktivní televize potom Microsoft Broadcast Server, který umožňuje
používat tzv. multicasting (technologie zefektivňující vysílání stejných
multimediálních dat více klientům jako protiklad tzv. unicastingu). Jako
dodatečné aplikace obsahuje instalační disk Windows NT 4.0 Service Pack 3.0 a
Internet Explorer. Technická kvalita vlastního vysílání je pochopitelně dána
šířkou přenosového pásma, rychlost přenosu multimediálních dat je v rozmezí 0,5
až 8 Mbps (NetShow Theater Server také umožňuje měnit rychlost přenosu
dynamicky). Program dále obsahuje prostředky pro administraci systému, jako je
např. Event Log, zaznamenávající systémové události do databáze formátu mdb;
využít lze i prostředky poskytované NT Serverem (Performance Monitor nebo Event
Viewer).

Architektura systému
K tomu, aby mohl být zprovozněn systém založený na Microsoft NetShow, není
potřeba žádného speciálního vybavení (viz dále). Základem systému je tzv. Title
Server, jehož prostřednictvím "komunikují" uživatelé (tedy klientské stanice) s
vlastním systémem, a jenž vyřizuje požadavky klientů a řídí vlastní vysílání.
Multimediální data jsou uložena na tzv. Content serverech, kterých může být až
14. Na druhé straně pro provoz minimální varianty stačí server jeden, a ten
potom současně slouží jako Title i Content server. Speciální způsob ukládání
multimediálních souborů na serverech je použit z důvodu optimalizace provozu,
zajištění stejné kvality vysílání u všech klientů a také proto, aby se
minimalizovala možnost výpadku dat (mimo jiné lze používat i redundantní
uložení dat, tzv. mirroring). Ke správě celého systému je určena speciální
stanice; administrace se týká hlavně konfigurace funkcí a parametrů serveru,
práce s multimediálními tituly a správy a monitoringu připojení. Počítač,
sloužící pro administraci systému, může zároveň sloužit jako klientská stanice.

Nezbytné hardwarové a softwarové vybavení
Výhodou produktu+ je skutečnost, že k jeho provozu stačí běžný hardware
požadavky na Title server jsou následující: PC s Pentiem min. 200 MHz (nebo
počítač Compaq Alpha), 64 MB RAM (128 MB pro
Alphu), 1GB pevný disk (prostor závisí na množství klientů) a pochopitelně
síťová karta (ethernet, ATM). Jako operační systém je třeba Windows NT Server
4.0 nebo NT 4.0 Enterprise Edition a Service Pack 3.0. Stejné požadavky jsou i
pro počítače, na kterých jsou umístěna multimediální data; počítač určený pro
správu systému vyžaduje v podstatě
libovolné Pentium a 32 MB RAM, ostatní požadavky jsou shodné (s vyjímkou
prohlížeče Internet Explorer). Klientské stanice požadují obdobnou konfiguraci,
samozřejmě s potřebným multimediálním vybavením, jako operační systém mohou být
použita Windows NT 4.0 Workstation nebo 95/98. Z hlediska síťového provozu je
pro klientské stanice potřeba protokol TCP/IP, pro servery, na kterých jsou
uložena data, pak UDP/IP.

Závěr
NetShow Theater Server 3.0 je vyspělý produkt, který umožňuje efektivní práci s
multimediálními daty
na platformě Windows NT (výhodou je i integrace s tímto systémem). Za klad lze
také považovat relativně malé nároky na hardware a samozřejmě i možnost
vytvářet vlastní multimediální aplikace za pomoci komponent ActiveX v rámci SDK.

Microsoft NetShow Theater Server 3.0
+ Podpora velkého množství multimediálních formátů
+ SDK pro vývoj multimediálních aplikací
- Omezení na platformu Windows NT
Firma:
Microsoft, s. r. o.
Novodvorská 1010 Praha 4
Cena: 93 230 Kč (bez DPH) za server a 5 klientů

9 0492/OK
'; 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'; } }