Tworzenie niestandardowego odbiornika internetowego

1. Omówienie

Logo Google Cast

Z tego ćwiczenia z programowania dowiesz się, jak utworzyć aplikację Custom Web Receiver, która umożliwia odtwarzanie treści na urządzeniach z wsparciem dla Casta.

Co to jest Google Cast?

Google Cast umożliwia użytkownikom 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 audio). Pakiet SDK Cast udostępnia niezbędne komponenty interfejsu użytkownika na podstawie listy kontrolnej interfejsu Google Cast.

Lista kontrolna dotycząca projektowania Google Cast została przygotowana, aby zapewnić użytkownikom prosty i przewidywalny sposób korzystania z Casta na wszystkich obsługiwanych platformach. Więcej informacji

Co będziemy budować?

Po ukończeniu tego ćwiczenia będziesz mieć aplikację HTML5, która będzie działać jako niestandardowy odbiornik i będzie wyświetlać treści wideo na urządzeniach obsługujących Google Cast.

Czego się nauczysz

  • Jak przygotować się do tworzenia odbiornika.
  • Podstawy odbiornika obsługującego Cast na podstawie interfejsu Cast Application Framework.
  • Jak odbierać filmy przesyłane przez Chromecasta.
  • Jak zintegrować Debug Logger
  • Jak zoptymalizować odbiornik pod kątem inteligentnych ekranów.

Czego potrzebujesz

Doświadczenie

  • Musisz mieć już wcześniejsze doświadczenie w programowaniu stron internetowych.
  • Wymagamy też wcześniejszej wiedzy na temat oglądania telewizji. :)

Jak będziesz korzystać z tego samouczka?

Przeczytaj go tylko Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenia z tworzeniem 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 swój komputer...

i rozpakuj pobrany plik ZIP.

3. Lokalne wdrożenie odbiornika

Aby można było używać odbiornika internetowego z urządzeniem Google Cast, musi on być hostowany w miejscu, do którego może dotrzeć urządzenie Google Cast. Jeśli masz już serwer, który obsługuje protokół https, pomiń te instrukcje i zapisz adres URL, ponieważ będzie Ci on potrzebny w następnej sekcji.

Jeśli nie masz serwera, możesz użyć hostingu Firebase lub ngrok.

Uruchamianie serwera

Gdy skonfigurujesz wybraną usługę, otwórz app-start i uruchom serwer.

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

4. Rejestrowanie aplikacji w Konsoli programisty Cast

Aby móc uruchamiać niestandardowy odbiornik utworzony w tym ćwiczeniu na Chromecastach, musisz zarejestrować aplikację. Po zarejestrowaniu aplikacji otrzymasz identyfikator aplikacji, którego aplikacja nadawcy musi używać do wykonywania wywołań interfejsu API, np. do uruchamiania aplikacji odbiorcy.

Obraz konsoli deweloperów Google Cast SDK z wyróżnionym przyciskiem „Dodaj nową aplikację”

Kliknij „Dodaj nową aplikację”.

Obraz ekranu „New Receiver Application” (Nowa aplikacja odbiornika) z zaznaczoną opcją „Custom Receiver” (Niestandardowy odbiornik)

Wybierz „Custom Receiver” (niestandardowy odbiornik).

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

Wpisz dane nowego odbiornika, pamiętaj, aby użyć adresu URL

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

Musisz też zarejestrować urządzenie Google Cast, by mogło ono uzyskiwać dostęp do aplikacji odbiornika przed jej opublikowaniem. Po opublikowaniu aplikacja odbiornika będzie dostępna dla wszystkich urządzeń Google Cast. Na potrzeby tego modułu zalecamy korzystanie z nieopublikowanej aplikacji odbiorczej.

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

Kliknij „Dodaj nowe urządzenie”.

Obraz okna „Dodaj urządzenie odbierające przesyłanie”

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, gdy otwierasz konsolę dewelopera Google Cast SDK.

