wtorek, 17 stycznia 2017

[API][Google] Rozgryzamy API Youtube'a i robimy własny odtwarzacz!

TRUE
2050492019291633876
Blog PHP Majster powraca na antenę po dłuższej przerwie w publikowaniu! Jak zapewne niestety zauważyliście, tydzień na publikację kolejnego wpisu przedłużył się... do prawie dwóch lat i przez ten czas blog nie był w ogóle aktualizowany. Przyczyna oczywiście była prozaiczna - najnormalniejszy w świecie brak wolnego czasu i dużo wszelakich projektów na głowie. Z nowym rokiem blog jednak powraca i tym razem będzie on sukcesywnie uzupełniany treścią, a jest tego w planach bardzo dużo.

Przede wszystkim za niedługo zajmiemy się dłuższą serią artykułów dotyczących frameworka Symfony, gdyż o ten temat prosiło na facebooku bardzo dużo osób. Będzie to jednakże długa seria, gdyż materiału do przyswojenia jest bardzo dużo - Symfony to bardzo obszerny temat, w dodatku wymuszający konieczność zahaczenia również o Doctrine i Twiga. Powoli jednak wszystko sobie tutaj opiszemy i tym razem wpisy będą pojawiać się nieco częściej, niż co dwa lata ;) Jak widać, strona graficzna bloga została też lekko odświeżona, mam nadzieję, że w takiej formie wszystko wygląda jaśniej i czytelniej, niż w wersji poprzedniej (wszelkie sugestie oczywiście mile widziane). Ale dobrze już, wystarczy tego przydługiego wstępu, czas zająć się ciekawym tematem, mianowicie w tym artykule zobaczymy jak w praktyczny sposób wykorzystać API udostępnione przez Google do youtubowego odtwarzacza.

Nad tematem tym pracowałem stosunkowo niedawno, tworząc dynamiczny, wysuwany "zza ekranu" odtwarzacz dla pewnego forum internetowego. Pierwotna wersja działała poprzez PHP i Javasript za pomocą zwykłego embeddowania oferowanego przez Youtube, jednakże w wersji kolejnej postanowiłem pójść o krok dalej, całkowicie zrezygnować z takiej formy i wykorzystać API od Google. Wybór takiego rozwiązania pozwolił stworzyć mi kilka bardzo ciekawych funkcjonalności, które postaram się w niniejszym artykule opisać. Omówimy sobie dokładnie zatem API odtwarzacza, zobaczymy w jaki sposób to wszystko działa i jak to w praktyce wykorzystać. Będzie dużo javascriptu i trochę PHP oraz połączenie jednego z drugim. Zapraszam do lektury...


Na początek możecie się zapoznać z bardzo dobrą dokumentacją jaką oferuje samo Google odnośnie playera, znajdziecie ją pod tym adresem:
[code]https://developers.google.com/youtube/iframe_api_reference[/code]
Działający "na żywo" materiał dydaktyczny mojego autorstwa znajdziecie natomiast pod tym adresem:
[code]http://www.webmaester.pl/_phpmajster/youtube-api-tutorial/index.php[/code]
(ale o tym więcej na samym końcu niniejszego tutoriala, polecam najpierw przeanalizować cały artykuł, a dopiero na końcu zajrzeć w podane miejsce).

Jak działa odtwarzacz Youtube?

