Benutzerdefinierten Web Receiver erstellen

1. Übersicht

Google Cast-Logo

In diesem Codelab erfährst du, wie du eine App mit benutzerdefinierten Webempfängern erstellst, um Inhalte auf für Google Cast optimierten Geräten wiederzugeben.

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 dem Computer als Fernbedienung für die Medienwiedergabe auf dem Fernseher verwenden.

Mit dem Google Cast SDK kann Ihre App für Google Cast optimierte Geräte steuern, z. B. einen Fernseher oder ein Soundsystem. Das Cast SDK bietet die erforderlichen UI-Komponenten basierend auf der Google Cast-Design-Checkliste.

Die Checkliste für das Google Cast-Design wurde bereitgestellt, um die Nutzung von Cast auf allen unterstützten Plattformen einfach und vorhersehbar zu machen. Weitere Informationen

Ziele

Wenn Sie dieses Codelab abgeschlossen haben, haben Sie eine HTML5-App, die als benutzerdefinierter Empfänger dient und Videoinhalte auf Cast-kompatiblen Geräten anzeigen kann.

Lerninhalte

  • Einrichtung für die Empfängerentwicklung
  • Die Grundlagen eines für Google Cast optimierten Empfängers, der auf dem Cast Application Framework basiert.
  • So empfängst du ein gestreamtes Video
  • Integration des Debug-Protokolls
  • Receiver für Smart Displays optimieren

Voraussetzungen

Erfahrung

  • Sie benötigen Vorkenntnisse in der Webentwicklung.
  • Außerdem solltest du schon einmal ferngesehen haben.

Wie möchten Sie diese Anleitung verwenden?

Nur durchlesen Lesen und die Übungen abschließen

Wie würden Sie Ihre Erfahrungen mit der Erstellung von Web-Apps bewerten?

Anfänger Fortgeschrittene Erfahren

Wie würden Sie Ihre Erfahrungen mit Fernsehen bewerten?

Anfänger Mittelstufe Fortgeschritten

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 du deinen Webreceiver mit einem Cast-Gerät verwenden kannst, muss er an einem Ort gehostet werden, an dem dein Cast-Gerät ihn erreichen kann. Wenn Sie bereits einen Server haben, der https unterstützt, überspringen Sie die folgende Anleitung und notieren Sie sich die URL, da Sie sie im nächsten Abschnitt benötigen.

Wenn Sie keinen Server haben, können Sie Firebase Hosting oder ngrok verwenden.

Server ausführen

Nachdem Sie den gewünschten Dienst eingerichtet haben, rufen Sie app-start auf und starten Sie den Server.

Notieren Sie sich die URL für Ihren gehosteten Empfänger. 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 Empfänger, wie in diesem Codelab erstellt, auf Chromecast-Geräten ausführen zu können. Nachdem Sie Ihre Anwendung registriert haben, erhalten Sie eine Anwendungs-ID, die die Absenderanwendung verwenden muss, um API-Aufrufe auszuführen, z. B. um eine Empfängeranwendung zu starten.

Bild der Google Cast SDK Developer Console mit hervorgehobener Schaltfläche „Add New Application“ (Neue Anwendung hinzufügen)

Klicken Sie auf „Neue Anwendung hinzufügen“.

Bild des Bildschirms „Neue Empfängeranwendung“, auf dem die Option „Benutzerdefinierter Empfänger“ hervorgehoben ist

Wählen Sie „Benutzerdefinierter Empfänger“ aus.

Bild des Bildschirms „Neuer benutzerdefinierter Empfänger“ mit einer URL, die jemand in das Feld „URL der Empfängeranwendung“ eingibt

Geben Sie die Details des neuen Empfängers ein. Verwenden Sie dabei die URL, die Sie am Ende erhalten haben.

im letzten Abschnitt. Notieren Sie sich die Anwendungs-ID, die dem neuen Empfänger zugewiesen wurde.

Außerdem müssen Sie Ihr Google Cast-Gerät registrieren, damit es vor der Veröffentlichung auf Ihre Empfängeranwendung zugreifen kann. Sobald Sie die Receiver-App veröffentlicht haben, 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.

Bild der Google Cast SDK-Entwicklerkonsole mit hervorgehobener Schaltfläche „Neues Gerät hinzufügen“

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