Urządzenie i odbiornik będą gotowe do testowania po 5–15 minutach. Po 5–15 minutach musisz zrestartować urządzenie z Castem.

5. Uruchamianie przykładowej aplikacji

Logo Google Chrome

Zanim nowa aplikacja odbiornika będzie gotowa do testowania, zobaczmy, jak wygląda gotowa aplikacja odbiornika. Odbiornik, który zamierzamy zbudować, będzie mógł odtwarzać media przy użyciu strumieniowego przesyłania danych z adaptacyjną szybkością transmisji bitów (użyjemy przykładowych treści zakodowanych w ramach dynamicznego adaptacyjnego strumieniowego przesyłania danych przez HTTP (DASH)).

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

Obraz karty „Ustawienia Cast Connect i Logger” w narzędziu Zarządzanie i kontrola

  1. Powinieneś/powinnaś zobaczyć nasze narzędzie do porównywania cen.
  2. Użyj domyślnego identyfikatora przykładowego odbiorcy „CC1AD845” i kliknij przycisk „Ustaw identyfikator aplikacji”.
  3. W lewym górnym rogu kliknij przycisk przesyłania i wybierz urządzenie Google Cast.

Obraz karty „Ustawienia Cast Connect i rejestratora” w narzędziu sterowania i kontroli (CaC), która wskazuje, że jest ono połączone z aplikacją odbiorczą

  1. Przejdź na kartę „Wczytaj multimedia” u góry.

Obraz karty „Wczytaj media” w narzędziu do zarządzania i kontroli

  1. Aby odtworzyć przykładowy film, kliknij przycisk „Wczytaj według treści”.
  2. Film zacznie się odtwarzać na urządzeniu z Google Cast, aby pokazać, jak działają podstawowe funkcje odbiornika domyślnego.

6. Przygotowanie projektu startowego

Musimy dodać obsługę Google Cast do pobranej przez Ciebie aplikacji startowej. Oto terminologia dotycząca Google Cast, której będziemy używać w tym ćwiczeniu z programowania:

  • aplikacja nadawcy działa na urządzeniu mobilnym lub laptopie,
  • na urządzeniu Google Cast działa aplikacja odbiornikowa.

Teraz możesz zacząć tworzyć projekt początkowy 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 pracy z tym laboratorium kodu http-server powinien rejestrować wprowadzane przez Ciebie zmiany. Jeśli nie, spróbuj zamknąć i ponownie uruchomić http-server.

Projektowanie aplikacji

Aplikacja odbiorcy inicjuje sesję Cast i czeka na żądanie LOAD (czyli na polecenie odtwarzania multimediów) od nadawcy.

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 umożliwiające odbiornik.

index.html

Ten plik HTML będzie zawierać interfejs aplikacji odbiorczej. Na razie jest pusty, ale będziemy go rozbudowywać w trakcie laboratorium kodu.

receiver.js

Ten skrypt będzie zarządzać całą logiką aplikacji odbiorczej. Obecnie jest to pusty plik, ale w następnej sekcji zamienimy go w pełnofunkcyjny odbiornik Cast za pomocą kilku linii kodu.

7. Podstawowy odbiornik Cast

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

Inicjowanie

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

<head>
  ...

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

Dodaj ten kod do index.html <body> przed tagiem <footer> loading receiver.js,, aby zapewnić pakietowi SDK odbiornika miejsce na wyświetlenie domyślnego interfejsu odbiornika, który jest dostarczany z dopiero co dodanym skryptem.

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

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

  • uzyskanie odwołania do CastReceiverContext, który jest głównym punktem wejścia do całego pakietu SDK odbiornika.
  • przechowywanie odwołania do obiektu PlayerManager, który obsługuje odtwarzanie, oraz udostępnianie wszystkich elementów, których potrzebujesz do wstawienia własnej logiki niestandardowej;
  • inicjalizacja pakietu SDK przez wywołanie funkcji start() w obiekcie CastReceiverContext

