Tworzenie niestandardowego odbiornika internetowego

1. Opis

Logo Google Cast

Dzięki tym ćwiczeniom z programowania dowiesz się, jak utworzyć aplikację niestandardowego odbiornika internetowego do odtwarzania treści na urządzeniach obsługujących Cast.

Co to jest Google Cast?

Google Cast pozwala użytkownikom przesyłać treści z urządzenia mobilnego na telewizor. Użytkownicy mogą wtedy używać urządzeń mobilnych lub przeglądarki Chrome na komputerze jako pilota do odtwarzania multimediów na telewizorze.

Pakiet SDK Google Cast umożliwia aplikacji sterowanie urządzeniami obsługującymi Google Cast (np. telewizorem czy systemem audio). Pakiet SDK Cast udostępnia niezbędne komponenty interfejsu, które są zgodne z listą kontrolną projektowania Google Cast.

Dostępna jest lista kontrolna projektu Google Cast, dzięki której korzystanie z Cast jest proste i przewidywalne na wszystkich obsługiwanych platformach. Więcej informacji

Co będziemy tworzyć?

Po ukończeniu tego ćwiczenia z programowania będziesz mieć aplikację HTML5, która będzie działać jako Twój własny niestandardowy odbiornik umożliwiający wyświetlanie treści wideo na urządzeniach obsługujących Cast.

Czego się nauczysz

  • Jak przygotować się do programowania odbiorników.
  • Podstawowe informacje o odbiorniku obsługującym Cast, opartym na platformie Cast Application Framework.
  • Jak odebrać film, który będzie przesyłany.
  • Jak zintegrować Rejestrator debugowania.
  • Jak zoptymalizować odbiornik pod kątem inteligentnych ekranów.

Czego potrzebujesz

Funkcja

  • Aby skorzystać z tej możliwości, musisz mieć wiedzę w zakresie tworzenia stron internetowych.
  • Potrzebna będzie też wcześniejsza wiedza o oglądaniu telewizji :)

Jak będziesz korzystać z tego samouczka?

Przeczytaj tylko do końca Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z tworzeniem aplikacji internetowych?

Początkujący Średni Średni

Jak oceniasz swoje wrażenia z oglądania telewizji?

Początkujący Średni Średni

2. Pobieranie przykładowego kodu

Możesz pobrać cały przykładowy kod na komputer...

i rozpakuj pobrany plik ZIP.

3. Lokalne wdrażanie odbiornika

Aby można było używać odbiornika internetowego z urządzeniem przesyłającym, musi on być hostowany w miejscu, w którym urządzenie przesyłające ma do niego dostęp. Jeśli masz już serwer obsługujący https, pomiń poniższe instrukcje i zanotuj adres URL, ponieważ będzie on potrzebny w następnej sekcji.

Jeśli nie masz serwera, którego można użyć, możesz użyć Hostingu Firebase lub ngrok.

Uruchamianie serwera

Po skonfigurowaniu wybranej usługi przejdź do app-start i uruchom serwer.

Zanotuj adres URL hostowanego odbiornika. Użyjesz go w następnej sekcji.

4. Rejestrowanie aplikacji w Konsoli programisty Cast

Aby móc uruchamiać niestandardowy odbiornik (wbudowany w te ćwiczenia z programowania) na urządzeniach Chromecast, musisz zarejestrować swoją aplikację. Po zarejestrowaniu aplikacji otrzymasz identyfikator, którego aplikacja musi używać do wykonywania wywołań interfejsu API, na przykład do uruchamiania aplikacji odbierającej.

Obraz konsoli programisty pakietu Google Cast SDK z wyróżnionym przyciskiem „Add New Application” (Dodaj nową aplikację)

Kliknij „Dodaj nową aplikację”

Obraz ekranu „Nowa aplikacja odbiornika” z wyróżnioną opcją „Niestandardowy odbiornik”

Wybierz „Odbiornik niestandardowy”. To właśnie nad tym pracujemy.

Obraz ekranu „Nowy niestandardowy odbiornik” z adresem URL wpisanym przez użytkownika w polu „Adres URL aplikacji odbierającego”

Wpisz dane nowego odbiorcy. Pamiętaj, aby użyć docelowego adresu URL.

w ostatniej sekcji. Zanotuj identyfikator aplikacji przypisany do nowego odbiornika.

Musisz też zarejestrować urządzenie Google Cast, by mogło mieć dostęp do aplikacji odbierającej przed jej opublikowaniem. Po opublikowaniu aplikacji odbierającej będzie ona dostępna dla wszystkich urządzeń Google Cast. Na potrzeby tych ćwiczeń z programowania zalecamy pracę z nieopublikowaną aplikacją odbierającą.

