Benutzerdefinierten Web Receiver erstellen

1. Überblick

Google Cast-Logo

In diesem Codelab erfahren Sie, wie Sie eine App für benutzerdefinierten Webempfänger erstellen, um Inhalte auf für Google Cast optimierten Geräten abzuspielen.

Was ist Google Cast?

Mit Google Cast können Nutzer Inhalte von einem Mobilgerät auf einen Fernseher streamen. Nutzer können dann ihr Mobilgerät oder den Chrome-Browser auf ihrem Computer als Fernbedienung für die Medienwiedergabe auf dem Fernseher verwenden.

Mit dem Google Cast SDK können Sie mit Ihrer App Google Cast-fähige Geräte steuern, z. B. einen Fernseher oder ein Soundsystem. Das Cast SDK stellt Ihnen die erforderlichen UI-Komponenten bereit, die auf der Checkliste für das Google Cast-Design basieren.

Die Checkliste für das Google Cast-Design enthält eine einfache und vorhersehbare Checkliste für Cast auf allen unterstützten Plattformen. Weitere Informationen

Ziele

Wenn Sie dieses Codelab abgeschlossen haben, haben Sie eine HTML5-App, die als Ihr eigener benutzerdefinierter Empfänger fungiert und Videoinhalte auf für Google Cast optimierten Geräten wiedergeben kann.

Lerninhalte

  • Einrichtung für die Empfängerentwicklung
  • Grundlagen eines für Google Cast optimierten Receivers, der auf dem Cast Application Framework basiert.
  • So empfangen Sie ein gestreamtes Video.
  • So integrieren Sie das Debug-Logger.
  • So optimierst du deinen Receiver für Smart Displays.

Voraussetzungen

Plattform

  • Sie müssen bereits über Kenntnisse in der Webentwicklung verfügen.
  • Vorkenntnisse im Fernsehen werden benötigt :)

Wie werden Sie diese Anleitung verwenden?

Nur durchlesen Lesen und die Übungen abschließen

Wie würden Sie Ihre Erfahrung mit der Entwicklung von Webanwendungen bewerten?

Neuling Fortgeschritten Versiert

Wie würdest du deine Erfahrung beim Fernsehen bewerten?

Neuling Fortgeschritten Versiert

2. Beispielcode abrufen

Sie können den gesamten Beispielcode auf Ihren Computer herunterladen...

und entpacken Sie die heruntergeladene ZIP-Datei.

3. Empfänger lokal bereitstellen

Damit Sie Ihren Web-Receiver mit einem Übertragungsgerät verwenden können, muss es an einem Ort gehostet werden, an dem Ihr Übertragungsgerät es erreichen kann. Sollten Sie bereits über einen Server verfügen, der HTTPS unterstützt, überspringen Sie die folgende Anleitung und merken Sie sich die URL, da Sie sie im nächsten Abschnitt benötigen.

Wenn kein Server zur Verfügung steht, können Sie Firebase Hosting oder ngrok verwenden.

Server ausführen

Nachdem Sie den Dienst Ihrer Wahl eingerichtet haben, gehen Sie zu app-start und starten Sie Ihren Server.

Notieren Sie sich die URL des gehosteten Empfängers. Sie benötigen sie im nächsten Abschnitt.

4. App in der Cast Developer Console registrieren

Sie müssen Ihre Anwendung registrieren, um einen benutzerdefinierten Receiver, wie in diesem Codelab erstellt, auf Chromecast-Geräten ausführen zu können. Nach der Registrierung Ihrer Anwendung erhalten Sie eine Anwendungs-ID, die Ihre Senderanwendung verwenden muss, um API-Aufrufe durchzuführen, beispielsweise um eine Empfängeranwendung zu starten.

Abbildung der Google Cast SDK Developer Console mit hervorgehobener Schaltfläche "Add New Application" (Neue App hinzufügen)

Klicken Sie auf „Neue Anwendung hinzufügen“.