Pewnie nie raz i nie dwa zdarzyło się Wam umieszczać (embeddować) jakieś filmy na swoich stronach. Youtube udostępnia ku temu kod do udostępnienia każdego filmu, który wygląda mniej więcej tak:
[code]<iframe width="560" height="315" src="https://www.youtube.com/embed/Pwrhzfsq8t4" frameborder="0" allowfullscreen></iframe>[/code]
Jest to zwykła ramka wyświetlająca odtwarzacz udostępniany z serwera Google. Jeśli ktoś z Was próbował wejść na adres ramki bezpośrednio to zobaczy golutki odtwarzacz:
[code]https://www.youtube.com/embed/Pwrhzfsq8t4[/code]
Jeśli ktoś zajrzy jeszcze głębiej, w źródło strony, ujrzy mniej więcej strukturę tego jak to wszystko jest zorganizowane. Przede wszystkim znajdziemy tam plik .js z samym odtwarzaczem:
[code]<script src="//s.ytimg.com/yts/jsbin/www-embed-player-vflP9Ky8j/www-embed-player.js" type="text/javascript" name="www-embed-player/www-embed-player"></script>[/code]
W sekcji body znajdziemy również jednego, jedynego DIV-a, o wymownej nazwie "player":
[code]<div id="player"></div>[/code]
oraz skrypt z json-ową konfiguracją odtwarzacza:
[code]<script>yt.setConfig({'EVENT_ID': "2xF9WJfANIXocNiCo0g",'VIDEO_ID': "Pwrhzfsq8t4",'POST_MESSAGE_ORIGIN': "*",'BG_P': [....] </script>[/code]

Dlaczego o tym piszę? Otóż piszę o tym dlatego, gdyż przyjrzenie się tej konstrukcji pomoże nam w zrozumieniu działania odtwarzacza od "kuchni strony". W naszym kodzie będzie to działać na takiej samej zasadzie jak tutaj. A zasada działania jest następująca: po załadowaniu kodu javascript odtwarzacza tworzony jest obiekt odtwarzacza, który w konstruktorze konfigurujemy po swojemu (określając np. adres filmu, czas rozpoczęcia, eventy i wiele innych opcji). Funkcje te są doskonale opisane w podanej wyżej dokumentacji referencyjnej od Google, my jednak zajmiemy się bardziej praktycznym opisem tego wszystkiego. Następnie inicjowany jest sam odtwarzacz, który podmienia zawartość podanego DIV-a na wyjście odtwarzacza. Obiekt odtwarzacza w javascripcie jest w pełni konfigurowalny i pozwala nam na zdefiniowanie swoich własnych funkcji dla zdarzeń takich jak np. wystartowanie filmu, zmiana stanu (typu przejście z odtwarzania do "pauzy" i inne). Eventy te opiszemy sobie kilka akapitów niżej, zacznijmy teraz od samego, najprostszego kodu.

Utwórzmy sobie pustą stronę, np. youtube.php, a w niej jednego DIV-a o identyfikatorze player:
[code]
<html>
<head>
<style>
#player {
  width:640px;
  height:320px;
}
</style>
</head>

<body>
<div id="player"></div>
</body>
</html>
[/code]
W sekcji <body>, za naszym DIV-em umieścimy sobie teraz prosty kod odtwarzacza, który wygląda tak:
[code]
<script>
   
  var tag = document.createElement('script');
  tag.src = "https://www.youtube.com/iframe_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      width: '640',
      height: '360',        
      videoId: 'Pwrhzfsq8t4'    
    });
  }    
</script>
[/code]
Jest to najprostszy z możliwych kod, który po załadowaniu strony youtube.php wyświetli nam film:

Jak widzimy, na stronie mamy już załadowany odtwarzacz, prześledźmy zatem po kolei w jaki sposób został on zainicjowany. Na samym początku dodawany jest do drzewa DOM nowy element typu <script>, który pobiera kod z adresu https://www.youtube.com/iframe_api. Dzieje się to tutaj:
[code]
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
[/code]
Skrypt ten zawiera definicję klasy "YT" oraz definicje wszystkich niezbędnych komponentów składających się na API odtwarzacza ładowanego poprzez iframe. Mając już załadowany cały kod googlowskiego API pozostaje nam jedynie obowiązek utworzenia jednej tylko funkcji, o nazwie:
[code]onYouTubeIframeAPIReady();[/code]
Funkcja ta zostanie wywołana automatycznie w momencie załadowania do pamięci przeglądarki całego API i jest to jedyna funkcja jeśli chodzi o API Youtube'a, jaką będziemy w naszej zabawie operować. Co więc musi się znaleźć w definicji naszej funkcji inicjującej odtwarzacz? Przede wszystkim musimy utworzyć obiekt odtwarzacza i jak widać w naszym kodzie nazwaliśmy nasz obiekt player:
[code]
var player;
player = new YT.Player();
[/code]
Powyższy kod tworzy nam obiekt Player z klasy YT i przypisuje do zmiennej player. Samo utworzenie obiektu niewiele by nam jednak dało, gdybyśmy nie podali listy argumentów stanowiących konfigurację naszego odtwarzacza. Jako pierwszy argument podajemy tutaj zawsze nazwę elementu DIV, do którego załadowany zostanie odtwarzacz (czyli tutaj - player, gdyż tak nazwaliśmy naszego DIV-a), natomiast jako drugi argument podajemy listę opcji. W naszym przypadku, jako iż zaczynamy od prostego przykładu - podaliśmy jedynie szerokość (width) i wysokość (height) odtwarzacza oraz id filmu, który ładujemy do odtwarzacza, czyli Pwrhzfsq8t4. Oczywiście podany tutaj adres filmu będziemy mogli zmieniać sobie dynamicznie podczas naszej dalszej zabawy, ale do tego jeszcze dojdziemy. Na tym etapie mamy przygotowany i zainicjowany pełnoprawny odtwarzacz za pomocą youtubowego API. Czas na zabawę.