Dodaj te informacje do 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 do wypróbowania nowego odbiornika.

Otwórz w przeglądarce narzędzie dowodzenia i kontroli.

Obraz karty „Ustawienia Cast Connect i Logger” w narzędziu do zarządzania i kontroli

Pamiętaj, aby podać swój własny identyfikator aplikacji zarejestrowany wcześniej w polu, i kliknij „Ustaw identyfikator aplikacji”. To polecenie instruuje narzędzie, aby podczas uruchamiania sesji przesyłania wykorzystywało odbiornik.

Przesyłanie multimediów

Ogólnie rzecz biorąc, aby odtworzyć multimedia na urządzeniu Cast, musi się wydarzyć to:

  1. Nadawca tworzy obiekt MediaInfo JSON z pakietu SDK Cast, który modeluje element multimedialny.
  2. Aby uruchomić aplikację odbiorczą, nadawca łączy się z urządzeniem przesyłającym.
  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 odbiorcy polecenia odtwarzania, aby kontrolować odtwarzanie na podstawie interakcji użytkownika z aplikacją nadawcy.

W tym pierwszym podstawowym podejściu wypełnimy kolumnę MediaInfo adresem URL odtwarzalnego zasobu (przechowywanego w kolumnie MediaInfo.contentUrl).

Prawdziwy nadawca używa w polu MediaInfo.contentId identyfikatora multimediów w ramach aplikacji. Odbiorca używa identyfikatora contentId do wykonywania odpowiednich wywołań interfejsu API w celu rozwiązywania rzeczywistego adresu URL zasobu i ustawiania go jako MediaInfo.contentUrl.. Odbiorca będzie też wykonywać takie zadania jak pozyskiwanie licencji DRM czy wstrzykiwanie informacji o przerwach na reklamę.

W następnej sekcji rozszerzymy odbiornik, aby wykonał dokładnie taką samą czynność. Kliknij ikonę przesyłania i wybierz urządzenie, aby otworzyć odbiornik.

Ilustracja karty „Ustawienia Cast Connect i rejestratora” w narzędziu sterowania i kontroli (CaC), która wskazuje, że jest ono połączone z aplikacją odbiorczą

Otwórz kartę „Wczytaj multimedia” i kliknij przycisk „Wczytaj według treści”. Odbiornik powinien zacząć odtwarzać przykładowe treści.

Obraz karty „Wczytaj multimedia” w narzędziu do zarządzania i kontroli

Tak więc pakiet SDK odbierający od razu obsługuje te dane:

  • Inicjowanie sesji przesyłania
  • obsługiwać przychodzące LOAD żądania od nadawców zawierające zasoby do odtworzenia;
  • Zapewnij podstawowe elementy interfejsu odtwarzacza, które można wyświetlić na dużym ekranie.

Zanim przejdziesz do następnej sekcji, w której rozszerzymy odbiornik, aby komunikował się z interfejsem API prostego przykładu, który będzie obsługiwał przychodzące LOAD żądania od nadawców, zapoznaj się z narzędziem CaC i jego kodem.

9. Integracja z zewnętrznym interfejsem API

W zależności od tego, jak większość deweloperów korzysta z urządzeń odbiorczych Cast w praktyce, zmodyfikujemy odbiornik, aby obsługiwał żądania LOAD, które odwołują się do treści multimedialnych za pomocą klucza interfejsu API, zamiast przesyłać URL zasobu do odtwarzania.

Aplikacje zwykle robią to, ponieważ:

  • Nadawca może nie znać adresu URL treści.
  • Aplikacja Cast została zaprojektowana tak, aby obsługiwać uwierzytelnianie, inne reguły biznesowe lub wywołania interfejsu API bezpośrednio na urządzeniu odbiorcy.

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

  • Przeczytaj przychodzące LOAD i jego niestandardowe contentId.
  • Aby wyszukać strumień zasobu, użyj wywołania GET interfejsu API.contentId
  • Zmodyfikuj żądanie LOAD, podając adres URL strumienia.
  • Zmień obiekt MediaInformation, aby ustawić parametry typu strumienia.
  • Przekazać żądanie do pakietu SDK w celu odtworzenia lub odrzucić polecenie, jeśli nie możemy wyszukać żądanego pliku multimedialnego.