Screenshot des Bildschirms „App für neuen Receiver“, auf dem die Option „Benutzerdefinierter Receiver“ markiert ist

Wählen Sie "Benutzerdefinierter Empfänger" aus.

Screenshot des Bildschirms „Neuer benutzerdefinierter Empfänger“ mit einer URL, die jemand in das Feld „Anwendungs-URL des Empfängers“ eingibt

Gib die Details zu deinem neuen Empfänger ein und verwende dabei die URL, die

im letzten Abschnitt. Notieren Sie sich die App-ID, die Ihrem neuen Empfänger zugewiesen ist.

Außerdem müssen Sie vor der Veröffentlichung Ihr Google Cast-Gerät registrieren, damit es auf die Receiver-App zugreifen kann. Nach der Veröffentlichung Ihrer Receiver-App ist sie für alle Google Cast-Geräte verfügbar. Für dieses Codelab wird empfohlen, mit einer nicht veröffentlichten Empfängeranwendung zu arbeiten.

Abbildung der Google Cast SDK Developer Console mit hervorgehobener Schaltfläche "Add New Device" (Neues Gerät hinzufügen)

Klicken Sie auf „Neues Gerät hinzufügen“.

Bild des Dialogfelds „Cast-Empfänger hinzufügen“

Geben Sie die Seriennummer ein, die auf der Rückseite Ihres Übertragungsgeräts aufgedruckt ist, und einen aussagekräftigen Namen. Sie können die Seriennummer auch durch Streamen des Bildschirms in Chrome ermitteln, wenn Sie die Google Cast SDK Developer Console aufrufen.

Es dauert 5 bis 15 Minuten, bis Empfänger und Gerät für Tests bereit sind. Warten Sie 5 bis 15 Minuten und starten Sie das Übertragungsgerät neu.

5. Beispiel-App ausführen

Google Chrome-Logo

Während wir darauf warten, dass unsere neue Empfängeranwendung zum Testen bereit ist, sehen wir uns an, wie eine fertige Beispielanwendung aussieht. Der Empfänger wird in der Lage sein, Medien mithilfe von Streaming mit adaptiver Bitrate wiederzugeben. Wir verwenden Beispielinhalte, die für Dynamic Adaptive Streaming over HTTP (DASH) codiert sind.

Öffnen Sie in Ihrem Browser das Befehls- und Kontrolltool (CaC).

Screenshot der Registerkarte "Cast Connect & Logger Controls" des Command and Control (CaC)-Tools

  1. Unser CaC-Tool sollte angezeigt werden.
  2. Verwenden Sie die standardmäßige Beispielempfänger-ID "CC1AD845" und klicken Sie auf die Schaltfläche "Set App ID" (App-ID festlegen).
  3. Klicken Sie links oben auf das Cast-Symbol und wählen Sie Ihr Google Cast-Gerät aus.

Abbildung des Tabs „Cast Connect & Logger Controls“ (Cast Connect & Logger-Steuerung) des Command and Control (CaC)-Tools, das anzeigt, dass es mit einer Receiver-App verbunden ist

  1. Gehen Sie oben zum Tab „Medien laden“.

Bild des Tabs „Medien laden“ des Command and Control (CaC)-Tools

  1. Klicken Sie auf die Schaltfläche "Nach Inhalt laden", um ein Beispielvideo abzuspielen.
  2. Das Video wird auf Ihrem Google Cast-Gerät wiedergegeben, um zu zeigen, wie die grundlegenden Receiver-Funktionen mit dem Standardempfänger aussehen.

6. Startprojekt vorbereiten

Wir müssen der heruntergeladene Start-App Support für Google Cast hinzufügen. Hier sind einige Google Cast-Terminologie, die wir in diesem Codelab verwenden werden:

  • Wenn eine Absender-App auf einem Mobilgerät oder Laptop ausgeführt wird
  • Eine Empfänger-App wird auf dem Google Cast-Gerät ausgeführt.