Bild des Dialogfelds „Streamingempfängergerät hinzufügen“

Geben Sie die Seriennummer ein, die auf der Rückseite Ihres Chromecast-Geräts aufgedruckt ist, und geben Sie einen aussagekräftigen Namen für das Gerät ein. Sie können die Seriennummer auch finden, indem Sie Ihren Bildschirm in Chrome streamen, wenn Sie auf die Google Cast SDK Developer Console zugreifen.

Es dauert 5 bis 15 Minuten, bis der Empfänger und das Gerät für den Test bereit sind. Warten Sie 5 bis 15 Minuten und starten Sie dann Ihr Streaminggerät neu.

5. Beispiel-App ausführen

Google Chrome-Logo

Während wir darauf warten, dass unsere neue Empfängeranwendung für Tests bereit ist, sehen wir uns an, wie eine fertige Empfänger-App aussehen könnte. Der Empfänger, den wir erstellen werden, kann Medien mit adaptivem Bitrate-Streaming abspielen. Wir verwenden Beispielinhalte, die für Dynamic Adaptive Streaming over HTTP (DASH) codiert sind.

Öffnen Sie in Ihrem Browser das Command and Control (CaC) Tool.

Bild des Tabs „Cast Connect & Logger Controls“ (Cast Connect & Logger-Steuerungen) des CaC-Tools (Command and Control)

  1. Sie sollten unser CaC-Tool sehen.
  2. Verwenden Sie die Standard-Empfänger-ID „CC1AD845“ und klicken Sie auf die Schaltfläche „App-ID festlegen“.
  3. Klicken Sie links oben auf das Cast-Symbol und wählen Sie Ihr Google Cast-Gerät aus.

Bild des Tabs „Cast Connect & Logger Controls“ (Cast Connect & Logger-Steuerungen) des CaC-Tools (Command and Control), das anzeigt, dass eine Verbindung zu einer Empfänger-App besteht

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