Obraz konsoli programisty pakietu Google Cast SDK z wyróżnionym przyciskiem „Dodaj nowe urządzenie”

Kliknij „Dodaj nowe urządzenie”.

Obraz okna „Dodaj odbiornik”

Wpisz numer seryjny wydrukowany z tyłu urządzenia Cast i nadaj mu opisową nazwę. Numer seryjny możesz też znaleźć, przesyłając ekran w Chrome, gdy otworzysz Google Cast SDK Developer Console.

Zanim odbiornik i urządzenie będą gotowe do testowania, może minąć 5–15 minut. Po 5–15 minutach musisz zrestartować urządzenie przesyłające.

5. Uruchamianie przykładowej aplikacji

Logo Google Chrome

Czekając, aż nowa aplikacja odbierająca będzie gotowa do testów, zobaczmy, jak wygląda przykładowa ukończona aplikacja odbierająca. Odbiornik, który stworzymy, będzie w stanie odtwarzać multimedia z wykorzystaniem przesyłania strumieniowego z adaptacyjną szybkością transmisji bitów (użyjemy przykładowej treści zakodowanej na potrzeby dynamicznego przesyłania strumieniowego przez HTTP (DASH).

W przeglądarce otwórz narzędzie Command and Control (CaC).

Obraz karty „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC)

  1. Powinno być widoczne nasze narzędzie do zarządzania relacjami z klientami (CAC).
  2. Użyj domyślnego przykładowego identyfikatora odbiornika „CC1AD845” i kliknij przycisk „Ustaw identyfikator aplikacji”.
  3. Kliknij przycisk Cast w lewym górnym rogu i wybierz urządzenie Google Cast.

Obraz karty „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC) wskazujący, że jest ona połączona z aplikacją odbiornika

  1. Przejdź do karty „Wczytaj multimedia” u góry.

Obraz karty „Load Media” w narzędziu Command and Control (CaC)

  1. Kliknij przycisk „Wczytaj według treści”, aby odtworzyć przykładowy film.
  2. Film zacznie się odtwarzać na urządzeniu Google Cast, aby pokazać, jak wygląda podstawowy odbiornik w przypadku domyślnego odbiornika.

6. Przygotuj projekt początkowy

Musimy dodać obsługę Google Cast do pobranej aplikacji startowej. Oto niektóre z terminologii związanej z Google Cast, których będziemy używać w tym ćwiczeniu z programowania:

  • aplikacja nadawca działa na urządzeniu mobilnym lub laptopie,
  • aplikacja odbiornika działa na urządzeniu Google Cast;

Możesz teraz zacząć pracować nad projektem początkowym za pomocą ulubionego edytora tekstu:

  1. Wybierz katalog ikona folderuapp-start z pobranego przykładowego kodu.
  2. Otwórz js/receiver.js i index.html

Podczas wykonywania tych ćwiczeń z programowania http-server powinien wykrywać wprowadzone przez Ciebie zmiany. Jeśli zauważysz, że nie, wyłącz i ponownie uruchom aplikację http-server.

Projektowanie aplikacji

Aplikacja odbierająca inicjuje sesję przesyłania i pozostaje w trybie gotowości, dopóki nie nadejdzie żądanie WCZYTUJĘ (czyli polecenie odtwarzania multimediów).

Aplikacja składa się z 1 widoku głównego zdefiniowanego w index.html i 1 pliku JavaScript o nazwie js/receiver.js, który zawiera wszystkie funkcje logiczne niezbędne do działania odbiornika.

index.html

Ten plik HTML będzie zawierać interfejs naszej aplikacji odbierającej. Na razie jest pusty, ale w trakcie ćwiczenia z kodowania będziemy go dodawać.

receiver.js

Ten skrypt będzie zarządzać całą logiką naszej aplikacji odbierającej. Na razie jest to po prostu pusty plik, ale w następnej sekcji zmienimy go w w pełni działający odbiornik Cast.

7. Podstawowy odbiornik

Podstawowy odbiornik zainicjuje sesję przesyłania podczas uruchamiania. Jest to konieczne, aby poinformować wszystkie połączone aplikacje nadawcy, że uruchomienie odbiorcy zakończyło się powodzeniem. Poza tym nowy pakiet SDK jest wstępnie skonfigurowany do obsługi multimediów strumieniowanych z adaptacyjną szybkością transmisji bitów (z użyciem DASH, HLS i Smooth Streaming) oraz zwykłych plików MP4. Spróbujmy.

Inicjacja

Dodaj ten kod do elementu index.html w nagłówku:

<head>
  ...

  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
</head>