Jetzt können Sie mit Ihrem bevorzugten Texteditor auf dem Startprojekt aufbauen:

  1. Wählen Sie das Verzeichnis Ordnersymbolapp-start aus dem heruntergeladenen Beispielcode aus.
  2. js/receiver.js und index.html öffnen

Hinweis: Während du dieses Codelab durchführst, sollte http-server die von dir vorgenommenen Änderungen übernehmen. Wenn dies nicht der Fall ist, solltest du http-server beenden und neu starten.

App-Design

Die Empfänger-App initialisiert die Streaming-Sitzung und ist im Stand-by-Modus, bis eine LOAD-Anfrage (also der Befehl zur Wiedergabe eines Medienelements) von einem Sender eingeht.

Die App besteht aus einer Hauptansicht, die in index.html definiert ist, und einer JavaScript-Datei namens js/receiver.js, die die gesamte Logik für den Betrieb des Empfängers enthält.

index.html

Diese HTML-Datei enthält die Benutzeroberfläche für unsere Empfänger-App. Bis auf Weiteres ist sie leer und wir werden sie während des gesamten Code-Lab hinzufügen.

receiver.js

Mit diesem Skript wird die gesamte Logik für unsere Empfänger-App verwaltet. Derzeit ist es nur eine leere Datei, aber wir werden sie im nächsten Abschnitt mit nur wenigen Codezeilen in einen voll funktionsfähigen Cast-Empfänger verwandeln.

7. Einen einfachen Streaming-Receiver

Ein einfacher Cast-Receiver initialisiert die Streaming-Sitzung beim Start. Dies ist erforderlich, um allen verbundenen Absenderanwendungen mitzuteilen, dass der Empfänger erfolgreich aufgerufen wurde. Darüber hinaus ist das neue SDK für die Verarbeitung von Streaming-Medien mit adaptiver Bitrate (mit DASH, HLS und Smooth Streaming) sowie für einfache MP4-Dateien vorkonfiguriert. Probieren wir das mal aus.

Initialisierung

Fügen Sie index.html im Header den folgenden Code hinzu:

<head>
  ...

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

Füge den folgenden Code in index.html <body> vor dem <footer> ein, das receiver.js, lädt, um dem Empfänger-SDK Platz für die standardmäßige Benutzeroberfläche des Empfängers bereitzustellen, die mit dem soeben hinzugefügten Skript ausgeliefert wird.

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

Jetzt müssen wir das SDK in js/receiver.js initialisieren. Es besteht aus:

  • Eine Referenz zu CastReceiverContext, deinem primären Einstiegspunkt für das gesamte Receiver SDK
  • Speichert einen Verweis auf PlayerManager, das Objekt, das die Wiedergabe verarbeitet, und bietet dir alle Hooks, die du zum Einbinden deiner eigenen benutzerdefinierten Logik benötigst
  • SDK durch Aufrufen von start() am CastReceiverContext initialisieren

Fügen Sie js/receiver.js Folgendes hinzu.

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

context.start();

8. Einfachen Videocontent streamen

Verwende für dieses Codelab das CaC-Tool, um deinen neuen Receiver zu testen.

Rufen Sie in Ihrem Webbrowser das Befehls- und Kontrolltool (CaC) auf.

Screenshot der Registerkarte &quot;Cast Connect & Logger Controls&quot; des Command and Control (CaC)-Tools

Ersetzen Sie die App durch Ihre eigene App-ID, die Sie zuvor im Feld registriert haben, und klicken Sie auf „App-ID festlegen“. Dadurch wird das Tool angewiesen, beim Starten der Streamingsitzung Ihren Empfänger zu verwenden.

Medien streamen