Eventy

Odtwarzacz operuje na zdarzeniach (eventach), do których możemy przypisać swoje funkcje je obslugujące. Eventem jest np. załadowanie odtwarzacza, lub też zmiana stanu (play/pause/stop, etc.). Do każdego ze zdarzeń możemy (ale nie musimy) zdefiniowć własną funkcję, która będzie uruchamiana w momencie wystąpienia zdarzenia. Funkcje do zdarzeń przypisujemy w liście parametrów podczas inicjowania odtwarzacza. Stwórzmy sobie teraz przykładową funkcję, która wyświetli nam alert w momencie kliknięcia na "play" odtwarzacza:
[code]
function onPlay(event)
{
  alert('Start!');
}
[/code]
Poprzez argument event pobierać będziemy później informacje o zwracanych przez odtwarzacz danych, ale o tym za chwilkę. Przypiszmy teraz zdefiniowaną przez nas funkcję do tworzonego obiektu:
[code]
var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      width: '640',
      height: '360',        
      videoId: 'Pwrhzfsq8t4',

      events: {
       'onStateChange': onPlay
      }    
    });
  }
[/code]
Jak widzimy, funkcje do eventów przypisujemy na zasadzie:
[code]
events: {
  'nazwaEventu': naszaFunkcja,
  'nazwaInnegoEventu': naszaInnaFunkcja,
  ...
}
[/code]
W naszym przykładzie przypisaliśmy utworzoną przez nas funkcję onPlay() do eventu o nazwie onStateChange. Event ten wyzwalany jest za każdym razem, gdy następuje zmiana stanu odtwarzacza, czyli np. jeśli ze stanu "odtwarzanie" zmieniamy stan na "pauza". Stanów takich jest kilka i reprezentowane są one liczbami:

-1 – unstarted (nie uruchomiono)
0 – ended (zakończono)
1 – playing (odtwarzanie)
2 – paused (wstrzymano)
3 – buffering (buforowanie)
5 – video cued (film został wskazany)

Nasz kod póki co nie rozróżnia z jakiego stanu na jaki dokonana została zmiana, gdyż nie określiliśmy tego jeszcze, wykona się on jednak podczas uruchomienia odtwarzania (nastąpi zmiana stanu z -1 na 1). Wypróbujmy:


Sukces. Po kliknięciu na przycisk odtwarzania wyświetla się okienko z alertem. Ale... wyświetliło się ono nam aż 3 razy! Dlaczego tak się dzieje? Otóż dzieje się tak dlatego, iż występują tutaj aż 3 zmiany stanu. Najpierw ze stanu "nie uruchomiono" następuje zmiana na stan "odtwarzanie", następnie na "buforowanie" i ponownie na "odtwarzanie". Aby teraz uzyskać dokładniejsze informacje o danym stanie w jakim znajduje się film i np. uzależnić tym warunkiem zachowanie naszej funkcji, wykorzystamy oferowaną przez API metodę:
[code]player.getPlayerState()[/code]
która zwraca numer stanu w jakim znajduje się odtwarzacz. Rozbudujmy zatem naszą funkcję onPlay o poniższy kod i przede wszystkim zmieńmy jej nazwę z onPlay na onChangeState, która będzie bardziej adekwatna, gdy już wiemy, że uruchamiać się będzie ona nie tylko podczas startu odtwarzania:
[code]
function onChangeState(event)
{
  var state = parseInt(event.data); // dla pewności rzutujemy na integer
  alert('Obecny stan: ' + state);

  if(state == 2) alert('Zapauzowano!');
}
[/code]
oczywiście nazwę funkcji zmieniamy też tutaj:
[code]
 events: {
   'onStateChange': onChangeState
 }