Udostępniony przykład interfejsu API pokazuje funkcje SDK umożliwiające dostosowywanie typowych zadań odbiornika, które można jednak wykonywać głównie bez korzystania z dodatkowych funkcji.

Przykładowe interfejsy API

Otwórz w przeglądarce stronę https://storage.googleapis.com/cpe-sample-media/content.json i zapoznaj się z naszym przykładowym katalogiem filmów. Treści obejmują adresy URL obrazów plakatów w formacie PNG, a także strumienie DASH i HLS. Strumienie DASH i HLS wskazują na demuxowane źródła wideo i dźwięku przechowywane w kontenerach MP4 podzielonych 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 po wywołaniu odbiornika za pomocą żądania LOAD zmapujemy klucz każdej pozycji (np. bbb, fbb_ad) na adres URL strumienia.

Przechwyć żądanie LOAD

W tym kroku utworzymy przechwytywanie ładowania za pomocą funkcji, która wysyła żądanie XHR do hostowanego pliku JSON. Po uzyskaniu pliku JSON przeanalizujemy jego zawartość i ustawimy metadane. W kolejnych sekcjach dostosujemy parametry MediaInformation, aby określić typ treści.

Dodaj poniższy kod do pliku js/receiver.js bezpośrednio przed wywołaniem 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 opiszemy, jak skonfigurować właściwość media w żądaniu wczytywania treści DASH.

Korzystanie z przykładowego treści interfejsu API DASH

Teraz, gdy mamy już przygotowany moduł przechwytywania wczytywania, określimy typ treści dla odbiornika. Odbiorca otrzyma adres URL playlisty reklamy nadrzędnej oraz typ MIME strumienia. Dodaj ten kod do pliku js/receiver.js w LOAD interceptor's 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ć stronę z treściami DASH. Jeśli chcesz przetestować wczytywanie treści HLS, wykonaj następny krok.

Korzystanie z przykładowej treści HLS interfejsu API

Przykładowy interfejs API obejmuje zarówno treści HLS, jak i DASH. Oprócz ustawienia contentType, 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 w próbnym interfejsie API. Gdy odbiornik jest skonfigurowany do odtwarzania strumieni HLS, domyślnym typem kontenera jest strumień transportowy (TS). W efekcie odbiornik spróbuje otworzyć strumienie MP4 w formacie TS, jeśli zmieniona zostanie tylko właściwość contentUrl. W żądaniu załadowania obiekt MediaInformation powinien zostać zmodyfikowany o dodatkowe właściwości, aby odbiorca wiedział, że treści są typu MP4, a nie TS. Dodaj poniższy kod do pliku js/receiver.js w elemencie przechwytującym obciążenie, aby zmodyfikować właściwości contentUrl i contentType. Dodatkowo dodaj 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 zarządzania i kontroli i ustaw identyfikator aplikacji na identyfikator aplikacji odbiorcy. Wybierz urządzenie za pomocą przycisku Przesyłaj.

Otwórz kartę „Wczytaj media”. 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 wszystko działa jak należy z modyfikacjami odbiornika, element przechwytujący powinien kształtować obiekt MediaInfo w coś, co pakiet SDK może odtworzyć na ekranie.

Kliknij przycisk „Wczytaj według treści”, aby sprawdzić, czy multimedia są odtwarzane prawidłowo. Identyfikator treści możesz zmienić na inny w pliku content.json.

10. Optymalizacja pod kątem inteligentnych ekranów

Inteligentne ekrany to urządzenia z funkcją dotykowej, które umożliwiają aplikacjom obsługę elementów sterujących dotykowych.