Dodaj poniższy kod do kodu index.html <body> przed elementem <footer> załadowaniem receiver.js,, aby zapewnić pakietowi SDK odbiorcy miejsce na wyświetlenie domyślnego interfejsu odbiorcy, który jest wysyłany ze dodanym właśnie skryptem.

<cast-media-player></cast-media-player>

Teraz musimy zainicjować pakiet SDK w js/receiver.js, w skład którego wchodzą:

  • uzyskanie odniesienia do CastReceiverContext, podstawowego punktu wejścia do całego pakietu SDK odbiornika;
  • przechowywanie odniesień do PlayerManager, czyli obiektu obsługującego odtwarzanie i zapewniania wszystkich punktów zaczepienia potrzebnych do obsługi własnej logiki;
  • inicjowanie pakietu SDK przez wywołanie start() w systemie CastReceiverContext

Dodaj te elementy do grupy reklam js/receiver.js.

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

context.start();

8. Przesyłanie „podstawowych” treści wideo

Na potrzeby tego ćwiczenia z programowania użyj narzędzia CaC, aby wypróbować nowy odbiornik.

Otwórz w przeglądarce narzędzie Command and Control (CaC).

Obraz karty „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC)

Zastąp własny identyfikator aplikacji zarejestrowanym wcześniej w polu i kliknij „Ustaw identyfikator aplikacji”. Dzięki temu narzędzie będzie używać odbiornika po rozpoczęciu sesji przesyłania.

Przesyłanie multimediów

Ogólnie, aby odtwarzać multimedia na urządzeniu przesyłającym, musisz wykonać te czynności:

  1. Nadawca tworzy z pakietu SDK Cast obiekt MediaInfo JSON, który modeluje element multimedialny.
  2. Nadawca łączy się z urządzeniem Cast, by uruchomić aplikację odbiorcy.
  3. Odbiorca wczytuje obiekt MediaInfo za pomocą żądania LOAD, aby odtworzyć treść.
  4. Odbiornik monitoruje i śledzi stan multimediów.
  5. Nadawca wysyła do odbiorcy polecenia odtwarzania, aby kontrolować odtwarzanie na podstawie interakcji użytkownika z aplikacją nadawcy.

W ramach pierwszej podstawowej próby uzupełnimy MediaInfo adresem URL zasobu możliwego do odtworzenia (zapisany w: MediaInfo.contentUrl).

Rzeczywisty nadawca używa w MediaInfo.contentId identyfikatora multimediów specyficznego dla aplikacji. Odbiorca używa contentId jako identyfikatora do wykonywania odpowiednich wywołań interfejsu API backendu w celu rozpoznania rzeczywistego adresu URL zasobu i ustawiania go na MediaInfo.contentUrl.. Adresat będzie też mógł wykonywać zadania takie jak pozyskiwanie licencji DRM czy wstawianie informacji o przerwach na reklamę.

W następnej sekcji rozszerzymy zakres odbiorcy, aby robił to samo co Ty. Na razie kliknij ikonę Cast i wybierz urządzenie, aby otworzyć odbiornik.

Obraz karty „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC) wskazujący, że jest ona połączona z aplikacją odbiornika

Przejdź do karty „Wczytaj multimedia” i kliknij przycisk „Wczytaj według treści”. Odbiornik powinien rozpocząć odtwarzanie przykładowej treści.

Obraz karty „Load Media” w narzędziu Command and Control (CaC)

Pakiet SDK odbiornika udostępnia gotowe do użycia funkcje:

  • Inicjuję sesję przesyłania
  • Obsługuj przychodzące żądania LOAD od nadawców, które zawierają zasoby możliwe do odtworzenia
  • Udostępnij podstawowy interfejs odtwarzacza gotowy do wyświetlania na dużym ekranie.

Zapoznaj się z narzędziem CaC i jego kodem, zanim przejdziemy do kolejnej sekcji, w której rozszerzymy adresata do rozmowy z prostym przykładowym interfejsem API, aby zrealizować przychodzące żądania LOAD od nadawców.

9. Integracja z zewnętrznym interfejsem API

Zgodnie ze sposobem, w jaki większość deweloperów korzysta z odbiorników przesyłania w rzeczywistych aplikacjach, zmienimy nasz odbiornik tak, aby obsługiwał żądania LOAD, które odwołują się do odpowiednich treści multimedialnych za pomocą klucza API, zamiast wysyłać adres URL zasobu z możliwością odtworzenia.

Dzieje się tak zwykle, ponieważ:

  • Nadawca może nie znać adresu URL treści.
  • Aplikacja Cast została zaprojektowana do obsługi uwierzytelniania, innych logiki biznesowej lub wywołań interfejsu API bezpośrednio na odbiorniku.

