Upload
3camp
View
238
Download
1
Embed Size (px)
Citation preview
// `#####: // ######### .########` #########:. // .########` :########### ############## // ######### ###### #####` ##### `###: // ######### ###### ##### ####. #### // ######## `###### ##### .#### .,:##### // ,######## ,#####. ##### ##### `######: // ########` ###### ##### ##### // ######## ###### ######### // #############` :#####. // :#########, /* * Grupa Wirtualna Polska sp z o.o. * * Rosa Łukasz * Team Leader / Senior Front-End Developer * * Szabłowski Adam * Senior Front-End Developer * */
/* Dotychczas FLASH ... * *
* 2008 – HTML5 First Public Working Draft * * Kwiecień 2010 - Bunt Jobsa * * YouTube wdraża VIDEO w HTML5 w 2011 r. * https://www.youtube.com/html5 * * GWP: Pierwsze przymiarki - wrzesień 2013 * * GWP: Do kwietnia 2014 player Flash'owy * Od maja 2014 player HTML5 * (Flash dla niewspierających przeglądarek oraz LiveStream) * * 28 października 2014 - HTML5 Recommendation * */
/* Powstanie HTML5 i tagu VIDEO * * * Popularyzacja wideo jako kontentu i nośnika reklamy, w związku z tym * zapotrzebowanie na natywne mechanizmy do publikowania tych matieriałów.
* * Uniezależnienie się od wtyczek firm trzecich, takich jak QuickTime, czy Flash. * * Ujednolicenie standardu, ułatwienie pracy deweloperom * (semantyka - VIDEO to VIDEO, a nie OBJECT czy EMBED). * */
/* Porównanie HTML5 vs Flash * * HTML5 Flash * * Wymagana instalacja playera Nie Tak * * Działa na urządzeniach mobilnych Tak Nie (już) * * Wsparcie przez iOS Tak Nie * * Szybkość działania Różnie Różnie * * Dojrzała technologia Nie Tak *
* Różne zachowanie w różnych środowiskach Tak (jeszcze) Nie * * * http://en.wikipedia.org/wiki/Comparison_of_HTML5_and_Flash * */
/* * * Dlaczego wideo w HTML5? * * Uniwersalność * * Większy zasięg * * Łatwość skórkowania * * Łatwość tworzenia nowych form reklamowych * */
/* * * WYZWANIA * * Różnice w implementacjach na różnych przeglądarkch, OS i ich wersjach. * * -> Obsługiwane formaty i kodeki * * http://pl.wikipedia.org/wiki/HTML5_video * * http://caniuse.com/#feat=webm (WP - tylko nowe materiały) * http://caniuse.com/#feat=mpeg4 (WP) * http://caniuse.com/#feat=ogv * * -> Różnice w zachowaniu API i UI * głównie Mobile iOS i stare wersje Androida * * -> Zmora programistów: Stockowa przeglądarka Androida ! * */
/* * * Strumienie NA ŻYWO - Dlaczego dalej we Flashu? * * * RTMP - Real Time Messaging Protocol * * HLS - HTTP Live Streaming * */
/* * * Na HLS zdecydowanie za wcześnie * * Nakład pracy nieporównywalny do efektów * */
/* * * Fullscreen * */
/* * * Fullscreen API - przeznaczenie * * zdjęcia * * filmy * * gry * */
/* * Fullscreen API - wsparcie * * CHROME 20 (15) * * FIREFOX 33 (10) * * IE 11 * * OPERA 15 (12.10) * * Safari 7.1 (5.1) * * Android mobile CHROME 39 (28) */
/* *
* <div id="wpplayer"> * <div class="player-container"> * <video width="100%" height="100%" controls> * <source src="...." type="video/mp4"/> * <source src="...." type="video/webm"/> * </video> * <button class="player-fullscreen">fullscreen</button> * </div> * </div> */
FSMap = (function () { var FSWebApi = [ ["requestFullscreen", "exitFullscreen", "fullscreenchange"], ["webkitRequestFullscreen", "webkitExitFullscreen", "webkitfullscreenchange"], ["webkitRequestFullScreen", "webkitCancelFullScreen", "webkitfullscreenchange"], ["mozRequestFullScreen", "mozCancelFullScreen", "mozfullscreenchange"],
["msRequestFullscreen", "msExitFullscreen", "MSFullscreenChange"]]; //... for (i = 0; i < l; i++) { bApi = FSWebApi[i]; if (bApi && bApi[1] in document) { for (i = 0, valLength = bApi.length; i < valLength; i++) { ret[FSWebApi[0][i]] = bApi[i]; } return ret; } } return false;})();
var wpplayer = document.getElementById("wpplayer"), fsContainer = wpplayer.getElementsByClassName("player-container")[0], fsBtn = wpplayer.getElementsByClassName("player-fullscreen")[0], fsClassName = "pseudofullscreen",
keyHandler = function (e) { if (e.keyCode === 27) { /* USUNIĘCIE KLASY SYMULUJĄCEJ FULLSCREEN */ } },
clickHandler = function () { if (FSMap) { fsContainer[FSMap.requestFullscreen](); } else { //IE<11
fsContainer.className += " " + fsClassName; document.onkeydown = keyHandler; } };
fsBtn.onclick = clickHandler;
/* * * Pseudoklasy Fullscreen * * :fullscreen { * position:fixed; * width:100%; height:100% * top:0; left:0; background-color:none; * } * :-webkit-full-screen { ... } * :-moz-full-screen { ... } * :-ms-fullscreen { ... } * */
/* * <style> * * .pseudofullscreen { * position: fixed; * top: 0; * left: 0; * width: 100%; * height: 100%; * } * * </style> */
/* * * <iframe ... allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe> * * IE jak zawsze działa inaczej * */
/* * * Autoplay * * <video ... autoplay></video> * * */
/* * * Autoplay jest zablokowany na urządzeniach z systemem iOS * oraz na części urządzeń z systemem Android * * Powód? * */
/* * * * * Odtworzenie wideo musi być poprzedzone akcją użytkownika * */
/* * * Rozwiązanie? * * Odtwarzanie kolejnych materiałów w ramach * jednego <video> * */
/* * * Przechowywanie danych międzydomenowo * * Serwis * */
var messanger, callbackQueue = {},
onMessage = function (e) { var cb, data, callbacks;
try { data = JSON.parse(e.data); } catch (ignore) {}
if (data && callbackQueue && callbackQueue[data.name] && callbackQueue[data.name][data.action]) { callbacks = callbackQueue[data.name][data.action]; }
if (callbacks) { for (i = 0; i < callbacks.length; i++) { cb = callbacks.pop(); cb(data); } } },
onMessangerLoad = function () { messanger = hub.contentWindow;
for (i = 0; i < waitingQueue.length; i++) { messanger.postMessage(waitingQueue[i].data, waitingQueue[i].domain || "*"); } },
onLoad = function () { if (!hub) { window.addEvent(window, 'message', onMessage);
hub = document.createElement("iframe"); document.body.appendChild(hub);
hub.onload = onMessangerLoad; hub.src = "//stg.wp.pl/hub.html"; } };
addEvent(document, 'DOMContentLoaded', onLoad);
window.WPXDCookies = {
isReady: function () { return !!messanger; },
setCookie: function (name, value, cb, domain) {
// cb // .... var data = JSON.stringify({ action: "set", name: name, value: value });
if (messanger) { messanger.postMessage(data, domain || "*"); } else { waitingQueue.push({ data: data, domain: domain }); } },
getCookie: function (name, cb, domain) {
// cb // .... var data = JSON.stringify({ action: "get", name: name });
if (messanger) { messanger.postMessage(data, domain || "*"); } else { waitingQueue.push({ data: data, domain: domain
}); } }};
/* * * Przechowywanie danych międzydomenowo * * Hub * */
var ALLOWED_NAMES = ["WPBASP", "WPVol", "WPClipsShown"],
message = function (e) { var data = JSON.parse(e.data), cookieRegExp, cookieValue, output;
if (data && ALLOWED_NAMES.indexOf(data.name) > -1) {
if (data.action === "set") { document.cookie = data.name + "=" + data.value; }
cookieRegExp = new RegExp('(?:(?:^|.*;\\s*)' + data.name + '\\=([^;]*).*$)|^.*$');
cookieValue = document.cookie.replace(cookieRegExp, "$1");
if (data.action === "set" && cookieValue === "") { output = { error: 1, type: 'cookie', message: "Can't set cookie. Check browser settings.", action: data.action, name: data.name, value: data.value
}; e.source.postMessage(JSON.stringify(output), "*"); throw new CookieError(output.message);
}
output = { error: 0, action: data.action, name: data.name, value: cookieValue };
e.source.postMessage(JSON.stringify(output), "*"); } else { throw new CookieError("Cookie name '" + data.name
+ "' not set or cookie is not allowed."); } };
addEvent(window, 'message', message);
/* * * Wykrywanie łącza * */
/* * * Co dają nam przeglądarki? * * * Connection.bandwidth * * Eksperymentalnie tylko Firefox dla Android. * https://developer.mozilla.org/en-US/docs/Web/API/Connection.bandwidth * * * Flash * * Ale co z urządzeniami mobilnymi? * */
/* * * Podejścia do tematu... * * Testowanie na wielu plikach graficznych o różnych wielkościach * * Testowanie na materiale w HTML5 * * */
/* *
* Testowanie na docelowym playerze, czyli tagu VIDEO: * * -> Przy pierwszym (pełnym) evencie PROGRESS pobieramy czas ładowania * i wielkość pobranej części materiału. * * -> Wysyłamy HEAD po wielkość całego materiału. * Tu wymagane są nagłówki CORS: * * Access-Control-Allow-Origin: nasza.domena.pl * Access-Control-Expose-Headers: Content-Length * * -> Wyliczmy bitrate (narzucamy 10%). * * -> Wybieramy jakość z 2 (lub 4) dostępnych i ewentualnie * podmieniamy materiał. * * -> Zapisujemy ostatnio wybraną jakość do międzydomenowego cookie. * * -> Przy kolejnym odtworzeniu (także w innym serwisie) * pobieramy jakość z cookie: * * -> Jeżeli nie ma wartości, jawnie wykrywamy łączę i ewentualnie * podmieniamy materiał. * * -> Jeżeli jest, wykrywamy ponownie w tle i ewentualnie * podmieniamy materiał. * * -> Liczba oczekiwanych eventów PROGRESS jako parametr, * co pozwala określać dokładność pomiaru. * * -> Możemy też użyć eventu CANPLAYTHROUGH, ale na wolniejszych łączach * trzeba na niego długo czekać. * */
var videoContainer = document.createElement('video'),
onQualitySet = function (quality) { // ustawiam jakość },
bandwidthDetector = new WP.player.BandwidthDetection(videoContainer, onQualitySet),
onVideoEvent = function (event) {
if (event.type === "progress") { bandwidthDetector.onProgress(videoContainer); }
if (event.type === "loadstart") { bandwidthDetector.onLaodStart(videoContainer); } };
videoContainer.addEventListener('progress', onVideoEvent);videoContainer.addEventListener('loadstart', onVideoEvent);
var xhr, onXHRReadyStateChange = function () { var contentLength, quality;
if (xhr.readyState === 2) { try { contentLength = parseInt(xhr.getResponseHeader("Content-Length"), 10); } catch (e) { onXHRError(); }
if (contentLength) { xhr.onreadystatechange = null; xhr.abort();
// ... liczymy bitrate, jakość itd. quality = 3; setQuality(quality);
} else { onXHRError(); } } },
onXHRError = function () { setQuality(0); };
try { xhr = new XMLHttpRequest(); xhr.onreadystatechange = onXHRReadyStateChange; xhr.onerror = onXHRError; xhr.open("HEAD", clipUrl, true); xhr.send();} catch (e) {
onXHRError();}
/* * * Po co, dlaczego tak? * * * Wykonujemy tylko jedno dodatkowe odpytanie HEAD * i gdy zajdzie potrzeba zmieniamy materiał na innej jakości. * * Jakość połączenia jest zmienna, zależna od aktualnego obciążenia łącza. * * Mamy dobre materiały - wykorzystajmy to, zróbmy lepsze wrażenie! * Tylko ok. 1% użytkowników zmienia jakość samodzielnie. * * Zapamiętujemy jakość (i inne parametry) między domenami, co polepsza UX. *
*/
/* * * Lepszy player -> * * lepsze materiały -> * * więcej odsłon/odtworzeń -> * * więcej reklamodawców -> * * większa szansa na premię :). * */
/* Architektura * * ------- * | API | * ------- * ↑ * ↓ ------------- ------------ * ------------------- | MODUŁ | | AD | * | | ←→ | REKLAMOWY | ←→ | SERVER | * | | ------------- ------------ * | C O R E | ↓ * | | ------------- ------------ * | | → | MODUŁ | → | STAT | * ------------------- | STATYSTYK | | SERVER | * ↑ ↑ ------------- ------------ * ↓ ↓ * -------- --------- * | SKIN | | VIDEO | * -------- --------- * ↑ ↑ * ↓ ↓ * --------- --------- * | HTML5 | | FLASH | * --------- --------- */
/* * * Aktualizacja i zarządzanie kodem * */
/* * * Biblioteka ogólnoportalowa WPJSLIB * * Player Portalowy - moduł ww. biblioteki * */
/* * * Propagacja nowej wersji Playera * * maksymalnie 15 minut, niezależnie od serwisu * */
/* * * Z perspektywy czasu (statystyki / wykresy) * * Czy było warto? * */
/* * * DZIĘKUJEMY ZA UWAGĘ!! * * * * * * * * * poszukiwany * * FRONT-END DEVELOPER * [email protected] * */