[/code]
Tutaj malutka uwaga - agument event pobierany do naszej funkcji jest obiektem zdarzenia.
Aby odczytać informację jaką zwraca korzystamy z właściwości data, czyli:
[code]event.data[/code]
Drugą sprawą jest kwestia, iż zwracane dane są typu string, więc konwertujemy tutaj zwrócony numer stanu na interger za pomocą parseInt().
Jeśli wszystko się zgadza, to tym razem nasza funkcja powinna podczas każdej zmiany stanu pokazać nam liczbę odpowiadającą danemu stanowi, a podczas zapauzowania filmu (zmiana na stan 2, czyli paused) powinna wyświetlić nam alerta o treści "Zapauzowano!". Sprawdźmy:

Po uruchomieniu filmu pojawiają się nam prawidłowo kolejno 3 alerty:
[code]Stan: -1 (stan wejściowy/film załadowany, nie odtwarza)[/code]
[code]Stan: 3 (rozpoczyna buforowanie)[/code]
[code]Stan: 1 (odtwarza)[/code]
Natomiast po zapauzowaniu najpierw zobaczymy alert:
[code]Stan:2 (zapauzowany)[/code]
a następnie alert:

Jak widzimy, poprzez odpowiednie operowanie informacją w jakim obecnie stanie znajduje się film, możemy tutaj stworzyć dowolne konstrukcje warunkowe i np. stworzyć sobie DIV-a, w którym na bieżąco umieszczać będziemy informację o aktualnym stanie filmu. Zróbmy to. Stwórzmy sobie drugiego DIV-a o id = status:
[code]<div id="status"></div>[/code]
Następnie przebudujmy naszą funkcję:
[code]
function onChangeState(event)
{
  var state = parseInt(event.data); // dla pewności rzutujemy na integer
  var status = '';

  switch(state)
  {
    case -1: status = 'nie uruchomiony'; break;
    case 1: status = 'odtwarzanie'; break;
    case 2: status = 'pauza'; break;
    case 3: status = 'buforowanie'; break;
    case 5: status = 'podano film'; break;
  }
  jQuery('#status').html(status);    
}
[/code]
Jak widzimy, korzystamy tutaj z jQuery, więc dołączymy bibliotekę do naszej strony. Nasz kod wyglądać będzie więc w całości tak:
[code]
<html>
<head>
<style>
#player {
  width:640px;
  height:320px;
}
#status {
  width:200px;
  height:30px;
  border:1px solid #000;
}
</style>
<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
</head>

<body>
<div id="player"></div>
<div id="status"></div>
<script>

  function onChangeState(event)
  {
    var state = parseInt(event.data); // dla pewności rzutujemy na integer
    var status = '';
 
    switch(state)
    {
      case -1: status = 'nie uruchomiony'; break;
      case 1: status = 'odtwarzanie'; break;
      case 2: status = 'pauza'; break;
      case 3: status = 'buforowanie'; break;
      case 5: status = 'podano film'; break;
    }
    jQuery('#status').html(status);    
  }
   
  var tag = document.createElement('script');

  tag.src = "https://www.youtube.com/iframe_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      width: '640',
      height: '360',        
      videoId: 'Pwrhzfsq8t4',
   
      events: {
       'onStateChange': onChangeState
      }      
    });
  }    
</script>
</body>
</html>
[/code]
Jak widzimy, wszystko działa jak należy:

Świetnie - zatem umiemy już pobierać informacje o filmie, a właściwie odtwarzaczu i stanie w jakim trzyma on nasz film. Do czego teraz może nam się przydać taka opcja? Otóż do wielu rzeczy, opiszę jedną z nich, którą wykorzystałem w swoim projekcie, o którym wspominałem na początku artykułu. Mianowicie - jak wspomniałem odtwarzacz był projektowany jako wysuwane zza ekranu okno (pozycja fixed, animowane chowanie i wyjeżdżanie za pomocą malutkiego przycisku). Co się jednak działo w momencie przeładowania strony, lub wejścia w inny link? Otóż odtwarzacz powracał do pierwotnego stanu, gdyż informacje o stanie w żaden sposób się nie zapisują, nie zapisują się także informacje o czasie, w którym ostatni raz "zastaliśmy" nasz film, zatem kolejnym razem startuje on od początku. Jak teraz to rozwiązałem? Otóż za pomocą obiektu Storage w HTML5. Obiekt Storage pozwala na zapisywanie zmiennych w pamięci przeglądarki. Jest to coś w rodzaju zmiennej sesyjnej w PHP, z tym że po stronie przeglądarki klienta, w dodatku zmienne te nie giną po zamknięciu przeglądarki.