Ta funkcja jest wdrażana głównie w metodzie PlayerManager setMessageInterceptor(). Dzięki temu możesz przechwytywać wiadomości przychodzące według typu i modyfikować je, zanim dotrą do wewnętrznego modułu obsługi wiadomości pakietu SDK. W tej sekcji omawiamy żądania (LOAD), w przypadku których:

  • Odczytaj przychodzące żądanie LOAD i jego niestandardowe żądanie contentId.
  • Wykonaj wywołanie GET do naszego interfejsu API, aby wyszukać zasób możliwy do strumieniowego przesyłania według jego atrybutu contentId.
  • Zmodyfikuj żądanie LOAD, używając adresu URL strumienia.
  • Aby ustawić parametry typu strumienia, zmodyfikuj obiekt MediaInformation.
  • Przekaż żądanie do SDK w celu odtworzenia lub odrzuć to polecenie, jeśli nie można znaleźć żądanych multimediów.

Udostępniony przykładowy interfejs API prezentuje punkty zaczepienia pakietu SDK do dostosowywania typowych zadań odbiorcy, nadal polegając w większości na gotowych rozwiązaniach.

Przykładowy interfejs API

Wpisz w przeglądarce adres https://storage.googleapis.com/cpe-sample-media/content.json i zapoznaj się z naszym przykładowym katalogiem filmów. Zawartość obejmuje adresy URL obrazów plakatów w formacie PNG oraz strumienie DASH i HLS. Strumienie DASH i HLS wskazują zdemiksowane źródła wideo i audio przechowywane w pofragmentowanych kontenerach mp4.

{
  "bbb": {
    "author": "The Blender Project",
    "description": "Grumpy Bunny is grumpy",
    "poster": "https://[...]/[...]/BigBuckBunny/images/screenshot1.png",
    "stream": {
      "dash": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.mpd",
      "hls": "https://[...]/[...]/BigBuckBunny/BigBuckBunny_master.m3u8",
    "title": "Big Buck Bunny"
  },
  "fbb_ad": {
    "author": "Google Inc.",
    "description": "Introducing Chromecast. The easiest way to enjoy [...]",
    "poster": "https://[...]/[...]/ForBiggerBlazes/images/screenshot8.png",
    "stream": {
      "dash": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.mpd",
      "hls": "https://[...]/[...]/ForBiggerBlazes/ForBiggerBlazes.m3u8",
    "title": "For Bigger Blazes"
  },

  [...]

}

W następnym kroku zmapujemy klucz każdego wpisu (na przykład bbb, fbb_ad) na adres URL strumienia po wywołaniu odbiornika za pomocą żądania LOAD.

Przechwytywanie żądania LOAD

W tym kroku utworzymy obiekt przechwytujący obciążenie z funkcją, która wysyła żądanie XHR do hostowanego pliku JSON. Po uzyskaniu pliku JSON przeanalizujemy treść i ustawimy metadane. W kolejnych sekcjach dostosujemy parametry MediaInformation, aby określić typ treści.

Dodaj ten kod do pliku js/receiver.js tuż przed wywołaniem funkcji context.start().

function makeRequest (method, url) {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest();
    xhr.open(method, url);
    xhr.onload = function () {
      if (this.status >= 200 && this.status < 300) {
        resolve(JSON.parse(xhr.response));
      } else {
        reject({
          status: this.status,
          statusText: xhr.statusText
        });
      }
    };
    xhr.onerror = function () {
      reject({
        status: this.status,
        statusText: xhr.statusText
      });
    };
    xhr.send();
  });
}

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
        // Fetch content repository by requested contentId
        makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json').then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            reject();
          } else {
            // Add metadata
            let metadata = new
               cast.framework.messages.GenericMediaMetadata();
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
        });
      });
    });

W następnej sekcji opisujemy, jak skonfigurować właściwość media żądania wczytania na potrzeby treści DASH.

Korzystanie z przykładowej treści DASH interfejsu API

Po przygotowaniu modułu do przechwytywania obciążenia określimy typ treści w odbiorniku. Na podstawie tych informacji odbiorca otrzyma adres URL playlisty reklamy nadrzędnej oraz typ MIME strumienia. Dodaj ten kod do pliku js/receiver.js w elemenciePromise() przechwytującego LOAD:

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            ...
          }
        });
      });
    });

Po wykonaniu tego kroku możesz przejść do testowania, aby spróbować wczytać treści z treścią DASH. Jeśli zamiast tego chcesz przetestować wczytywanie za pomocą treści HLS, przejdź do następnego kroku.

Korzystanie z przykładowej treści HLS interfejsu API