Damit Medien auf einem Übertragungsgerät abgespielt werden können, müssen folgende Voraussetzungen erfüllt sein:

  1. Der Absender erstellt ein MediaInfo-JSON-Objekt aus dem Cast SDK, das ein Medienelement modelliert.
  2. Der Sender stellt eine Verbindung zum Übertragungsgerät her, um die Empfänger-App zu starten.
  3. Der Empfänger lädt das MediaInfo-Objekt über eine LOAD-Anfrage, um den Inhalt wiederzugeben.
  4. Der Empfänger überwacht und verfolgt den Medienstatus.
  5. Der Sender sendet Wiedergabebefehle an den Empfänger, um die Wiedergabe basierend auf Nutzerinteraktionen mit der Sender-App zu steuern.

In diesem ersten einfachen Versuch werden wir MediaInfo mit einer spielbaren Asset-URL füllen (gespeichert in MediaInfo.contentUrl).

Ein echter Absender verwendet eine anwendungsspezifische Medien-ID in MediaInfo.contentId. Der Empfänger verwendet die contentId als Kennung, um entsprechende Back-End-API-Aufrufe durchzuführen, um die eigentliche Asset-URL aufzulösen und auf MediaInfo.contentUrl. zu setzen. Der Empfänger übernimmt auch Aufgaben wie den Erwerb von DRM-Lizenzen oder das Einfügen von Informationen zu Werbeunterbrechungen.

Im nächsten Abschnitt erweitern wir den Empfänger entsprechend. Klicke zunächst auf das Cast-Symbol und wähle dein Gerät aus, um den Receiver zu öffnen.

Abbildung des Tabs „Cast Connect & Logger Controls“ (Cast Connect & Logger-Steuerung) des Command and Control (CaC)-Tools, das anzeigt, dass es mit einer Receiver-App verbunden ist

Navigieren Sie zum Tab "Medien laden" und klicken Sie auf die Schaltfläche "Nach Inhalt laden". Der Receiver sollte dann mit der Wiedergabe des Beispielinhalts beginnen.

Bild des Tabs „Medien laden“ des Command and Control (CaC)-Tools

Standardmäßig verarbeitet das Receiver SDK Folgendes:

  • Streamingsitzung wird initialisiert
  • Eingehende LOAD-Anfragen von Absendern verarbeiten, die abspielbare Assets enthalten
  • Stellen Sie eine grundlegende Player-Benutzeroberfläche bereit, die auf dem großen Bildschirm angezeigt werden kann.

Machen Sie sich mit dem CaC-Tool und seinem Code vertraut, bevor Sie mit dem nächsten Abschnitt fortfahren. In diesem Abschnitt erweitern wir den Empfänger auf eine einfache Beispiel-API, um eingehende LOAD-Anfragen von Absendern zu erfüllen.

9. In eine externe API einbinden

Wie die meisten Entwickler mit ihren Cast Receivern in realen Anwendungen interagieren, ändern wir unseren Empfänger so, dass LOAD-Anfragen verarbeitet werden, die mit dem API-Schlüssel auf die gewünschten Medieninhalte verweisen, anstatt eine abspielbare Asset-URL zu senden.

Dies geschieht in der Regel aus folgenden Gründen:

  • Der Absender kennt die URL des Inhalts möglicherweise nicht.
  • Die Cast-Anwendung ist darauf ausgelegt, Authentifizierungen, andere Geschäftslogik oder API-Aufrufe direkt auf dem Empfänger auszuführen.

Diese Funktion wird hauptsächlich in der Methode PlayerManager setMessageInterceptor() implementiert. Dadurch können Sie eingehende Nachrichten nach Typ abfangen und ändern, bevor sie den internen Nachrichten-Handler des SDK erreichen. In diesem Abschnitt befassen wir uns mit LOAD-Anfragen, wobei wir Folgendes tun:

  • Die eingehende LOAD-Anfrage und ihren benutzerdefinierten contentId lesen.
  • Rufe unsere API mit einem GET-Aufruf auf, um das streamfähige Asset anhand seiner contentId zu suchen.
  • Ändern Sie die LOAD-Anfrage mit der URL des Streams.
  • Ändern Sie das Objekt MediaInformation, um die Streamtypparameter festzulegen.
  • Übergeben Sie die Anfrage zur Wiedergabe an das SDK oder lehnen Sie den Befehl ab, wenn wir die angeforderten Medien nicht abrufen können.