Obiekt Storage

Z obiektu Storage korzystamy oczywiście za pomocą javascriptu, a jest to bardzo proste.
Aby zapisać zmienną w pamięci, wykorzystujemy następujący kod:
[code]
if (typeof(Storage) !== "undefined") {
  localStorage.setItem("NAZWA_ZMIENNEJ", WARTOŚĆ);
}
[/code]
Następnie, aby później odczytać wartość, robimy to tak:
[code]
var zmienna;
if (typeof(Storage) !== "undefined") {
  zmienna = localStorage.getItem("NAZWA_ZMIENNEJ");
}
[/code]
Bardzo prosty w użyciu i niesamowicie pomocny mechanizm. Domyślacie się już, jak go wykorzystać w naszym przypadku?
[code]
function onChangeState(event)
{
  var state = parseInt(event.data);

  if (typeof(Storage) !== "undefined") {
    localStorage.setItem("stanYt", state);
  }
}
[/code]
Powyższym sposobem zapisujemy w pamięci przeglądarki informację o stanie w jakim znajduje się film. Teraz po przeładowaniu strony możemy odczytać stan ze zmiennej stanYt i np. jeśli film był w trakcie odtwarzania, to wznowić je automatycznie za pomocą warunku:
[code]
jQuery(document).ready(function() {

  if (typeof(Storage) !== "undefined") {
    var state = parseInt(localStorage.getItem("stanYt")); // pamiętajmy o parseInt, gdyż w Storage wszystkie zmienne zapisywane są jako string
    if(state == 1)
    {
      // tutaj kod startujący film
    }  
  }
});
[/code]
Dodatkowo, pokusić się możemy o zapisanie aktualnej pozycji filmu i ponowienie odtwarzania od zadanego momentu, na co przepis przedstawię poniżej.

Aktualny czas odtwarzania

Aby pobrać z odtwarzacza aktualny czas w sekundach, w których znajduje się aktualnie oglądany film wykorzystamy do tego kolejną metodą udostępnioną przez API, mianowicie:
[code]player.getCurrentTime()[/code]
która zwraca aktualny czas odtwarzania w sekundach.
W jaki sposób teraz zapisać obecny czas do pamięci? Musimy pamiętać, że film podczas odtwarzania znajduje się cały czas w stanie = 1 (odtwarzanie), zatem musimy tutaj wykorzystać jakiś inny, zewnętrzny trigger, który co pewien czas zapisywać nam będzie obecny czas do obiektu Storage. Skorzystamy tutaj z wbudowanej w javascript funkcji setInterval(). Nasz kod będzie zatem wyglądać tak:
[code]
function saveTime()
{
  if(player)
  {
    var seconds = parseInt(player.getCurrentTime());
    localStorage.setItem("currentTime", seconds);
  }
}

setInterval(function() {
      saveTime();
}, 5000);
[/code]
Za pomocą powyższego, co 5 sekund do zmiennej currentTime zapisywana będzie obecna wartość licznika odtwarzania. Następnie po odświeżeniu strony po odczytaniu wartości będziemy mieli możliwość wystartowania filmu od odczytanej z obiektu Storage wartości.

Sterowanie odtwarzaniem