W tej sekcji opisaliśmy, jak zoptymalizować aplikację odbiornika podczas uruchamiania na wyświetlaczach smart TV oraz jak dostosować elementy sterujące odtwarzaczem.

Dostęp do elementów sterujących interfejsu

Obiekt elementów sterujących interfejsem inteligentnych ekranów można otworzyć za pomocą elementu 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ć atrybut touchScreenOptimizedApp w CastReceiverOptions. W tym ćwiczeniu używamy elementu <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Domyślne przyciski sterujące są przypisywane do każdego slotu na podstawie MetadataType i MediaStatus.supportedMediaCommands.

Sterowanie odtwarzaniem

W przypadku MetadataType.MOVIE, MetadataType.TV_SHOWMetadataType.GENERIC obiekt elementów sterujących interfejsem w przypadku inteligentnych ekranów będzie wyświetlany tak jak w przykładzie poniżej.

Obraz odtwarzanego filmu z elementami sterującymi interfejsu nałożonymi u góry

  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 interfejsem na inteligentnych ekranach będzie wyglądał tak:

Obraz przedstawiający odtwarzanie muzyki z elementami sterującymi nałożonymi na górze

  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

Aktualizuję obsługiwane polecenia multimedialne

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

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

Obraz elementów sterujących odtwarzaczem multimediów: pasek postępu, przycisk „Odtwórz”, 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 elementów sterujących będzie wyglądał tak:

Obraz elementów sterujących odtwarzaczem: włączone przyciski: pasek postępu, przycisk „Odtwórz”, „Przeskocz do przodu” i „Przeskocz do tyłu” oraz „Kolejka do poprzedniej” i „Kolejka do następnej”

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

Obraz elementów sterujących odtwarzaczem: pasek postępu, przycisk „Odtwórz” oraz włączone przyciski „Dodaj do kolejki poprzedni” i „Dodaj do kolejki następny”

Jeśli ścieżki tekstowe są dostępne, przycisk napisów będzie zawsze pokazywany w miejscu SLOT_1.

Obraz elementów sterujących odtwarzaczem multimediów: pasek postępu, przycisk „Odtwórz”, przyciski „Przewiń do przodu” i „Przewiń do tyłu”, przyciski „Dodaj do kolejki poprzedni” i „Dodaj do kolejki następny” oraz włączone przyciski „Napisy”.

Aby dynamicznie zmienić wartość supportedMediaCommands po uruchomieniu kontekstu odbiornika, możesz wywołać funkcję PlayerManager.setSupportedMediaCommands, aby zastąpić wartość. Możesz też dodać nowe polecenie za pomocą addSupportedMediaCommands lub usunąć istniejące polecenie za pomocą removeSupportedMediaCommands.

Dostosowywanie przycisków

Możesz je dostosować za pomocą PlayerDataBinder. Aby ustawić pierwszy slot elementów sterujących, dodaj do pliku js/receiver.js ten kod poniżej elementów sterujących dotykowych:

...

// 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 w CAF Receiver, która umożliwia użytkownikom przeglądanie dodatkowych treści na urządzeniach z ekranem dotykowym. Aby to zaimplementować, użyj PlayerDataBinder do skonfigurowania interfejsu BrowseContent. Następnie możesz wypełnić go wartościami BrowseItems na podstawie treści, które chcesz wyświetlać.

BrowseContent

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

Obraz przedstawiający interfejs dla przeglądania z 2 miniaturami filmów i częścią trzecią

  1. BrowseContent.title
  2. BrowseContent.items

Współczynnik proporcji

Użyj opcji targetAspectRatio property, aby wybrać najlepszy współczynnik proporcji dla komponentów z obrazem. Pakiet SDK odbiornika CAF 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 dla każdego elementu:

Obraz interfejsu BrowseContent z 2 miniaturami filmów i częścią trzeciego

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