Die bereitgestellte Beispiel-API zeigt die Hooks des SDK, mit denen häufige Empfängeraufgaben angepasst werden können, ohne dabei die Standard-Funktion zu nutzen.

Beispiel-API

Rufen Sie in Ihrem Browser https://storage.googleapis.com/cpe-sample-media/content.json auf und sehen Sie sich unseren Beispielvideokatalog an. Die Inhalte umfassen URLs für Posterbilder im PNG-Format sowie DASH- und HLS-Streams. Die DASH- und HLS-Streams verweisen auf aufgeteilte Video- und Audioquellen, die in fragmentierten MP4-Containern gespeichert sind.

{
  "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"
  },

  [...]

}

Im nächsten Schritt ordnen wir den Schlüssel jedes Eintrags (z. B. bbb, fbb_ad) der URL des Streams zu, nachdem der Empfänger mit einer LOAD-Anfrage aufgerufen wurde.

LOAD-Anfrage abfangen

In diesem Schritt erstellen wir einen Lade-Interceptor mit einer Funktion, die eine XHR-Anfrage an die gehostete JSON-Datei sendet. Sobald die JSON-Datei abgerufen ist, parsen wir den Inhalt und legen die Metadaten fest. In den folgenden Abschnitten passen wir die MediaInformation-Parameter an, um den Inhaltstyp anzugeben.

Fügen Sie der Datei js/receiver.js direkt vor dem Aufruf von context.start() den folgenden Code hinzu.

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);
          }
        });
      });
    });

Im nächsten Abschnitt erfahren Sie, wie Sie das Attribut media der Ladeanfrage für DASH-Content konfigurieren.

DASH-Content mit der Beispiel-API verwenden

Nachdem wir nun den Lade-Interceptor vorbereitet haben, geben wir dem Empfänger den Inhaltstyp an. Diese Informationen liefern dem Empfänger die Masterplaylist-URL und den Stream-MIME-Typ. Fügen Sie der Datei „js/receiver.js“ in der Promise() des LOAD-Interceptors den folgenden Code hinzu:

...
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';
            ...
          }
        });
      });
    });

Wenn Sie diesen Schritt abgeschlossen haben, können Sie mit dem Testlauf fortfahren und versuchen, DASH-Inhalte zu laden. Wenn Sie stattdessen das Laden mit HLS-Content testen möchten, führen Sie den nächsten Schritt aus.

HLS-Inhalt der Sample API verwenden

Die Beispiel-API enthält HLS-Content sowie DASH. Zusätzlich zur Festlegung von contentType wie im vorherigen Schritt benötigt die Ladeanfrage einige zusätzliche Attribute, um die HLS-URLs der Beispiel-API zu verwenden. Wenn der Empfänger für die Wiedergabe von HLS-Streams konfiguriert ist, wird als standardmäßiger Containertyp Transport Stream (TS) erwartet. Daher versucht der Empfänger, die MP4-Beispielstreams im TS-Format zu öffnen, wenn nur das Attribut contentUrl geändert wird. In der Ladeanfrage sollte das MediaInformation-Objekt mit zusätzlichen Eigenschaften geändert werden, damit der Empfänger weiß, dass der Inhalt vom Typ MP4 und nicht vom Typ TS ist. Fügen Sie der Datei js/receiver.js im Load-Interceptor den folgenden Code hinzu, um die Attribute contentUrl und contentType zu ändern. Fügen Sie außerdem die Attribute HlsSegmentFormat und HlsVideoSegmentFormat hinzu.

...
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;
            ...
          }
        });
      });
    });

Testen

Öffnen Sie wieder das Command and Control (CaC)-Tool und legen Sie als App-ID die App-ID des Empfängers fest. Wähle dein Gerät über das Cast-Symbol aus.

