Tworzenie niestandardowego odbiornika internetowego

1. Przegląd

Logo Google Cast

Z tego ćwiczenia z programowania dowiesz się, jak utworzyć niestandardową aplikację odbiornika internetowego do odtwarzania treści na urządzeniach obsługujących Cast.

Co to jest Google Cast?

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

Pakiet Google Cast SDK umożliwia aplikacji sterowanie urządzeniami obsługującymi Google Cast (np. telewizorem lub systemem dźwiękowym). Pakiet Cast SDK udostępnia niezbędne komponenty interfejsu na podstawie listy kontrolnej projektu Google Cast.

Lista kontrolna projektu Google Cast została opracowana, aby zapewnić prostotę i przewidywalność korzystania z Cast na wszystkich obsługiwanych platformach. Więcej informacji

Co będziemy tworzyć?

Po ukończeniu tego kursu będziesz mieć aplikację HTML5, która będzie działać jako Twój własny odbiornik niestandardowy, który może wyświetlać treści wideo na urządzeniach obsługujących Cast.

Czego się nauczysz

  • Jak przygotować się do tworzenia odbiorników.
  • Podstawowe informacje o odbiorniku obsługującym Casta, który jest oparty na platformie aplikacji Cast.
  • Jak odbierać przesyłany film.
  • Jak zintegrować narzędzie Debug Logger.
  • Jak zoptymalizować odbiornik pod kątem inteligentnych wyświetlaczy.

Czego potrzebujesz

Doświadczenie

  • Musisz mieć wcześniejszą wiedzę na temat tworzenia stron internetowych.
  • Musisz też mieć doświadczenie w oglądaniu telewizji.

Jak zamierzasz korzystać z tego samouczka?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie w tworzeniu aplikacji internetowych?

Początkujący Średnio zaawansowany Zaawansowany

Jak oceniasz oglądanie telewizji?

Początkujący Średnio zaawansowany Zaawansowany

2. Pobieranie przykładowego kodu

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

i rozpakuj pobrany plik ZIP.

3. Wdrażanie odbiornika lokalnie

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

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

Uruchamianie serwera

Po skonfigurowaniu wybranej usługi otwórz app-start i uruchom serwer.

Zanotuj adres URL hostowanego odbiornika. Będzie on potrzebny w następnej sekcji.

4. Rejestrowanie aplikacji w Konsoli programisty Cast

Aby móc uruchamiać na urządzeniach Chromecast niestandardowy odbiornik, taki jak ten utworzony w tym ćwiczeniu, musisz zarejestrować aplikację. Po zarejestrowaniu aplikacji otrzymasz identyfikator aplikacji, którego aplikacja wysyłająca musi używać do wykonywania wywołań interfejsu API, np. do uruchamiania aplikacji odbierającej.

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

Kliknij „Dodaj nową aplikację”.

Obraz ekranu „New Receiver Application” (Nowa aplikacja odbiornika) z wyróżnioną opcją „Custom Receiver” (Odbiornik niestandardowy)

Wybierz „Odbiornik niestandardowy” – to właśnie tworzymy.

Obraz ekranu „Nowy odbiornik niestandardowy” z adresem URL wpisywanym w polu „Adres URL aplikacji odbiornika”

Wpisz dane nowego odbiorcy, używając adresu URL, który został Ci przypisany.

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

Musisz też zarejestrować urządzenie przesyłające Google Cast, aby przed opublikowaniem aplikacji odbiornika mogło ono uzyskać do niej dostęp. Po opublikowaniu aplikacji odbiornika będzie ona dostępna na wszystkich urządzeniach Google Cast. Na potrzeby tego modułu zalecamy pracę z nieopublikowaną aplikacją odbiorcy.

Obraz Konsoli programisty Google Cast SDK z wyróżnionym przyciskiem „Add New Device” (Dodaj nowe urządzenie)

Kliknij „Dodaj nowe urządzenie”.

Obraz okna „Dodaj urządzenie odbiornika Cast”

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

Zanim odbiornik i urządzenie będą gotowe do testowania, minie 5–15 minut. Po odczekaniu 5–15 minut musisz ponownie uruchomić urządzenie przesyłające.

5. Uruchamianie przykładowej aplikacji