Ustawianie danych 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 playerDataBinder i w detektorze zdarzeń MEDIA_CHANGED, aby ustawić elementy przeglądania z nazwą „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 w przeglądarce multimediów uruchamia przechwytywanie LOAD. Dodaj do przechwytu LOAD ten kod, 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ć wartość null dla obiektu BrowseContent, aby usunąć interfejs przeglądania multimediów.

12. Debugowanie aplikacji odbiorczych

Pakiet Cast Receiver SDK to inna opcja dla programistów, która pozwala łatwo debugować aplikacje odbiorników. Służy do tego interfejs CastDebugLogger API i narzędzie Command and Control (CaC) do przechwytywania dzienników.

Zdarzenie inicjujące

Aby włączyć ten 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 pliku i pod funkcją 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 rejestrator debugowania jest włączony, na odbiorniku wyświetla się nakładka z napisem DEBUG MODE.

Obraz odtwarzanego filmu z komunikatem „Tryb debugowania” wyświetlanym na czerwonym tle w lewym górnym rogu kadru

Zdarzenia z dziennika odtwarzacza

Korzystając z CastDebugLogger, możesz łatwo rejestrować zdarzenia odtwarzacza wywoływane przez pakiet SDK CAF Receiver SDK i rejestrować dane zdarzeń na różnych poziomach rejestrowania. Konfiguracja loggerLevelByEvents używa parametrów cast.framework.events.EventTypecast.framework.events.category do określania, które zdarzenia mają być rejestrowane.

Aby rejestrować, kiedy uruchamia się zdarzenie CORE odtwarzacza lub gdy następuje zmiana 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 dziennika i tagi niestandardowe

Interfejs CastDebugLogger API umożliwia tworzenie komunikatów dziennika w różnych kolorach wyświetlanych na nakładce debugowania odbiornika. Dostępne są następujące metody logowania, uporządkowane według priorytetu od najwyższego do najniższego:

  • 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 logowania pierwszy parametr to tag niestandardowy. Może to być dowolny ciąg znaków, który uznasz za odpowiedni. CastDebugLogger używa tagów do filtrowania dzienników. Poniżej znajdziesz szczegółowe informacje o używaniu tagów. Drugi parametr to wiadomość logowania.

Aby wyświetlić logi w działaniu, dodaj je 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 będą się wyświetlać w przeźroczystym oknie debugowania, ustawiając poziom logowania w  dla każdego tagu niestandardowego.loggerLevelByTags Na przykład włączenie tagu niestandardowego z poziomem dziennika cast.framework.LoggerLevel.DEBUG spowoduje wyświetlenie wszystkich komunikatów dodanych z błędami, ostrzeżeniami, informacjami i komunikatami debugowania. Włączenie tagu niestandardowego na poziomie WARNING będzie powodować wyświetlanie tylko komunikatów o błędach i ostrzeżeń w logu.

Konfiguracja loggerLevelByTags jest opcjonalna. Jeśli tag niestandardowy nie jest skonfigurowany pod kątem poziomu rejestratora, wszystkie komunikaty dziennika będą wyświetlane w przesłonie debugowania.

Poniżej rejestratora zdarzeń CORE dodaj ten kod:

// 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

Narzędzie do debugowania Google Cast udostępnia nakładkę debugowania na urządzeniu odbiorczym, aby wyświetlać niestandardowe komunikaty logowania na urządzeniu Google Cast. Użyj klawisza showDebugLogs, aby przełączać nakładkę debugowania, i klawisza clearDebugLogs, aby wyczyścić komunikaty logu w 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 z listą komunikatów dziennika debugowania na półprzezroczystym tle na ramce wideo

13. Gratulacje

Teraz już wiesz, jak utworzyć własną aplikację internetową odbiornika za pomocą pakietu SDK odbiornika internetowego przesyłania.

Więcej informacji znajdziesz w przewodniku dla programistów dotyczącym Web Receiver.