Gehen Sie zum Tab „Medien laden“. Löschen Sie dieses Mal den Text im Feld „Content-URL“ neben der Schaltfläche „Nach Inhalt laden“. Dadurch wird unsere Anwendung gezwungen, eine LOAD-Anfrage an unsere Medien zu senden, die nur den Verweis contentId enthält.

Bild des Tabs „Medien laden“ des Command and Control (CaC)-Tools

Vorausgesetzt, mit deinen Änderungen am Empfänger funktionierte alles einwandfrei. Der Interceptor sollte das MediaInfo-Objekt so gestalten, dass das SDK auf dem Bildschirm wiedergegeben werden kann.

Klicken Sie auf die Schaltfläche "Load by Content" (Nach Inhalt laden), um zu sehen, ob Ihre Medien korrekt wiedergegeben werden. Du kannst die Content ID-ID in der Datei content.json ändern.

10. Optimierung für Smart Displays

Smart Displays sind Geräte mit Touchfunktion, die es Empfänger-Apps ermöglichen, Touchbedienung zu unterstützen.

In diesem Abschnitt wird erläutert, wie du deine Receiver-App beim Start auf Smart Displays optimieren und die Steuerelemente des Players anpassen kannst.

Auf UI-Steuerelemente zugreifen

Auf das UI Controls-Objekt für Smart Displays kann über cast.framework.ui.Controls.GetInstance() zugegriffen werden. Fügen Sie der Datei js/receiver.js über context.start() den folgenden Code hinzu:

...

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

context.start();

Wenn Sie das <cast-media-player>-Element nicht verwenden, müssen Sie touchScreenOptimizedApp in CastReceiverOptions festlegen. In diesem Codelab verwenden wir das Element <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Die standardmäßigen Steuerschaltflächen werden basierend auf MetadataType und MediaStatus.supportedMediaCommands jedem Slot zugewiesen.

Videosteuerelemente

Für MetadataType.MOVIE, MetadataType.TV_SHOW und MetadataType.GENERIC wird das UI Controls-Objekt für Smart Displays wie im folgenden Beispiel angezeigt.

Bild eines Videos, das mit eingeblendeten UI-Steuerelementen wiedergegeben wird

  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

Audiosteuerung

Für MetadataType.MUSIC_TRACK wird das UI-Steuerelemente-Objekt für Smart Displays so angezeigt:

Abbildung der Musikwiedergabe mit eingeblendeten UI-Steuerelementen

  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

Unterstützte Medienbefehle aktualisieren

Das UI-Steuerelemente-Objekt bestimmt anhand von MediaStatus.supportedMediaCommands auch, ob ein ControlsButton angezeigt wird oder nicht.

Wenn der Wert von supportedMediaCommands gleich ALL_BASIC_MEDIA ist, wird das Standardlayout des Steuerelements so angezeigt:

Abbildung der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Wiedergabeschaltfläche, Schaltflächen „Vorwärts springen“ und „Zurückspulen“ aktiviert

Wenn der Wert von supportedMediaCommands gleich ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT ist, wird das Standardlayout des Steuerelements so angezeigt:

Abbildung der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Wiedergabeschaltfläche, Schaltflächen „Vorwärts springen“ und „Zurückspulen“ sowie die Schaltflächen „Zurück in die Warteschlange“ und „Nächste in der Wiedergabeliste“ aktiviert

Wenn der Wert von „supportedMediaCommands“ gleich PAUSE | QUEUE_PREV | QUEUE_NEXT ist, wird das Standardlayout der Steuerelemente so angezeigt:

Abbildung der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Wiedergabeschaltfläche sowie Schaltflächen „Vorheriger Wiedergabeliste“ und „Wiedergabeliste“ aktiviert

Wenn Texttracks verfügbar sind, wird die Schaltfläche für Untertitel immer bei SLOT_1 angezeigt.