Przykładowy interfejs API zawiera treści HLS i DASH. Oprócz skonfigurowania ustawienia contentType tak jak w poprzednim kroku, żądanie wczytania wymaga pewnych dodatkowych właściwości, by można było korzystać z adresów URL HLS przykładowego interfejsu API. Gdy odbiornik jest skonfigurowany do odtwarzania strumieni HLS, domyślnym oczekiwanym typem kontenera jest strumień transportu (TS). W efekcie odbiornik spróbuje otworzyć przykładowe strumienie MP4 w formacie TS, jeśli zmieni się tylko właściwość contentUrl. W żądaniu wczytania obiekt MediaInformation należy zmodyfikować za pomocą dodatkowych właściwości, aby odbiorca wiedział, że treść jest typu MP4, a nie TS. Aby zmodyfikować właściwości contentUrl i contentType, dodaj ten kod do pliku js/receiver.js w programie przechwytującym obciążenie. Dodaj też właściwości HlsSegmentFormat i HlsVideoSegmentFormat.

...
playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      return new Promise((resolve, reject) => {
          ...
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.hls;
            request.media.contentType = 'application/x-mpegurl';
            request.media.hlsSegmentFormat = cast.framework.messages.HlsSegmentFormat.FMP4;
            request.media.hlsVideoSegmentFormat = cast.framework.messages.HlsVideoSegmentFormat.FMP4;
            ...
          }
        });
      });
    });

Testowanie

Ponownie otwórz narzędzie Command and Control (CaC) i ustaw identyfikator aplikacji jako identyfikator aplikacji odbiorcy. Wybierz urządzenie, klikając przycisk Cast.

Przejdź do karty „Wczytaj multimedia”. Tym razem usuń tekst w polu „Adres URL treści” obok przycisku „Wczytaj według treści”, co zmusi naszą aplikację do wysłania żądania LOAD zawierającego tylko odwołanie do contentId naszych multimediów.

Obraz karty „Load Media” w narzędziu Command and Control (CaC)

Zakładając, że po zmodyfikowaniu odbiornika wszystko działa prawidłowo, moduł przechwytujący powinien kształtować obiekt MediaInfo w coś, co SDK może odtwarzać na ekranie.

Aby sprawdzić, czy multimedia są odtwarzane prawidłowo, kliknij przycisk „Wczytaj według zawartości”. Możesz zmienić identyfikator treści na inny w pliku content.json.

10. Optymalizacja pod kątem inteligentnych ekranów

Inteligentne ekrany to urządzenia z funkcjami dotykowymi, które umożliwiają aplikacjom odbierającym obsługę sterowania dotykowego.

W tej sekcji dowiesz się, jak zoptymalizować aplikację odbiornika po uruchomieniu na inteligentnych ekranach oraz jak dostosować elementy sterujące odtwarzaczem.

Uzyskiwanie dostępu do elementów sterujących interfejsu

Dostęp do obiektów elementów sterujących interfejsu na inteligentnych ekranach można uzyskać, używając aplikacji cast.framework.ui.Controls.GetInstance(). Dodaj ten kod do pliku js/receiver.js powyżej context.start():

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();

context.start();

Jeśli nie używasz elementu <cast-media-player>, musisz ustawić touchScreenOptimizedApp w elemencie CastReceiverOptions. W tym ćwiczeniu z programowania korzystamy z elementu <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Domyślne przyciski sterujące są przypisywane do poszczególnych boksów na podstawie MetadataType i MediaStatus.supportedMediaCommands.

Sterowanie odtwarzaniem

W aplikacjach MetadataType.MOVIE, MetadataType.TV_SHOW i MetadataType.GENERIC obiekt elementów sterujących interfejsu użytkownika na inteligentnych ekranach będzie wyświetlany, jak widać w poniższym przykładzie.

Obraz przedstawiający odtwarzany film z nałożonymi na siebie elementami sterującymi interfejsu

  1. --playback-logo-image
  2. MediaMetadata.subtitle
  3. MediaMetadata.title
  4. MediaStatus.currentTime
  5. MediaInformation.duration
  6. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.QUEUE_PREV
  7. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.SEEK_BACKWARD_30
  8. PLAY/PAUSE
  9. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.SEEK_FORWARD_30
  10. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.QUEUE_NEXT

Elementy sterujące dźwiękiem

W przypadku MetadataType.MUSIC_TRACK obiekt elementów sterujących interfejsu na inteligentnych ekranach będzie wyświetlany w ten sposób:

Obraz przedstawiający odtwarzaną muzykę z nałożonymi na siebie elementami sterującymi interfejsu

  1. --playback-logo-image
  2. MusicTrackMediaMetadata.albumName
  3. MusicTrackMediaMetadata.title
  4. MusicTrackMediaMetadata.albumArtist
  5. MusicTrackMediaMetadata.images[0]
  6. MediaStatus.currentTime
  7. MediaInformation.duration
  8. ControlsSlot.SLOT_SECONDARY_1: ControlsButton.NO_BUTTON
  9. ControlsSlot.SLOT_PRIMARY_1: ControlsButton.QUEUE_PREV
  10. PLAY/PAUSE
  11. ControlsSlot.SLOT_PRIMARY_2: ControlsButton.QUEUE_NEXT
  12. ControlsSlot.SLOT_SECONDARY_2: ControlsButton.NO_BUTTON

Aktualizowanie obsługiwanych poleceń multimedialnych

Obiekt elementów sterujących interfejsu określa też, czy wyświetlany jest ControlsButton na podstawie MediaStatus.supportedMediaCommands.

Gdy wartość supportedMediaCommands jest równa ALL_BASIC_MEDIA, domyślny układ elementu sterującego wygląda tak:

Obraz elementów sterujących odtwarzacza: pasek postępu, przycisk „Odtwórz”, włączone przyciski „Przeskocz do przodu” i „Przeskocz do tyłu”

Gdy wartość supportedMediaCommands jest równa ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT, domyślny układ elementu sterującego wygląda tak:

Obraz elementów sterujących odtwarzaczem: pasek postępu, przycisk „Odtwórz”, przyciski „Przeskocz do przodu” i „Przeskocz do tyłu” oraz włączone przyciski „Poprzednia kolejka” i „Następny w kolejce”

Gdy wartość obsługiwanychMediaCommands wynosi PAUSE | QUEUE_PREV | QUEUE_NEXT, domyślny układ elementu sterującego wygląda tak:

Obraz elementów sterujących odtwarzaczem: pasek postępu, przycisk „Odtwórz” oraz przyciski „Poprzednia kolejka” i „Następny w kolejce” są włączone

Jeśli ścieżki tekstowe są dostępne, przycisk napisów będzie zawsze wyświetlany na pozycji SLOT_1.

Obraz elementów sterujących odtwarzaczem: pasek postępu, przycisk „Odtwórz”, „Przeskocz do przodu” i „Przeskocz do tyłu”, przyciski „Poprzednia kolejka” i „Następny w kolejce” oraz przyciski „Napisy” włączone

Aby dynamicznie zmieniać wartość supportedMediaCommands po uruchomieniu kontekstu odbiorcy, możesz wywołać PlayerManager.setSupportedMediaCommands w celu zastąpienia wartości. Możesz też dodać nowe polecenie addSupportedMediaCommands lub usunąć istniejące, używając polecenia removeSupportedMediaCommands.

Dostosowywanie przycisków sterujących

Opcje możesz dostosować za pomocą PlayerDataBinder. Dodaj ten kod do pliku js/receiver.js pod elementami dotykowymi, aby ustawić pierwsze miejsce na elementy sterujące:

...

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    // Clear default buttons and re-assign
    touchControls.clearDefaultSlotAssignments();
    touchControls.assignButton(
      cast.framework.ui.ControlsSlot.SLOT_PRIMARY_1,
      cast.framework.ui.ControlsButton.SEEK_BACKWARD_30
    );
  });

context.start();

11. Wdrażanie przeglądania multimediów na inteligentnych ekranach

Przeglądanie multimediów to funkcja odbiornika CAF, która pozwala użytkownikom odkrywać dodatkowe treści na urządzeniach dotykowych. W tym celu trzeba użyć PlayerDataBinder do skonfigurowania interfejsu użytkownika BrowseContent. Następnie możesz wypełnić go wartością BrowseItems w zależności od treści, które chcesz wyświetlać.

BrowseContent

Poniżej znajdziesz przykład interfejsu użytkownika BrowseContent i jego właściwości:

Obraz interfejsu PrzeglądajContent, na którym widoczne są 2 miniatury filmów i część trzeciej

  1. BrowseContent.title
  2. BrowseContent.items

Format obrazu

Aby wybrać najlepszy współczynnik proporcji dla komponentów z obrazem, użyj pola targetAspectRatio property. Pakiet SDK odbiornika CAF obsługuje 3 formaty obrazu: SQUARE_1_TO_1, PORTRAIT_2_TO_3 oraz LANDSCAPE_16_TO_9.

BrowseItem

Użyj parametru BrowseItem, aby wyświetlić tytuł, podtytuł, czas trwania i obraz każdego elementu:

Obraz interfejsu PrzeglądajContent, na którym widoczne są 2 miniatury filmów i część trzeciej

  1. BrowseItem.image
  2. BrowseItem.duration
  3. BrowseItem.title
  4. BrowseItem.subtitle

Ustaw dane przeglądania multimediów

Możesz udostępnić listę treści multimedialnych do przeglądania, dzwoniąc pod numer setBrowseContent. Dodaj ten kod do pliku js/receiver.js poniżej elementu playerDataBinder i w detektorze zdarzeń MEDIA_CHANGED, aby określić elementy przeglądania za pomocą tytułu „Następny”.

// Optimizing for smart displays
const touchControls = cast.framework.ui.Controls.getInstance();
const playerData = new cast.framework.ui.PlayerData();
const playerDataBinder = new cast.framework.ui.PlayerDataBinder(playerData);

...

let browseItems = getBrowseItems();

function getBrowseItems() {
  let browseItems = [];
  makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
  .then(function (data) {
    for (let key in data) {
      let item = new cast.framework.ui.BrowseItem();
      item.entity = key;
      item.title = data[key].title;
      item.subtitle = data[key].description;
      item.image = new cast.framework.messages.Image(data[key].poster);
      item.imageType = cast.framework.ui.BrowseImageType.MOVIE;
      browseItems.push(item);
    }
  });
  return browseItems;
}

let browseContent = new cast.framework.ui.BrowseContent();
browseContent.title = 'Up Next';
browseContent.items = browseItems;
browseContent.targetAspectRatio = cast.framework.ui.BrowseImageAspectRatio.LANDSCAPE_16_TO_9;

playerDataBinder.addEventListener(
  cast.framework.ui.PlayerDataEventType.MEDIA_CHANGED,
  (e) => {
    if (!e.value) return;

    ....

    // Media browse
    touchControls.setBrowseContent(browseContent);
  });

Kliknięcie elementu przeglądania multimediów wywoła przechwytywanie LOAD. Dodaj ten kod do elementu przechwytującego LOAD, aby zmapować obiekt request.media.contentId na element request.media.entity z elementu przeglądania multimediów:

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD,
    request => {
      ...

      // Map contentId to entity
      if (request.media && request.media.entity) {
        request.media.contentId = request.media.entity;
      }

      return new Promise((resolve, reject) => {
            ...
        });
    });

Możesz też ustawić obiekt BrowseContent na null, aby usunąć interfejs przeglądania multimediów.

12. Debugowanie aplikacji odbierających

Pakiet Cast pickupr SDK to inna opcja dla programistów, która pozwala łatwo debugować aplikacje odbiornika za pomocą interfejsu CastDebugLogger API i powiązanego z nim narzędzia Command and Control (CaC) do przechwytywania dzienników.

Zdarzenie inicjujące

Aby zastosować interfejs API, dodaj skrypt źródłowy CastDebugLogger w pliku index.html. Źródło powinno być zadeklarowane w tagu <head> po zadeklarowaniu pakietu SDK Cast Odbieranie.

<head>
  ...
  <script src="//www.gstatic.com/cast/sdk/libs/caf_receiver/v3/cast_receiver_framework.js"></script>
  <!-- Cast Debug Logger -->
  <script src="//www.gstatic.com/cast/sdk/libs/devtools/debug_layer/caf_receiver_logger.js"></script>
</head>

W js/receiver.js na górze pliku i pod playerManager dodaj ten kod, aby pobrać wystąpienie CastDebugLogger i włączyć rejestrator:

const context = cast.framework.CastReceiverContext.getInstance();
const playerManager = context.getPlayerManager();

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();
const LOG_TAG = 'MyAPP.LOG';

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

Gdy rejestrator debugowania jest włączony, na odbiorniku pojawi się nakładka z tekstem DEBUG MODE.

Obraz przedstawiający odtwarzany film z komunikatem „TRYB DEBUGOWANIA” na czerwonym tle w lewym górnym rogu ramki

Zdarzenia odtwarzacza dziennika

Za pomocą CastDebugLogger możesz łatwo rejestrować zdarzenia odtwarzacza, które są uruchamiane przez pakiet SDK odbiornika CAF, a także rejestrować dane zdarzeń za pomocą różnych poziomów rejestratora. Konfiguracja loggerLevelByEvents używa elementów cast.framework.events.EventType i cast.framework.events.category do określania, które zdarzenia będą rejestrowane.

Dodaj ten kod pod deklaracją castDebugLogger, aby zapisywać informacje o wywołaniu zdarzenia CORE odtwarzacza lub przekazaniu zmiany mediaStatus:

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

Komunikaty logu i tagi niestandardowe