No dobrze, opisaliśmy możliwe zastosowania, nie opisaliśmy jednak w jaki sposób za pomocą javascriptu uruchomić, lub zatrzymać film, albo przewinąć do danej sekundy. Czas zatem to nadrobić, aby funkcje takie połączyć z powyższymi i stworzyć w pełni działającą całość. Na początek uruchomienie odtwarzania, które wykonać można - uwaga - na dwa różne sposoby. Sposobem pierwszym jest wykorzystanie metody API o nazwie:
[code]player.playVideo()[/code]
I tutaj uwaga - odtwarzanie musimy dokonać na już załadowanym filmie, dlatego też najpierw musimy mieć pewność, że odtwarzacz jest gotowy i posiada załadowany film. Sprawdzimy to za pomocą zwykłego if-a, który sprawdzi nam, czy obiekt istnieje:
[code]
if(player) {
  // akcja
}
[/code]
Zróbmy teraz sobie swoje własne, zewnętrzne przyciski do sterowania youtubowym odtwarzaczem. Wykonamy 3 buttony: play, pause i stop, które za pomocą API będą zewnętrznie sterować nam odtwarzanym filmem. Tworzymy zatem 3 przyciski:
[code]
<button id="play">PLAY</button>
<button id="pause">PAUSE</button>
<button id="stop">STOP</button>
[/code]
i oprogramowujemy je w jQuery:
[code]
jQuery(document).ready(function() {

  jQuery('#play').click(function() {
    if(player) player.playVideo();
  });
  jQuery('#pause').click(function() {
    if(player) player.pauseVideo();
  });
  jQuery('#stop').click(function() {
    if(player) player.stopVideo();
  });
});
[/code]

Bingo! Mamy kontrolę nad filmem za pomocą swojego kodu. Oczywiście zamiast przycisków możemy wykorzystać dowolny kod, np. taki, który za pomocą zapisanej w Storage zmiennej uruchomi nam film po odświeżeniu strony, o ile jego ostatni stan to było odtwarzanie (czyli stan = 1). Dokonamy tego bardzo prostym kodem:
[code]
jQuery(document).ready(function() {

  var state;

  // odczytujemy wcześniej zapisany stan
  if (typeof(Storage) !== "undefined") {
    state = localStorage.getItem("stanYt");
  }

  // jeśli stan == 1, to starujemy odtwarzanie
  if(state == 1)
  {
    if(player) player.playVideo();
  }

});
[/code]
Możemy to też zrobić za pomocą eventu onReady, który możemy oprogramować, np. tak jak poniżej:
[code]
function onPlayerReady(event) {
     
  if (typeof(Storage) !== "undefined") {
 
    if(parseInt(localStorage.getItem("stanYt")) == 1)
    {
      event.target.playVideo(); // w event.target znajduje się referencja do naszego odtwarzacza
    }      
  }        
}
[/code]
Funkcję taką musimy przypisać do eventu o nazwie onReady podczas inicjowania odtwarzacza:
[code]
events: {
  'onReady': onPlayerReady
}
[/code]
Powyższy sposób jest jednym z dwóch, gdyż możemy to zrobić jeszcze inaczej - za pomocą funkcji autoplay. W tym przypadku nasz kod musimy umieścić jeszcze przed zainicjowaniem odtwarzacza i w przypadku chęci automatycznego rozpoczęcia odtwarzania przekazać jeden parametr więcej podczas inicjowania odtwarzacza:
[code]autoplay: 1[/code]
Poniżej przykład takiego działania:
[code]
var state;
var autostart = 0;

// odczytujemy wcześniej zapisany stan
if (typeof(Storage) !== "undefined") {
  state = localStorage.getItem("stanYt");
}

if(state == 1)
{
  if(player) autostart = 1;
}

function onYouTubeIframeAPIReady() {
  width: '640',
  height: '360',        
  videoId: 'Pwrhzfsq8t4',
  playerVars: { 'autoplay': autostart},
  events: {
   'onStateChange': onChangeState
  }
});
[/code]
Jak widzimy - w zmiennych odtwarzacza (playerVars) podajemy opcję autoplay z wartością, którą określa tutaj nasza zmienna autostart, przyjmująca 1, gdy zapisany stan = 1, lub 0, jeśli jest inaczej.


Czas odtwarzania