Abbildung der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Wiedergabeschaltfläche, Schaltflächen „Vorwärts springen“ und „Zurückspulen“, „Zurück in die Warteschlange“ und „Nächste in der Warteschlange“ sowie die Schaltflächen „Untertitel“ aktiviert

Wenn Sie den Wert von supportedMediaCommands nach dem Start eines Empfängerkontexts dynamisch ändern möchten, können Sie PlayerManager.setSupportedMediaCommands aufrufen, um den Wert zu überschreiben. Außerdem können Sie mit addSupportedMediaCommands einen neuen Befehl hinzufügen oder mit removeSupportedMediaCommands einen vorhandenen Befehl entfernen.

Steuerungsschaltflächen anpassen

Du kannst die Steuerelemente mit PlayerDataBinder anpassen. Fügen Sie der Datei js/receiver.js unter den touchControls den folgenden Code hinzu, um die erste Anzeigenfläche der Steuerelemente festzulegen:

...

// 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. Mediensuche auf Smart Displays implementieren

Media Browse ist eine CAF-Receiver-Funktion, mit der Nutzer zusätzliche Inhalte auf Touchgeräten durchsuchen können. Um dies zu implementieren, verwenden Sie PlayerDataBinder, um die BrowseContent-UI festzulegen. Anschließend können Sie je nach Inhalt, den Sie darstellen möchten, BrowseItems eingeben.

BrowseContent

Unten sehen Sie ein Beispiel für die BrowseContent-UI und ihre Eigenschaften:

Abbildung der BrowseContent-Benutzeroberfläche mit zwei Video-Thumbnails und einem Teil eines dritten Video-Thumbnails

  1. BrowseContent.title
  2. BrowseContent.items

Seitenverhältnis

Verwenden Sie targetAspectRatio property, um das beste Seitenverhältnis für Ihre Bild-Assets auszuwählen. Vom CAF Receiver SDK werden drei Seitenverhältnisse unterstützt: SQUARE_1_TO_1, PORTRAIT_2_TO_3 und LANDSCAPE_16_TO_9.

BrowseItem

Verwende BrowseItem, um Titel, Untertitel, Dauer und Bild für jedes Element anzuzeigen:

Abbildung der BrowseContent-Benutzeroberfläche mit zwei Video-Thumbnails und einem Teil eines dritten Video-Thumbnails

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

Media Browse-Daten festlegen

Sie können eine Liste mit Medieninhalten zum Durchsuchen bereitstellen, indem Sie setBrowseContent aufrufen. Fügen Sie den folgenden Code in die Datei js/receiver.js unter playerDataBinder und in den Event-Listener MEDIA_CHANGED ein, um für die durchsuchbaren Elemente den Titel „Nächstes Video“ festzulegen.

// 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);
  });

Wenn Sie auf ein stöberbares Medienelement klicken, wird der LOAD-Interceptor ausgelöst. Fügen Sie Ihrem LOAD-Interceptor den folgenden Code hinzu, um request.media.contentId im Mediensuchelement dem request.media.entity zuzuordnen:

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) => {
            ...
        });
    });

Du kannst das Objekt BrowseContent auch auf null setzen, um die Media Browse-Benutzeroberfläche zu entfernen.

12. Fehlerbehebung bei Empfänger-Apps

Das Cast Receiver SDK bietet Entwicklern eine weitere Option, mit der Entwickler ganz einfach Fehler in Empfänger-Apps beheben können. Dazu werden die CastDebugLogger API und ein zugehöriges CaC-Tool (Command and Control) zum Erfassen von Protokollen verwendet.

Initialisierung

Fügen Sie der Datei „index.html“ das Quellskript CastDebugLogger hinzu, um die API einzubinden. Die Quelle sollte im <head>-Tag nach der Cast Receiver SDK-Deklaration deklariert werden.

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