Interfejs CastDebugLogger API umożliwia tworzenie komunikatów dziennika w różnych kolorach, które są wyświetlane na nakładce debugowania odbiornika. Dostępne są te metody rejestrowania, uporządkowane w kolejności od najwyższego do najniższego priorytetu:

  • castDebugLogger.error(custom_tag, message);
  • castDebugLogger.warn(custom_tag, message);
  • castDebugLogger.info(custom_tag, message);
  • castDebugLogger.debug(custom_tag, message);

W przypadku każdej metody rejestrowania pierwszym parametrem jest tag niestandardowy. Może to być dowolny ciąg identyfikujący Cię, który uznasz za ważny. CastDebugLogger używa tagów do filtrowania logów. Zastosowanie tagów zostało szczegółowo wyjaśnione poniżej. Drugi parametr to komunikat logu.

Aby pokazać logi w działaniu, dodaj logi do przechwytywania LOAD.

playerManager.setMessageInterceptor(
  cast.framework.messages.MessageType.LOAD,
  request => {
    castDebugLogger.info(LOG_TAG, 'Intercepting LOAD request');

    // Map contentId to entity
    if (request.media && request.media.entity) {
      request.media.contentId = request.media.entity;
    }

    return new Promise((resolve, reject) => {
      // Fetch content repository by requested contentId
      makeRequest('GET', 'https://storage.googleapis.com/cpe-sample-media/content.json')
        .then(function (data) {
          let item = data[request.media.contentId];
          if(!item) {
            // Content could not be found in repository
            castDebugLogger.error(LOG_TAG, 'Content not found');
            reject();
          } else {
            // Adjusting request to make requested content playable
            request.media.contentUrl = item.stream.dash;
            request.media.contentType = 'application/dash+xml';
            castDebugLogger.warn(LOG_TAG, 'Playable URL:', request.media.contentUrl);

            // Add metadata
            let metadata = new cast.framework.messages.MovieMediaMetadata();
            metadata.metadataType = cast.framework.messages.MetadataType.MOVIE;
            metadata.title = item.title;
            metadata.subtitle = item.author;

            request.media.metadata = metadata;

            // Resolve request
            resolve(request);
          }
      });
    });
  });

Możesz kontrolować, które komunikaty pojawiają się na nakładce debugowania, ustawiając poziom logowania w loggerLevelByTags dla każdego tagu niestandardowego. Na przykład włączenie tagu niestandardowego z poziomem rejestrowania cast.framework.LoggerLevel.DEBUG spowoduje wyświetlenie wszystkich dodanych komunikatów z komunikatami o błędach, ostrzeżeniach, informacjach i dziennikach debugowania. Włączenie tagu niestandardowego z poziomem WARNING spowoduje wyświetlanie tylko komunikatów o błędach i ostrzeżeń.

Konfiguracja loggerLevelByTags jest opcjonalna. Jeśli tag niestandardowy nie jest skonfigurowany na poziomie rejestratora, na nakładce debugowania będą się wyświetlać wszystkie komunikaty dziennika.

Dodaj ten kod pod rejestratorem zdarzeń CORE:

// Set verbosity level for Core events.
castDebugLogger.loggerLevelByEvents = {
  'cast.framework.events.category.CORE': cast.framework.LoggerLevel.INFO,
  'cast.framework.events.EventType.MEDIA_STATUS': cast.framework.LoggerLevel.DEBUG
}

// Set verbosity level for custom tags.
castDebugLogger.loggerLevelByTags = {
    [LOG_TAG]: cast.framework.LoggerLevel.DEBUG,
};

Nakładka debugowania

Rejestrator debugowania Cast udostępnia na odbiorniku nakładkę debugowania, która umożliwia wyświetlanie niestandardowych komunikatów dziennika na urządzeniu przesyłającym. Użyj przycisku showDebugLogs, aby przełączać nakładkę debugowania, i przycisku clearDebugLogs, aby wyczyścić komunikaty dziennika na nakładce.

Dodaj ten kod, aby wyświetlić podgląd nakładki debugowania na odbiorniku.

context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      // Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
      castDebugLogger.setEnabled(true);

      // Show debug overlay
      castDebugLogger.showDebugLogs(true);

      // Clear log messages on debug overlay
      castDebugLogger.clearDebugLogs();
  }
});

Obraz przedstawiający nakładkę debugowania, czyli listę komunikatów dziennika debugowania na półprzezroczystym tle na klatce filmu

13. Gratulacje

Wiesz już, jak utworzyć niestandardową aplikację odbiornika internetowego za pomocą pakietu SDK Cast Web pickupr.

Więcej informacji znajdziesz w przewodniku dla programistów dotyczącym komponentu WebView.