Jak teraz uruchomić odtwarzanie od zadanego momentu? W kilku poprzednich akapitach stworzyliśmy kod, który w odstępie co 5 sekund zapisuje wartość sekundową licznika do zmiennej currentTime w obiekcie Storage. Wykorzystajmy teraz tę zmienną. Najpierw jednak musimy zrozumieć jak działa ustawianie czasu. Wykorzystywana do tego jest metoda:
[code]seekTo(sekundy);[/code]
Metoda ta przewija film do podanej jako argument ilości sekund. I tutaj ważna uwaga - film musi być już wystartowany. Jeśli przewiniemy zastopowany film, to nie nastąpi jego odtworzenie, kolejność zatem jest następująca - najpierw startujemy film za pomocą metody playVideo(), a następnie za pomocą metody seekTo() przewijany do zadanej chwili. Rozbudujmy nasz startujący kod z powyżej o opcję przewinięcia do zapisanej w Storage wartości:
[code]
function onPlayerReady(event) {
     
  if (typeof(Storage) !== "undefined") {
 
    if(parseInt(localStorage.getItem("stanYt")) == 1)
    {
      event.target.playVideo();  // startujemy film        
      var startTime = 0; // domyślnie ustawiamy na 0 sekund
      startTime = parseInt(localStorage.getItem("currentTime")); // odczytujemy wartość ze Storage
      if(startTime > 0) event.target.seekTo(startTime);  // jeśli zapisana jest wartość > 0, to przewijamy do tej chwili
    }      
  }        
}
[/code]
Tak na marginesie - wyjaśnienie należy się ciągłemu używaniu warunku:
[code]
if (typeof(Storage) !== "undefined") {

}
[/code]
Otóż warunek ten sprawdza, czy obiekt Storage jest dostępny. Nie jest to konieczne, gdyż praktycznie wszystko powyżej Internet Explorera 7 ma wbudowaną jego obsługę i raczej musielibyśmy mieć pecha, aby trafić na tak starą przeglądarką. Mimo wszystko, aby być eleganckim i gotowym na i taką ewentualność warto jest pozostawić tę instrukcję, gdyż w razie niedostępności Storage javascript wyrzuciłby niezłapany wyjątek.

Dobrze, lecimy dalej. Powyższe przewinięcie do zadanej sekundy to oczywiście tylko jeden ze sposobów wykorzystania tej możliwości. Równie dobrze możemy sobie utworzyć np. inputa, za pomocą jQuery odczytywać wpisaną tam wartość i przekazywać jako zmienną do metody seekTo(). Możemy także taką wartość pobierać sobie np. z tablicy $_GET, czyli z paska adresu i następnie za pomocą PHP generować odpowiedni kod javascript, np.:
[code]
<?php

if(isset($_GET['time']))
{
  echo '<script>
  player.seekTo(' . $_GET['time'] . ');
  </script>';
}
?>
[/code]

Ładowanie dowolnego filmu

Stwórzmy jeszcze jedną ciekawą funkcjonalność do naszego odtwarzacza, mianowicie możliwość podawania filmu do odtworzenia przez użytkownika. Wykorzystamy do tego javascriptowy prompt, który będzie pytał użytkownika o link do filmu na YT, po czym uruchomi ten film w naszym odtwarzaczu. Na początek jednak musimy otrzymany z prompta link sparsować (pamiętajmy, że musimy z linku wyciągnąć sam identyfikator filmu) oraz przede wszystkim sprawdzić, czy jest on poprawny. Wykorzystamy do tego funkcję:
[code]
function ytParser(url) {
    var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]{11,11}).*/;
    var match = url.match(regExp);
    if (match) if (match.length >= 2) return match[2];  
}
[/code]
Funkcja pobiera jako argument link do filmu na YT, po czym sprawdza, czy link pasuje do wzorca, a następnie zwraca nam wycięty identyfikator filmu.

Kolejną funkcją jaką stworzymy, będzie funkcja pytająca o adres filmu:
[code]
function customYt()
{
  var yt = prompt('Podaj adres do filmu na Youtubie (pełny adres - w całości, np. https://www.youtube.com/watch?v=_v94XqFW4Qw)'); // pobieramy link z prompta

  if(yt != '')
  {
    var parsed = ytParser(yt); // wycinamy z linku identyfikator
     if(parsed != undefined) {    
       player.loadVideoById(parsed);  // ładujemy film    
     }
   }  
}
[/code]
Wprawione oko zauważy, że widzimy tutaj coś, czego jeszcze nie omawialiśmy, czyli metodę:
[code]player.loadVideoById()[/code]
Metoda ta pobiera jako parametr ID filmu z YT, ładuje go do odtwarzacza i rozpoczyna odtwarzanie.