Bild des Tabs „Load Media“ (Medien laden) des Command-and-Control-Tools (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 Empfängerfunktionen mit dem Standardempfänger aussehen.

6. Startprojekt vorbereiten

Wir müssen der heruntergeladenen Start-App Unterstützung für Google Cast hinzufügen. Hier sind einige Google Cast-Begriffe, die wir in diesem Codelab verwenden werden:

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

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

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

Hinweis: Wenn Sie dieses Codelab durcharbeiten, sollten die von Ihnen vorgenommenen Änderungen in http-server übernommen werden. Wenn das nicht der Fall ist, beenden Sie http-server und starten Sie es neu.

App-Design

Die Empfänger-App initialisiert die Cast-Sitzung und wartet, bis eine LOAD-Anfrage (d. h. der Befehl zum Abspielen 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 die Funktion des Empfängers enthält.

index.html

Diese HTML-Datei enthält die Benutzeroberfläche der Receiver-App. Sie ist vorerst leer und wird in diesem Code-Lab weiter ergänzt.

receiver.js

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

7. Einen einfachen Cast-Empfänger

Ein einfacher Cast-Empfänger initialisiert die Cast-Sitzung beim Start. Dies ist erforderlich, um allen verbundenen Absenderanwendungen mitzuteilen, dass der Empfänger erfolgreich gestartet wurde. Außerdem ist das neue SDK bereits für die Verarbeitung von Streamingmedien mit adaptiver Bitrate (mit DASH, HLS und Smooth Streaming) und einfachen MP4-Dateien konfiguriert. Probieren wir es 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 index.html <body> vor dem <footer> loading receiver.js, den folgenden Code hinzu, um dem Empfänger-SDK Platz zum Aufrufen der Standard-Empfänger-Benutzeroberfläche zu geben, die im gerade hinzugefügten Script enthalten ist.

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

Jetzt müssen wir das SDK in js/receiver.js initialisieren. Folgende Elemente sind vorhanden:

  • eine Referenz auf CastReceiverContext, deinen primären Einstiegspunkt in das gesamte Receiver SDK, zu erhalten
  • Speichern eines Verweis auf das PlayerManager, das Objekt für die Wiedergabe und Bereitstellung aller Hooks, die du für die Einbindung deiner eigenen benutzerdefinierten Logik benötigst
  • SDK initialisieren, indem start() auf CastReceiverContext aufgerufen wird

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

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

context.start();

8. „Einfache“ Videoinhalte streamen

Verwenden Sie für dieses Codelab das CaC-Tool, um Ihren brandneuen Empfänger zu testen.

Rufen Sie das Command and Control (CaC) Tool in Ihrem Webbrowser auf.

Bild des Tabs „Cast Connect- und Protokollsteuerung“ des CAC-Tools (Command and Control)

Ersetzen Sie die zuvor registrierte App-ID durch Ihre eigene und klicken Sie auf „App-ID festlegen“. Dadurch wird das Tool angewiesen, Ihren Receiver beim Starten der Übertragung zu verwenden.

Medien werden gestreamt

Wenn Sie Medien auf einem Übertragungsgerät wiedergeben möchten, 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ängeranwendung zu starten.
  3. Der Empfänger lädt das MediaInfo-Objekt über eine LOAD-Anfrage zum Abspielen der Inhalte.
  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.

Bei diesem ersten einfachen Versuch geben wir in MediaInfo eine abspielbare Asset-URL ein, die in MediaInfo.contentUrl gespeichert ist.

Ein echter Absender verwendet in MediaInfo.contentId eine anwendungsspezifische Medienkennung. Der Empfänger verwendet die contentId als Kennung, um entsprechende Backend-API-Aufrufe auszuführen, um die tatsächliche Asset-URL aufzulösen und auf MediaInfo.contentUrl. festzulegen. Der Empfänger übernimmt auch Aufgaben wie den Erwerb von DRM-Lizenzen oder das Einschleusen von Informationen zu Werbeunterbrechungen.

Im nächsten Abschnitt werden wir deinen Receiver für eine ähnliche Funktion erweitern. Klicken Sie vorerst auf das Cast-Symbol und wählen Sie Ihr Gerät aus, um den Receiver zu öffnen.

Bild des Tabs „Cast Connect & Logger Controls“ (Cast Connect & Logger Controls) des CaC-Tools (Command and Control), das anzeigt, dass eine Verbindung zu einer Empfänger-App besteht

Rufen Sie den Tab „Medien hochladen“ auf und klicken Sie auf die Schaltfläche „Nach Inhalt laden“. Der Receiver sollte jetzt mit der Wiedergabe des Beispielinhalts beginnen.

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

Das Receiver SDK bietet standardmäßig folgende Funktionen:

  • Stream-Sitzung initialisieren
  • Eingehende LOAD-Anfragen von Absendern mit abspielbaren Assets verarbeiten
  • Bieten Sie eine einfache Player-Benutzeroberfläche, die auf dem großen Bildschirm angezeigt werden kann.

Sie können sich das CaC-Tool und seinen Code ansehen, bevor Sie mit dem nächsten Abschnitt fortfahren. Dort erweitern wir unseren Empfänger, damit er mit einer einfachen Beispiel-API kommunizieren kann, um eingehende LOAD-Anfragen von Absendern zu erfüllen.

9. In eine externe API einbinden

In Übereinstimmung mit der Art und Weise, wie die meisten Entwickler mit ihren Cast-Empfängern in realen Anwendungen interagieren, werden wir unseren Empfänger so ändern, dass er LOAD-Anfragen verarbeitet, die auf die gewünschten Medieninhalte über den API-Schlüssel verweisen, anstatt eine abspielbare Asset-URL zu senden.

In der Regel geschieht dies aus folgenden Gründen:

  • Der Absender kennt möglicherweise nicht die URL der Inhalte.
  • Die Cast-Anwendung ist so konzipiert, dass Authentifizierung, andere Geschäftslogik oder API-Aufrufe direkt auf dem Empfänger ausgeführt werden.

Diese Funktion ist hauptsächlich in der Methode PlayerManager setMessageInterceptor() implementiert. So können Sie eingehende Nachrichten nach Typ abfangen und ändern, bevor sie den internen Nachrichten-Handler des SDKs erreichen. In diesem Abschnitt geht es um LOAD-Anfragen, in denen wir Folgendes tun:

  • Lies die eingehende LOAD-Anfrage und die benutzerdefinierte contentId.
  • Rufe unsere API mit einem GET-Aufruf auf, um das streambare Asset anhand seines contentId abzurufen.
  • Ändern Sie die LOAD-Anfrage mit der URL des Streams.
  • Ändern Sie das MediaInformation-Objekt, um die Parameter für den Streamtyp festzulegen.
  • Gib die Anfrage zur Wiedergabe an das SDK weiter oder lehne den Befehl ab, wenn wir die angeforderten Medien nicht finden können.

Die bereitgestellte Beispiel-API zeigt die Hooks des SDKs zur Anpassung gängiger Empfängeraufgaben, wobei die meisten Funktionen direkt einsatzbereit sind.

Beispiel-API

Rufen Sie in Ihrem Browser die Seite 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 demultiplexierte 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 Load Interceptor mit einer Funktion, die eine XHR-Anfrage an die gehostete JSON-Datei sendet. Sobald die JSON-Datei verfügbar ist, werden die Inhalte geparst und die Metadaten festgelegt. In den folgenden Abschnitten passen wir die MediaInformation-Parameter an, um den Inhaltstyp anzugeben.

Fügen Sie der js/receiver.js-Datei den folgenden Code direkt vor dem Aufruf von context.start() 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 wird beschrieben, wie du die Property media der Ladeanfrage für DASH-Inhalte konfigurierst.

Beispiel-API für DASH-Inhalte verwenden

Nachdem wir den Load Interceptor vorbereitet haben, geben wir dem Empfänger den Inhaltstyp an. Anhand dieser Informationen erhält der Empfänger die URL der Masterplaylist und den MIME-Typ des Streams. Fügen Sie der Datei „js/receiver.js“ im LOAD des Promise() 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 du diesen Schritt abgeschlossen hast, kannst du mit dem Testen fortfahren, um das Laden mit DASH-Inhalten zu testen. Wenn Sie das Laden mit HLS-Inhalten testen möchten, lesen Sie den nächsten Schritt.

HLS-Inhalte der Sample API verwenden

Die Beispiel-API enthält sowohl HLS- als auch DASH-Inhalte. Zusätzlich zum Festlegen von contentType wie im vorherigen Schritt sind für die Ladeanfrage einige zusätzliche Eigenschaften erforderlich, um die HLS-URLs der Beispiel-API zu verwenden. Wenn der Empfänger für die Wiedergabe von HLS-Streams konfiguriert ist, wird der Standardcontainertyp „Transport Stream“ (TS) erwartet. In diesem Fall versucht der Empfänger, die Beispiel-MP4-Streams im TS-Format zu öffnen, wenn nur die Property contentUrl geändert wird. In der Ladeanfrage sollte das MediaInformation-Objekt mit zusätzlichen Attributen geändert werden, damit der Empfänger erkennt, dass der Inhalt vom Typ MP4 und nicht vom Typ TS ist. Fügen Sie der js/Receiver.js-Datei im Load-Abfangende den folgenden Code hinzu, um die Attribute contentUrl und contentType zu ändern. Füge außerdem die Properties 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 noch einmal das Command-and-Control-Tool (CaC) und legen Sie Ihre App-ID auf die App-ID des Empfängers fest. Wählen Sie mit der Schaltfläche „Streamen“ Ihr Gerät aus.

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

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

Wenn die Änderungen am Empfänger wie gewünscht funktionieren, sollte das MediaInfo-Objekt vom Interceptor so angepasst werden, dass es vom SDK auf dem Bildschirm wiedergegeben werden kann.

Klicken Sie auf die Schaltfläche „Nach Inhalt laden“, um zu prüfen, ob Ihre Medien richtig wiedergegeben werden. Du kannst die Content-ID in der Datei content.json durch eine andere ID ersetzen.

10. Anzeigen für Smart Displays optimieren

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

In diesem Abschnitt erfährst du, wie du die Receiver-App beim Starten auf Smart Displays optimieren und die Steuerelemente des Videoplayers anpassen kannst.

Auf UI-Steuerelemente zugreifen

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

...

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

context.start();

Wenn du das Element <cast-media-player> nicht verwendest, musst du touchScreenOptimizedApp in CastReceiverOptions festlegen. In diesem Codelab verwenden wir das Element <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Jedem Slot werden basierend auf MetadataType und MediaStatus.supportedMediaCommands Standardsteuerungstasten zugewiesen.

Videosteuerung

Für MetadataType.MOVIE, MetadataType.TV_SHOW und MetadataType.GENERIC wird das UI-Steuerelemente-Objekt für Smart Displays wie im Beispiel unten 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-Steuerelementobjekt für Smart Displays wie unten dargestellt angezeigt:

Bild von Musik mit überlagerter UI-Steuerung

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

Das UI-Steuerelementobjekt bestimmt auch, ob ein ControlsButton basierend auf MediaStatus.supportedMediaCommands angezeigt wird oder nicht.

Wenn der Wert von supportedMediaCommands mit ALL_BASIC_MEDIA übereinstimmt, wird das Standard-Steuerelement-Layout wie unten dargestellt angezeigt:

Bild der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Schaltfläche „Wiedergabe“, Schaltfläche „Vorwärts springen“ und „Zurückspringen“ aktiviert

Wenn der Wert von supportedMediaCommands mit ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT übereinstimmt, wird das Standard-Steuerelement-Layout wie unten dargestellt angezeigt:

Bild der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Schaltfläche „Wiedergabe“, Schaltfläche „Vorwärts springen“ und „Zurückspringen“ sowie aktivierte Schaltflächen „Vorherige Wiedergabeliste“ und „Nächste Wiedergabeliste“

Wenn der Wert von „supportedMediaCommands“ PAUSE | QUEUE_PREV | QUEUE_NEXT entspricht, wird das Standardkontroll-Layout wie unten dargestellt angezeigt:

Bild der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Schaltfläche „Wiedergabe“ und aktivierte Schaltflächen „Vorheriges Video der Wiedergabeliste hinzufügen“ und „Nächstes Video der Wiedergabeliste hinzufügen“

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

Bild der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Schaltfläche „Wiedergabe“, Schaltflächen „Vorspulen“ und „Zurückspulen“, Schaltflächen „Vorheriges Video der Wiedergabeliste hinzufügen“ und „Nächstes Video der Wiedergabeliste hinzufügen“ sowie aktivierte Schaltflächen „Untertitel“

Wenn du den Wert von supportedMediaCommands nach dem Starten eines Empfängerkontexts dynamisch ändern möchtest, kannst du PlayerManager.setSupportedMediaCommands aufrufen, um den Wert zu überschreiben. Sie können auch einen neuen Befehl mit addSupportedMediaCommands hinzufügen oder einen vorhandenen Befehl mit removeSupportedMediaCommands entfernen.

Steuerelemente anpassen

Sie können die Steuerelemente mit PlayerDataBinder anpassen. Fügen Sie der js/receiver.js-Datei unter den Touchbedienungselementen den folgenden Code hinzu, um den ersten Slot Ihrer 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

Die Mediensuche ist eine CAF-Empfängerfunktion, mit der Nutzer zusätzliche Inhalte auf Touchgeräten erkunden können. Dazu verwenden Sie PlayerDataBinder, um die BrowseContent-Benutzeroberfläche festzulegen. Sie können sie dann je nach Inhalt, den Sie anzeigen möchten, mit BrowseItems füllen.

BrowseContent

Unten sehen Sie ein Beispiel für die BrowseContent-Benutzeroberfläche und ihre Eigenschaften:

Bild der Benutzeroberfläche von „BrowseContent“ mit zwei Video-Thumbnails und einem Teil eines dritten

  1. BrowseContent.title
  2. BrowseContent.items

Seitenverhältnis

Wählen Sie mit targetAspectRatio property das beste Seitenverhältnis für Ihre Bild-Assets aus. Das CAF Receiver SDK unterstützt drei Seitenverhältnisse: SQUARE_1_TO_1, PORTRAIT_2_TO_3 und LANDSCAPE_16_TO_9.

BrowseItem

Mit BrowseItem kannst du Titel, Untertitel, Dauer und Bild für jedes Element anzeigen:

Bild der Benutzeroberfläche von „BrowseContent“ mit zwei Video-Thumbnails und einem Teil eines dritten

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

Daten für die Mediensuche festlegen

Du kannst eine Liste mit Medieninhalten zum Stöbern bereitstellen, indem du setBrowseContent aufrufst. Füge der js/receiver.js-Datei unter playerDataBinder und im MEDIA_CHANGED-Ereignis-Listener den folgenden Code hinzu, um den Titel der Elemente im Bereich „Als Nächstes“ 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 du auf ein Element in der Mediensuche klickst, wird der LOAD-Abfangmechanismus ausgelöst. Füge deinem LOAD-Interceptor den folgenden Code hinzu, um die request.media.contentId dem request.media.entity aus dem Medien-Browse-Element 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 auch das BrowseContent-Objekt auf null setzen, um die Media-Suche zu entfernen.

12. Fehler bei Empfänger-Apps beheben

Das Cast Receiver SDK bietet Entwicklern eine weitere Möglichkeit, Receiver-Apps einfach zu debuggen. Dazu verwenden sie die CastDebugLogger API und ein zugehöriges Command and Control (CaC) Tool, um Protokolle zu erfassen.

Initialisierung

Fügen Sie das CastDebugLogger-Quellskript der Datei „index.html“ 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 oben in der Datei und unter playerManager den folgenden Code hinzu, um die CastDebugLogger-Instanz abzurufen und den Protokoller 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 die Debugging-Protokollierung aktiviert ist, wird auf dem Empfänger ein Overlay mit DEBUG MODE angezeigt.

Bild eines abgespielten Videos mit der Meldung „DEBUG MODE“ (DEBUG-MODUS) auf rotem Hintergrund in der oberen linken Ecke des Frames

Spielerereignisse protokollieren

Mit CastDebugLogger kannst du Spielerereignisse, die vom CAF Receiver SDK ausgelöst werden, ganz einfach protokollieren und die Ereignisdaten mit verschiedenen Protokollierungsebenen erfassen. In der loggerLevelByEvents-Konfiguration werden mit cast.framework.events.EventType und cast.framework.events.category die Ereignisse angegeben, die protokolliert werden sollen.

Füge den folgenden Code unter der castDebugLogger-Deklaration hinzu, um zu protokollieren, wenn ein CORE-Ereignis des 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
}

Logeinträge und benutzerdefinierte Tags

Mit der CastDebugProtokollierung API können Sie Protokollmeldungen erstellen, die auf dem Debug-Overlay des Empfängers in verschiedenen Farben angezeigt werden. Die folgenden Protokollmethoden sind verfügbar, aufgeführt in der Reihenfolge von höchster zu niedrigster Priorität:

  • 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. Dies kann eine beliebige Zeichenfolge sein, die Sie aussagekräftig finden. CastDebugLogger verwendet Tags, um die Logs zu filtern. Die Verwendung von Tags wird weiter unten ausführlich erläutert. Der zweite Parameter ist die Protokollmeldung.

Wenn Sie Logs in Aktion sehen möchten, fügen Sie Ihrem LOAD-Interceptor Logs hinzu.

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 in loggerLevelByTags die Protokollebene für jedes benutzerdefinierte Tag festlegen. Wenn Sie beispielsweise ein benutzerdefiniertes Tag mit der Logebene cast.framework.LoggerLevel.DEBUG aktivieren, werden alle hinzugefügten Nachrichten mit Fehler-, Warn-, Info- und Debug-Logmeldungen angezeigt. Wenn Sie ein benutzerdefiniertes Tag mit der Ebene WARNING aktivieren, werden nur Fehler- und Warnmeldungen protokolliert.

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

Fügen Sie unter dem CORE-Ereignisprotokoll 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

Der Cast-Debug-Logger bietet auf dem Empfänger ein Debug-Overlay, über das benutzerdefinierte Protokollmeldungen auf dem gestreamten Gerät angezeigt werden. Mit showDebugLogs können Sie das Debug-Overlay ein- und ausschalten und mit clearDebugLogs die Protokollmeldungen im Overlay löschen.

Fügen Sie den folgenden Code hinzu, um eine Vorschau des Debug-Overlays auf Ihrem Receiver zu sehen.

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, das das Debug-Overlay zeigt, eine Liste von Debug-Protokollmeldungen auf einem durchsichtigen Hintergrund über einem Videoframe

13. Glückwunsch

Sie wissen jetzt, wie Sie mit dem Cast Web Receiver SDK eine benutzerdefinierte Web-Empfängeranwendung erstellen.

Weitere Informationen findest du im Entwicklerhandbuch für Webreceiver.