Logo Google Chrome

Zanim nasza nowa aplikacja odbiornika będzie gotowa do testowania, zobaczmy, jak wygląda przykładowa ukończona aplikacja odbiornika. Odbiornik, który zamierzamy utworzyć, będzie w stanie odtwarzać multimedia przy użyciu strumieniowego przesyłania danych z adaptacyjną szybkością transmisji bitów (będziemy używać przykładowych treści zakodowanych na potrzeby dynamicznego adaptacyjnego strumieniowego przesyłania danych przez HTTP (DASH)).

W przeglądarce otwórz narzędzie do zarządzania i kontroli.

Ilustracja przedstawiająca kartę „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC)

  1. Powinno się wyświetlić nasze narzędzie CaC.
  2. Użyj domyślnego przykładowego identyfikatora odbiornika „CC1AD845” i kliknij przycisk „Set App ID” (Ustaw identyfikator aplikacji).
  3. W lewym górnym rogu kliknij przycisk Cast i wybierz urządzenie przesyłające Google Cast.

Ilustracja przedstawiająca kartę „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC), która wskazuje, że jest ono połączone z aplikacją odbiornika

  1. U góry kliknij kartę „Wczytaj multimedia”.

Obraz karty „Wczytaj multimedia” w narzędziu Command and Control (CaC)

  1. Aby odtworzyć przykładowy film, kliknij przycisk „Wczytaj według treści”.
  2. Film zacznie się odtwarzać na urządzeniu przesyłającym Google Cast, aby pokazać, jak wygląda podstawowa funkcjonalność odbiornika przy użyciu odbiornika domyślnego.

6. Przygotowywanie projektu początkowego

Musimy dodać obsługę Google Cast do pobranej aplikacji startowej. W tym ćwiczeniu będziemy używać tych terminów związanych z Google Cast:

  • aplikacja nadawcy jest uruchomiona na urządzeniu mobilnym lub laptopie,
  • na urządzeniu przesyłającym działa aplikacja odbiornika;

Teraz możesz rozbudowywać projekt początkowy za pomocą ulubionego edytora tekstu:

  1. W pobranych przykładowych kodach wybierz katalog ikona folderuapp-start.
  2. Otwórz js/receiver.js i index.html

Pamiętaj, że w trakcie wykonywania tego samouczka http-server powinno wykrywać wprowadzane przez Ciebie zmiany. Jeśli zauważysz, że tak nie jest, zamknij i ponownie uruchom http-server.

Projektowanie aplikacji

Aplikacja odbiorcy inicjuje sesję Cast i pozostaje w trybie gotowości, dopóki nie nadejdzie żądanie LOAD (czyli polecenie odtworzenia multimediów) od nadawcy.

Aplikacja składa się z jednego głównego widoku zdefiniowanego w pliku index.html i jednego pliku JavaScript o nazwie js/receiver.js, który zawiera całą logikę działania odbiornika.

index.html

Ten plik HTML będzie zawierać interfejs aplikacji odbiorcy. Na razie jest pusty, ale będziemy go uzupełniać w trakcie tego modułu.

receiver.js

Ten skrypt będzie zarządzać całą logiką aplikacji odbiorcy. Obecnie jest to tylko pusty plik, ale w następnej sekcji przekształcimy go w w pełni funkcjonalny odbiornik Cast za pomocą zaledwie kilku wierszy kodu.

7. podstawowy odbiornik Cast,

Podstawowy odbiornik Cast zainicjuje sesję Cast podczas uruchamiania. Jest to konieczne, aby poinformować wszystkie połączone aplikacje wysyłające, że uruchomienie odbiornika się powiodło. Dodatkowo nowy pakiet SDK jest wstępnie skonfigurowany do obsługi strumieniowego przesyłania multimediów z adaptacyjną szybkością transmisji bitów (przy użyciu DASH, HLS i Smooth Streaming) oraz zwykłych plików MP4. Spróbujmy.

Inicjowanie

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

<head>
  ...

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

Dodaj poniższy kod do index.html <body> przed <footer> loading receiver.js,, aby zapewnić pakietowi SDK odbiornika miejsce na wyświetlenie domyślnego interfejsu odbiornika, który jest dostarczany ze skryptem, który właśnie dodajesz.

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