Mając taki zestaw funkcji możemy pokusić się o jeszcze jedno zastosowanie. Wyobraźmy sobie, że gdzieś na swojej stronie (np. jeśli jest to forum internetowe) posiadamy linki do róznych filmów, jakie umieszczają użytkownicy. Nic nie stoi na przeszkodzenie, aby dokonać takiego ich parsowania, aby po kliknięciu na adres filmu z Youtube uruchamiać np. javascriptową funkcję, która odtwarzać będzie film bezpośrednio w naszym odtwarzaczu. Wykonałem taką możliwość w projekcie, o którym wspominałem i sprawuje się ona bardzo ciekawie, zwłaszcza, iż sam odtwarzacz jest zafixowany w rogu ekranu i możliwy do zwijania/rozwijania. Bardzo praktyczna funkcjonalność, choć z początku może się ona wydawać jedynie czymś w rodzaju nieistotnego "bajeru".

Łącząc odpowiednio PHP z generowanym javascriptem mamy pełną kontrolę nad naszym odtwarzaczem. Oczywiście funkcji i możliwości jest znacznie, znacznie więcej, jednakże są one pięknie opisane w dokumentacji, do której linka podałem na początku tego artykułu. Po przyswojeniu wiedzy jaką przekazałem w powyższym poradniku zrozumienie dokumentacji przyjdzie Wam z łatwością. Na tym powoli kończymy - mam nadzieję, że opisane tutaj rzeczy wydały się ciekawe i przede wszystkim przydatne. Poniżej znajduje się wersja "na żywo" jak taki projekt działa (kod źródłowy w...źródle strony ;) ). Można się pobawić, podać swój film, przewinąć, odświeżyć stronę, sprawdzić przywracanie stanu itd.:


http://www.webmaester.pl/_phpmajster/youtube-api-tutorial/index.php

12 komentarzy:

  1. Uff... Nowy wpis. Odetchnęłam z ulgą :)

    OdpowiedzUsuń
  2. Chyba nikt po takim czasie nie spodziewał się nowego wpisu :D
    Fajnie że wróciłeś!

    OdpowiedzUsuń
  3. Wróciłem, wróciłem i obiecuję, że tym razem blog będzie częściej aktualizowany, już się pisze nowy tekst do wrzucenia :) Pozdrawiam!

    OdpowiedzUsuń
    Odpowiedzi
    1. Sam się pisze? To się nazywa automatyzacja :)
      Nie wiem jak inni, ale ja czekam z niecierpliwością!

      Dobrej nocy.

      Usuń
  4. Fajnie, fajnie!
    A czy jest opcja taka, ze np po 20skeundach możemy wyśweitlić jakąś aniete, albo jakieś labele na player nałożyć?
    Stricte po yt api

    OdpowiedzUsuń
  5. Fajny wpis. Ładny odtwarzacz, na pewno się przyda. Fajnie, że wróciłeś. Zabieram się za czytanie najnowszego wpisu!

    OdpowiedzUsuń
  6. cześć! czy mogę Tobie zlecić stworzenie za pomocą API od YT skryptu za pomocą którego z mojej strony mogę uploadowac filmy bezposrednio na moj kanał YT z moim tytułem i opisem do filmu?
    Do tego zadania również chciałbym art. wyjaśniający jaki tu zamieściłes. Rzeczowy i prosty do przyswojenia. Czekam na odpowiedź z wyceną.
    Pozdr.

    OdpowiedzUsuń
    Odpowiedzi
    1. Hej! Tak, jasne, odezwij się do mnie na mój adres mailowy: szczyglis83 (małpa) gmail.com i opisz mi dokładniej, czego by tam było potrzeba.
      Pozdrawiam. MS

      Usuń
  7. Super wpis. Podoba mi się w jak przystępny sposób tłumaczysz zawiłości projektowania stron. Ja swoje strony mam zaprojektowane w neconie, oni znają się tam naprawdę na rzeczy i nigdy nie miałam powodu, żeby narzekać. Cały układ jest przemyślany i estetyczny. Pozdrawiam serdecznie.

    OdpowiedzUsuń
  8. This excellent website truly has all of the info I wanted concerning this subject and didn’t know who to ask.
    UI Development Training in Bangalore
    Reactjs Training in Bangalore

    OdpowiedzUsuń

Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)

webmaester.pl - profesjonalne projektowanie WWW i webaplikacji
webmaester.pl - profesjonalne projektowanie WWW i webaplikacji