Fügen Sie in js/receiver.js am Anfang der Datei und unter playerManager den folgenden Code ein, um die CastDebugLogger-Instanz abzurufen und den Logger zu aktivieren:

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);
  }
});

Wenn das Debug-Protokoll aktiviert ist, wird auf dem Empfänger ein Overlay mit DEBUG MODE angezeigt.

Bild eines Videos, das mit der Meldung „FEHLERMODUS“ auf einem roten Hintergrund in der oberen linken Ecke des Frames angezeigt wird

Player-Ereignisse protokollieren

Mit CastDebugLogger kannst du ganz einfach Spielerereignisse protokollieren, die vom CAF Receiver SDK ausgelöst werden, und die Ereignisdaten auf verschiedenen Logger-Ebenen protokollieren. Die loggerLevelByEvents-Konfiguration verwendet cast.framework.events.EventType und cast.framework.events.category, um anzugeben, welche Ereignisse protokolliert werden.

Füge den folgenden Code unter der castDebugLogger-Deklaration ein, um zu protokollieren, wenn ein CORE-Ereignis eines Spielers ausgelöst oder eine mediaStatus-Änderung übertragen wird:

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

Protokollnachrichten und benutzerdefinierte Tags

Mit der CastDebugLogger API können Sie Protokollmeldungen erstellen, die in verschiedenen Farben auf dem Debug-Overlay des Empfängers angezeigt werden. Die folgenden Logmethoden sind verfügbar, von der höchsten zur niedrigsten Priorität geordnet:

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

Bei jeder Logmethode ist der erste Parameter ein benutzerdefiniertes Tag. Dabei kann es sich um einen beliebigen identifizierenden String handeln, den Sie für relevant halten. CastDebugLogger verwendet Tags, um die Logs zu filtern. Die Verwendung von Tags wird weiter unten ausführlich erläutert. Der zweite Parameter ist die Lognachricht.

Fügen Sie Ihrem LOAD-Interceptor Logs hinzu, um Logs in Aktion anzuzeigen.

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);
          }
      });
    });
  });

Sie können festlegen, welche Meldungen im Debug-Overlay angezeigt werden, indem Sie die Protokollebene in loggerLevelByTags für jedes benutzerdefinierte Tag festlegen. Wenn Sie beispielsweise ein benutzerdefiniertes Tag mit der Protokollebene cast.framework.LoggerLevel.DEBUG aktivieren, werden alle Meldungen angezeigt, die mit Fehler-, Warn-, Info- und Debug-Protokollmeldungen hinzugefügt wurden. Wenn Sie ein benutzerdefiniertes Tag mit der Ebene WARNING aktivieren, werden nur Protokollmeldungen mit Fehlern und Warnungen angezeigt.

Die Konfiguration von loggerLevelByTags ist optional. Wenn ein benutzerdefiniertes Tag nicht für seine Protokollierungsebene konfiguriert ist, werden alle Protokollmeldungen im Debug-Overlay angezeigt.

Fügen Sie unter dem Ereignisprotokoll CORE den folgenden Code ein:

// 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,
};

Debug-Overlay

Das Cast Debug Logger bietet ein Debug-Overlay auf dem Empfänger, um Ihre benutzerdefinierten Protokollmeldungen auf dem Übertragungsgerät anzuzeigen. Verwende showDebugLogs, um das Debug-Overlay umzuschalten, und clearDebugLogs, um Protokollmeldungen auf dem Overlay zu löschen.

Fügen Sie den folgenden Code hinzu, um eine Vorschau des Debug-Overlays auf Ihrem Empfänger anzuzeigen.

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();
  }
});

Bild mit dem Debug-Overlay, einer Liste von Debug-Protokollmeldungen vor einem durchsichtigen Hintergrund über einem Videoframe

13. Glückwunsch

Jetzt wissen Sie, wie Sie mit dem Cast Web Receiver SDK eine benutzerdefinierte Webempfänger-App erstellen.

Weitere Informationen finden Sie im Web Receiver-Entwicklerleitfaden.