Teraz musimy zainicjować pakiet SDK w js/receiver.js, który składa się z:

  • uzyskanie odwołania do CastReceiverContext, głównego punktu wejścia do całego pakietu SDK odbiornika;
  • przechowywanie odwołania do obiektu PlayerManager, który obsługuje odtwarzanie i zapewnia wszystkie niezbędne punkty zaczepienia do włączenia własnej logiki niestandardowej;
  • inicjowanie pakietu SDK przez wywołanie start()CastReceiverContext;

Dodać te boty do pokoju „js/receiver.js”?

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

context.start();

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

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

W przeglądarce otwórz narzędzie do zarządzania i kontroli.

Ilustracja przedstawiająca kartę „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC)

W polu wpisz swój identyfikator aplikacji zarejestrowany wcześniej i kliknij „Set App ID” (Ustaw identyfikator aplikacji). Ta opcja nakazuje narzędziu używanie odbiornika podczas rozpoczynania sesji przesyłania.

Przesyłanie multimediów

Aby odtworzyć multimedia na urządzeniu przesyłającym, musisz wykonać te czynności:

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

W pierwszej podstawowej próbie wypełnimy pole MediaInfo adresem URL odtwarzanego zasobu (przechowywanym w MediaInfo.contentUrl).

Prawdziwy nadawca używa w atrybucie MediaInfo.contentId identyfikatora multimediów specyficznego dla aplikacji. Odbiornik używa contentId jako identyfikatora do wykonywania odpowiednich wywołań interfejsu API backendu w celu rozpoznania rzeczywistego adresu URL zasobu i ustawienia go na MediaInfo.contentUrl. Odbiornik będzie też obsługiwać zadania takie jak uzyskiwanie licencji DRM czy wstawianie informacji o przerwach na reklamy.

W następnej sekcji rozszerzymy funkcjonalność odbiornika, aby mógł to robić. Na razie kliknij ikonę przesyłania i wybierz urządzenie, aby otworzyć odbiornik.

Ilustracja przedstawiająca kartę „Cast Connect & Logger Controls” w narzędziu Command and Control (CaC), która wskazuje, że jest ono połączone z aplikacją odbiornika

Otwórz kartę „Load Media” (Wczytaj multimedia) i kliknij przycisk „Load by Content” (Wczytaj według treści). Odbiornik powinien rozpocząć odtwarzanie przykładowych treści.

Obraz karty „Wczytaj multimedia” w narzędziu Command and Control (CaC)

Pakiet SDK odbiornika od razu obsługuje:

  • Inicjowanie sesji przesyłania
  • Obsługuj przychodzące żądania LOAD od nadawców, które zawierają zasoby do odtworzenia.
  • Zapewnij podstawowy interfejs odtwarzacza gotowy do wyświetlania na dużym ekranie.

Zanim przejdziesz do następnej sekcji, w której rozszerzymy nasz odbiornik, aby komunikował się z prostym przykładowym interfejsem API w celu obsługi przychodzących LOAD żądań od nadawców, możesz zapoznać się z narzędziem CaC i jego kodem.

9. Integracja z zewnętrznym interfejsem API

Podobnie jak w przypadku większości deweloperów, którzy w aplikacjach działających w rzeczywistych warunkach korzystają z odbiorników Cast, zmodyfikujemy nasz odbiornik, aby obsługiwał żądania LOAD, które odwołują się do docelowych treści multimedialnych za pomocą klucza interfejsu API, zamiast wysyłać adres URL odtwarzanego zasobu.

Aplikacje zwykle robią to z tych powodów:

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

Ta funkcja jest zaimplementowana głównie w metodzie PlayerManager setMessageInterceptor(). Umożliwia to przechwytywanie wiadomości przychodzących według typu i modyfikowanie ich, zanim dotrą do wewnętrznego modułu obsługi wiadomości w pakiecie SDK. W tej sekcji zajmujemy się żądaniami LOAD, w przypadku których wykonamy te czynności:

  • Przeczytaj przychodzące LOAD żądanie i jego niestandardowe contentId.
  • Wywołaj nasz interfejs API, aby wyszukać zasób, który można przesyłać strumieniowo, na podstawie jego contentId.GET
  • Zmodyfikuj żądanie LOAD, dodając adres URL transmisji.
  • Zmodyfikuj obiekt MediaInformation, aby ustawić parametry typu strumienia.
  • Przekaż prośbę do pakietu SDK w celu odtworzenia lub odrzuć polecenie, jeśli nie możemy znaleźć żądanych multimediów.

Przykładowy interfejs API pokazuje punkty zaczepienia pakietu SDK do dostosowywania typowych zadań odbiornika, przy jednoczesnym zachowaniu w większości gotowego środowiska.

Przykładowy interfejs API

Otwórz w przeglądarce adres https://storage.googleapis.com/cpe-sample-media/content.json i zapoznaj się z naszym przykładowym katalogiem filmów. Treści zawierają adresy URL obrazów plakatów w formacie PNG, a także strumienie DASH i HLS. Strumienie DASH i HLS wskazują na zdemuksowane źródła wideo i audio przechowywane w kontenerach z plikami MP4 podzielonymi na fragmenty.

{
  "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 (np. bbb, fbb_ad) na adres URL strumienia po wywołaniu odbiorcy za pomocą żądania LOAD.

Przechwyć żądanie LOAD

W tym kroku utworzymy przechwytujący wczytywanie z funkcją, która wysyła żądanie XHR do hostowanego pliku JSON. Po uzyskaniu JSON pliku przeanalizujemy jego zawartość 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 wczytywania w przypadku treści DASH.

Korzystanie z przykładowych treści DASH API

Po przygotowaniu przechwytującego ładowanie określimy typ treści dla odbiorcy. Te informacje zawierają adres URL playlisty reklamy nadrzędnej i typ MIME strumienia. Dodaj ten kod do pliku js/receiver.js w LOAD interceptorze Promise():

...
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 sekcji Testowanie, aby spróbować wczytać treści DASH. Jeśli zamiast tego chcesz przetestować wczytywanie treści HLS, przejdź do następnego kroku.

Korzystanie z przykładowych treści HLS API

Przykładowy interfejs API zawiera treści HLS i DASH. Oprócz ustawienia parametru contentType, tak jak w poprzednim kroku, żądanie wczytania będzie wymagać dodatkowych właściwości, aby można było używać adresów URL HLS przykładowego interfejsu API. Gdy odbiornik jest skonfigurowany do odtwarzania strumieni HLS, domyślnym oczekiwanym typem kontenera jest strumień transportowy (TS). W rezultacie odbiorca spróbuje otworzyć przykładowe strumienie MP4 w formacie TS, jeśli zmodyfikowana zostanie tylko właściwość contentUrl. W żądaniu wczytania należy zmodyfikować obiekt MediaInformation, dodając do niego dodatkowe właściwości, aby odbiorca wiedział, że treść jest typu MP4, a nie TS. Dodaj ten kod do pliku js/receiver.js w interceptorze wczytywania, aby zmodyfikować właściwości contentUrlcontentType. Dodaj też właściwości HlsSegmentFormatHlsVideoSegmentFormat.

...
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 do sterowania i zarządzania (CaC) i ustaw identyfikator aplikacji na identyfikator aplikacji odbiorcy. Wybierz urządzenie za pomocą przycisku Cast.

Otwórz kartę „Wczytaj multimedia”. Tym razem usuń tekst w polu „Adres URL treści” obok przycisku „Wczytaj według treści”, co spowoduje, że nasza aplikacja wyśle żądanie LOAD zawierające tylko odwołanie contentId do naszych multimediów.

Obraz karty „Wczytaj multimedia” w narzędziu Command and Control (CaC)

Zakładając, że zmiany w odbiorniku zostały wprowadzone prawidłowo, przechwytujący powinien przekształcić obiekt MediaInfo w formę, którą pakiet SDK może odtworzyć na ekranie.

Kliknij przycisk „Load by Content” (Wczytaj według treści), aby sprawdzić, czy multimedia są odtwarzane prawidłowo. Możesz zmienić identyfikator Content ID na inny w pliku content.json.

10. Optymalizacja pod kątem inteligentnych wyświetlaczy

Inteligentne wyświetlacze to urządzenia z funkcją dotykową, które umożliwiają aplikacjom odbiornika obsługę elementów sterujących z funkcją dotykową.

W tej sekcji dowiesz się, jak zoptymalizować aplikację odbiorcy uruchamianą na inteligentnych wyświetlaczach i jak dostosować elementy sterujące odtwarzacza.

Dostęp do elementów sterujących interfejsu

Do obiektu UI Controls na inteligentnych wyświetlaczach można uzyskać dostęp za pomocą funkcji cast.framework.ui.Controls.GetInstance(). Dodaj do pliku js/receiver.js ten kod 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ć touchScreenOptimizedAppCastReceiverOptions. W tym ćwiczeniu używamy elementu <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Do każdego miejsca docelowego przypisywane są domyślne przyciski sterujące na podstawie MetadataTypeMediaStatus.supportedMediaCommands.

Sterowanie odtwarzaniem

W przypadku MetadataType.MOVIE, MetadataType.TV_SHOWMetadataType.GENERIC obiekt UI Controls dla inteligentnych wyświetlaczy będzie wyświetlany jak w poniższym przykładzie.

Obraz przedstawiający odtwarzany film z elementami interfejsu na wierzchu

  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

Sterowanie 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 odtwarzanie muzyki z elementami interfejsu na wierzchu

  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 UI Controls określa też, czy ControlsButton jest wyświetlany, na podstawie wartości MediaStatus.supportedMediaCommands.

Gdy wartość supportedMediaCommands jest równa ALL_BASIC_MEDIA, domyślny układ elementów sterujących będzie wyglądać tak:

Grafika elementów sterujących odtwarzacza: pasek postępu, przycisk „Odtwórz”, przyciski „Przewiń do przodu” i „Przewiń do tyłu” są włączone.

Gdy wartość supportedMediaCommands jest równa ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT, domyślny układ elementów sterujących będzie wyglądać tak:

Obraz elementów sterujących odtwarzacza multimediów: pasek postępu, przycisk „Odtwórz”, przyciski „Przewiń do przodu” i „Przewiń do tyłu” oraz przyciski „Kolejka poprzednia” i „Kolejka następna” są włączone.

Gdy wartość supportedMediaCommands wynosi PAUSE | QUEUE_PREV | QUEUE_NEXT, domyślny układ sterowania będzie wyglądać tak:

Obraz elementów sterujących odtwarzacza multimediów: pasek postępu, przycisk „Odtwórz” oraz przyciski „Kolejka poprzednia” i „Kolejka następna”

Gdy ścieżki tekstowe są dostępne, przycisk napisów jest zawsze wyświetlany w pozycji SLOT_1.

Obraz elementów sterujących odtwarzacza multimediów: pasek postępu, przycisk „Odtwórz”, przyciski „Przewiń do przodu” i „Przewiń do tyłu”, przyciski „Kolejka poprzednia” i „Kolejka następna” oraz włączone przyciski „Napisy”

Aby dynamicznie zmienić wartość supportedMediaCommands po rozpoczęciu kontekstu odbiorcy, możesz wywołać PlayerManager.setSupportedMediaCommands, aby zastąpić wartość. Możesz też dodać nowe polecenie, klikając addSupportedMediaCommands, lub usunąć istniejące polecenie, klikając removeSupportedMediaCommands.

Dostosowywanie przycisków sterujących

Możesz dostosować elementy sterujące za pomocą funkcji PlayerDataBinder. Dodaj ten kod do pliku js/receiver.js poniżej elementu touchControls, aby ustawić pierwszy slot elementów sterujących:

...

// 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 umożliwia użytkownikom przeglądanie dodatkowych treści na urządzeniach dotykowych. Aby to zrobić, użyj PlayerDataBinder do ustawienia interfejsu BrowseContent. Następnie możesz wypełnić go BrowseItems na podstawie treści, które chcesz wyświetlać.

BrowseContent

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

Obraz interfejsu BrowseContent z 2 miniatury filmów i fragmentem trzeciej

  1. BrowseContent.title
  2. BrowseContent.items

Współczynnik proporcji

Użyj ikony targetAspectRatio property, aby wybrać najlepszy współczynnik proporcji dla komponentów z obrazem. Pakiet CAF Receiver SDK obsługuje 3 formaty obrazu: SQUARE_1_TO_1, PORTRAIT_2_TO_3LANDSCAPE_16_TO_9.

BrowseItem

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

Obraz interfejsu BrowseContent z 2 miniatury filmów i fragmentem trzeciej

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

Ustawianie danych przeglądania multimediów

Aby udostępnić listę treści multimedialnych do przeglądania, wywołaj funkcję setBrowseContent. Dodaj poniższy kod do pliku js/receiver.js pod tagiem playerDataBinder i w detektorze zdarzeń MEDIA_CHANGED, aby ustawić przeglądanie elementów z tytułem „Następne”.

// 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 spowoduje uruchomienie LOAD interfejsu. Dodaj ten kod do interfejsu LOAD, aby zmapować request.media.contentId na 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 odbiorczych

Pakiet Cast Receiver SDK zapewnia programistom kolejną opcję łatwego debugowania aplikacji odbiornika za pomocą interfejsu CastDebugLogger API i powiązanego narzędzia Command and Control (CaC) do rejestrowania dzienników.

Zdarzenie inicjujące

Aby zintegrować interfejs API, dodaj skrypt źródłowy CastDebugLogger do pliku index.html. Źródło należy zadeklarować w tagu <head> po deklaracji pakietu SDK odbiornika Cast.

<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 pliku js/receiver.js u góry i pod playerManager dodaj ten kod, aby pobrać instancję 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 rejestrowanie debugowania jest włączone, na odbiorniku wyświetli się nakładka z symbolem DEBUG MODE.

Obraz przedstawiający odtwarzany film z komunikatem „DEBUG MODE” (TRYB DEBUGOWANIA) wyświetlanym na czerwonym tle w lewym górnym rogu kadru

Rejestrowanie zdarzeń odtwarzacza

Za pomocą CastDebugLogger możesz łatwo rejestrować zdarzenia odtwarzacza wywoływane przez pakiet SDK odbiornika CAF i używać różnych poziomów rejestrowania do rejestrowania danych zdarzeń. Konfiguracja loggerLevelByEvents używa pól cast.framework.events.EventTypecast.framework.events.category do określania, które zdarzenia będą rejestrowane.

Aby rejestrować zdarzenie CORE odtwarzacza lub zmianę mediaStatus, dodaj ten kod pod deklaracją castDebugLogger:

// 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 logów i tagi niestandardowe

Interfejs CastDebugLogger API umożliwia tworzenie komunikatów dziennika, które pojawiają się na nakładce debugowania odbiornika w różnych kolorach. Dostępne są te metody rejestrowania, wymienione 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 znaków, który ma dla Ciebie znaczenie. CastDebugLogger używa tagów do filtrowania dzienników. Sposób używania tagów opisujemy szczegółowo poniżej. Drugi parametr to komunikat logu.

Aby zobaczyć logi w działaniu, dodaj je do LOAD interfejsu przechwytującego.

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 określić, które wiadomości mają się wyświetlać na nakładce debugowania, ustawiając poziom rejestrowania w parametrze loggerLevelByTags dla każdego tagu niestandardowego. Na przykład włączenie tagu niestandardowego z poziomem logowania cast.framework.LoggerLevel.DEBUG spowoduje wyświetlenie wszystkich wiadomości dodanych z komunikatami o błędach, ostrzeżeniami, informacjami i komunikatami dziennika debugowania. Włączenie tagu niestandardowego na poziomie WARNING spowoduje wyświetlanie tylko komunikatów o błędach i ostrzeżeń.

Konfiguracja loggerLevelByTags jest opcjonalna. Jeśli tag niestandardowy nie jest skonfigurowany dla poziomu rejestratora, wszystkie komunikaty dziennika będą wyświetlane na nakładce debugowania.

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 nakładkę debugowania na odbiorniku, aby wyświetlać niestandardowe komunikaty dziennika na urządzeniu przesyłającym. Użyj klawisza showDebugLogs, aby przełączać nakładkę debugowania, a klawisza clearDebugLogs, aby wyczyścić wiadomości 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, listę komunikatów dziennika debugowania na półprzezroczystym tle na klatce wideo

13. Gratulacje

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

Więcej informacji znajdziesz w przewodniku dla programistów dotyczącym odbiornika internetowego.