Benutzerdefinierten Web Receiver erstellen

1. Übersicht

Google Cast-Logo

In diesem Codelab erfahren Sie, wie Sie eine benutzerdefinierte Web Receiver-App 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 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 wie Fernseher oder Soundsysteme steuern. Das Cast SDK bietet Ihnen die erforderlichen UI-Komponenten basierend auf der Google Cast-Design-Checkliste.

Die Google Cast-Design-Checkliste soll dafür sorgen, dass die Cast-User Experience auf allen unterstützten Plattformen einfach und vorhersehbar ist. Weitere Informationen

Ziele

Nach Abschluss dieses Codelabs haben Sie eine HTML5-App, die als Ihr eigener benutzerdefinierter Empfänger fungiert und Videoinhalte auf Cast-fähigen Geräten anzeigen kann.

Lerninhalte

  • So richten Sie die Entwicklung von Empfängern ein.
  • Die Grundlagen eines Cast-fähigen Empfängers, der auf dem Cast Application Framework basiert.
  • Gecastete Videos empfangen
  • Debug-Logger einbinden
  • Empfänger für Smart Displays optimieren

Voraussetzungen

Erfahrung

  • Sie benötigen Vorkenntnisse in der Webentwicklung.
  • Außerdem sollten Sie sich mit dem Fernsehen auskennen :)

Wie werden Sie diese Anleitung verwenden?

Nur lesen Lesen und Übungen durchführen

Wie würden Sie Ihre Erfahrung mit der Entwicklung von Web-Apps bewerten?

Anfänger Mittelstufe Fortgeschrittene

Wie würdest du deine Erfahrung beim 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 Web Receiver mit einem Google Cast-Gerät verwenden kannst, muss er an einem Ort gehostet werden, an dem dein Google Cast-Gerät ihn erreichen kann. Wenn Sie bereits einen Server haben, der HTTPS unterstützt, überspringen Sie die folgenden Anweisungen und notieren Sie sich die URL, da Sie sie im nächsten Abschnitt benötigen.

Wenn Sie keinen Server zur Verfügung 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. Anwendung 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. Nachdem Sie Ihre Anwendung registriert haben, erhalten Sie eine Anwendungs-ID, die Ihre Senderanwendung für API-Aufrufe verwenden muss, z. B. zum Starten einer Empfängeranwendung.

Bild der Google Cast SDK Developer Console mit hervorgehobenem Button „Neue Anwendung hinzufügen“

Klicken Sie auf „Neue Anwendung hinzufügen“.

Bild des Bildschirms „Neue Receiver-Anwendung“ mit der hervorgehobenen Option „Benutzerdefinierter Receiver“

Wählen Sie „Benutzerdefinierter Receiver“ aus. Das ist der Receiver, den wir erstellen.

Bild des Bildschirms „New Custom Receiver“ (Neuer benutzerdefinierter Receiver) mit einer URL, die in das Feld „Receiver Application URL“ (URL der Receiver-Anwendung) eingegeben wird

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

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

Außerdem müssen Sie Ihr Google Cast-Gerät registrieren, damit es auf Ihre Receiver-Anwendung zugreifen kann, bevor Sie sie veröffentlichen. Sobald Sie Ihre Empfängeranwendung veröffentlicht haben, ist sie für alle Google Cast-Geräte verfügbar. Für dieses Codelab wird empfohlen, mit einer unveröffentlichten Empfängeranwendung zu arbeiten.

Bild der Google Cast SDK Developer Console mit der Schaltfläche „Neues Gerät hinzufügen“

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

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

Gib die Seriennummer ein, die auf der Rückseite deines Cast-Geräts aufgedruckt ist, und gib dem Gerät einen aussagekräftigen Namen. Sie können die Seriennummer auch finden, indem Sie Ihren Bildschirm in Chrome spiegeln, 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 Tests bereit sind. Nach 5 bis 15 Minuten musst du dein Cast-Gerät neu starten.

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 Beispiel-Empfänger-App aussieht. Der Receiver, den wir erstellen, kann Medien mit adaptiver Bitrate wiedergeben. 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“ im Command and Control (CaC) Tool

  1. Das Tool für die Kundenakquisition sollte angezeigt werden.
  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- und Logger-Steuerelemente) des Command and Control (CaC)-Tools, das zeigt, dass es mit einer Receiver-App verbunden ist

  1. Klicken Sie oben auf den Tab „Medien laden“.

Bild des Tab „Load Media“ (Media laden) im Command and Control (CaC) Tool

  1. Klicken Sie auf die Schaltfläche „Load by Content“ (Nach Inhalt laden), um ein Beispielvideo abzuspielen.
  2. Das Video wird auf Ihrem Google Cast-Gerät wiedergegeben, um die grundlegende Receiver-Funktionalität mit dem Standard-Receiver zu demonstrieren.

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 in diesem Codelab verwendet werden:

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

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

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

http-server sollte Änderungen, die Sie vornehmen, automatisch erkennen. Wenn Sie feststellen, dass das nicht der Fall ist, beenden Sie http-server und starten Sie die App neu.

App-Design

Die Empfänger-App initialisiert die Cast-Sitzung und wartet, bis eine LOAD-Anfrage (also der Befehl zur Wiedergabe eines Mediums) von einem Absender 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 unseres Receivers enthält.

index.html

Diese HTML-Datei enthält die Benutzeroberfläche für unsere Receiver-App. Derzeit ist sie leer. Wir werden sie im Laufe des Codelabs ergänzen.

receiver.js

Dieses Skript enthält die gesamte Logik für unsere Receiver-App. Derzeit ist es nur eine leere Datei, aber im nächsten Abschnitt werden wir es mit nur wenigen Zeilen Code in einen voll funktionsfähigen Cast-Receiver verwandeln.

7. Einfacher Cast-Empfänger

Ein einfacher Cast-Empfänger initialisiert die Cast-Sitzung beim Start. Dies ist erforderlich, um allen verbundenen Senderanwendungen mitzuteilen, dass das Aufrufen des Empfängers erfolgreich war. Außerdem ist das neue SDK vorkonfiguriert, um adaptive Bitrate-Streamingmedien (mit DASH, HLS und Smooth Streaming) und einfache MP4-Dateien zu verarbeiten. Probieren wir es aus.

Initialisierung

Fügen Sie den folgenden Code in den Header von index.html ein:

<head>
  ...

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

Fügen Sie den folgenden Code in index.html <body> vor dem <footer>-Ladevorgang receiver.js, ein, damit das Receiver-SDK genügend Platz hat, um die Standard-Receiver-Benutzeroberfläche zu starten, die mit dem gerade hinzugefügten Skript ausgeliefert wird.

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

Jetzt müssen wir das SDK in js/receiver.js initialisieren. Dazu gehören:

  • eine Referenz auf CastReceiverContext abrufen, Ihren primären Einstiegspunkt für das gesamte Receiver SDK
  • Speichern eines Verweises auf PlayerManager, das Objekt, das die Wiedergabe übernimmt und Ihnen alle Hooks zur Verfügung stellt, die Sie zum Einbinden Ihrer eigenen benutzerdefinierten Logik benötigen
  • Initialisieren Sie das SDK, indem Sie start() für CastReceiverContext aufrufen.

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 neuen Empfänger auszuprobieren.

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

Bild des Tabs „Cast Connect & Logger Controls“ im Command and Control (CaC) Tool

Ersetzen Sie die App-ID im Feld durch Ihre eigene und klicken Sie auf „App-ID festlegen“. Dadurch wird das Tool angewiesen, Ihren Receiver beim Starten der Cast-Sitzung zu verwenden.

Medien streamen

Auf übergeordneter Ebene muss Folgendes passieren, um Medien auf einem Cast-Gerät abzuspielen:

  1. Der Absender erstellt ein MediaInfo-JSON-Objekt aus dem Cast SDK, das ein Media-Element modelliert.
  2. Der Absender 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, um die Inhalte abzuspielen.
  4. Der Empfänger überwacht und verfolgt den Medienstatus.
  5. Der Absender sendet Wiedergabebefehle an den Empfänger, um die Wiedergabe basierend auf Nutzerinteraktionen mit der Absender-App zu steuern.

Bei diesem ersten einfachen Versuch wird MediaInfo mit einer URL für ein abspielbares Asset (gespeichert in MediaInfo.contentUrl) gefüllt.

Ein realer Absender verwendet eine anwendungsspezifische Media-Kennung in MediaInfo.contentId. Der Empfänger verwendet 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 Einfügen von Informationen zu Werbeunterbrechungen.

Im nächsten Abschnitt werden wir deinen Receiver so erweitern, dass er genau das tut. Klicke vorerst auf das Cast-Symbol und wähle dein Gerät aus, um den Receiver zu öffnen.

Bild des Tab „Cast Connect & Logger Controls“ (Cast Connect- und Logger-Steuerelemente) des Command and Control-Tools (CaC-Tool), das zeigt, dass es mit einer Receiver-App verbunden ist

Rufen Sie den Tab „Load Media“ (Media laden) auf und klicken Sie auf die Schaltfläche „Load by Content“ (Nach Inhalt laden). Auf dem Empfänger sollte die Wiedergabe der Beispielinhalte gestartet werden.

Bild des Tab „Load Media“ (Media laden) im Command and Control (CaC) Tool

Das Receiver SDK bietet standardmäßig folgende Funktionen:

  • Streamingsitzung wird initialisiert
  • Eingehende LOAD-Anfragen von Absendern mit abspielbaren Assets verarbeiten
  • Stelle eine einfache Player-Benutzeroberfläche bereit, die auf dem großen Bildschirm angezeigt werden kann.

Sehen Sie sich das CaC-Tool und seinen Code an, bevor Sie mit dem nächsten Abschnitt fortfahren. Dort erweitern wir unseren Receiver, damit er mit einer einfachen Beispiel-API kommunizieren kann, um eingehende LOAD-Anfragen von Absendern zu bearbeiten.

9. In eine externe API einbinden

Entsprechend der Art und Weise, wie die meisten Entwickler in realen Anwendungen mit ihren Cast-Empfängern interagieren, werden wir unseren Empfänger so ändern, dass er LOAD-Anfragen verarbeitet, die sich über den API-Schlüssel auf die beabsichtigten Medieninhalte beziehen, anstatt eine URL für ein abspielbares Asset zu senden.

Anwendungen tun dies in der Regel aus folgenden Gründen:

  • Der Absender kennt die URL der Inhalte möglicherweise nicht.
  • Die Cast-Anwendung ist so konzipiert, dass sie die Authentifizierung, andere Geschäftslogik oder API-Aufrufe direkt auf dem Empfängergerät verarbeitet.

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 Nachrichtensender des SDK erreichen. In diesem Abschnitt geht es um LOAD-Anfragen. Wir werden Folgendes tun:

  • Eingehende LOAD-Anfrage und zugehörige benutzerdefinierte contentId lesen.
  • Rufen Sie unsere API mit GET auf, um das streamfähige Asset anhand seiner contentId zu suchen.
  • Ändern Sie die LOAD-Anfrage mit der URL des Streams.
  • Ändern Sie das MediaInformation-Objekt, um die Parameter für den Streamtyp festzulegen.
  • Leite 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 SDK-Hooks zum Anpassen gängiger Receiver-Aufgaben, während sie sich weiterhin auf eine größtenteils sofort einsatzbereite Lösung stützt.

Beispiel-API

Rufen Sie in Ihrem Browser https://storage.googleapis.com/cpe-sample-media/content.json auf, um sich unseren Beispielvideokatalog anzusehen. Die Inhalte umfassen URLs für Posterbilder im PNG-Format sowie DASH- und HLS-Streams. Die DASH- und HLS-Streams verweisen auf demultiplexte 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 wird der Schlüssel jedes Eintrags (z. B. bbb, fbb_ad) der URL des Streams zugeordnet, nachdem der Receiver 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 vorliegt, 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 Ihrer js/receiver.js-Datei den folgenden Code hinzu, direkt vor dem Aufruf von 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);
          }
        });
      });
    });

Im nächsten Abschnitt wird beschrieben, wie Sie die media-Eigenschaft der Ladeanfrage für DASH-Inhalte konfigurieren.

DASH-Inhalte der Sample API verwenden

Nachdem wir den Lade-Interceptor vorbereitet haben, geben wir den Inhaltstyp für den Empfänger an. Diese Informationen enthalten die URL der Master-Playlist und den MIME-Typ des Streams für den Empfänger. Fügen Sie der Datei „js/receiver.js“ im 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';
            ...
          }
        });
      });
    });

Sobald Sie diesen Schritt abgeschlossen haben, können Sie mit dem Testen fortfahren, um das Laden mit DASH-Inhalten auszuprobieren. Wenn Sie das Laden mit HLS-Inhalten testen möchten, fahren Sie mit dem nächsten Schritt fort.

HLS-Beispielinhalte der API verwenden

Die Beispiel-API enthält sowohl HLS- als auch DASH-Inhalte. Zusätzlich zum Festlegen von contentType wie im vorherigen Schritt muss die Ladeanfrage einige zusätzliche Eigenschaften enthalten, damit die HLS-URLs der Beispiel-API verwendet werden können. Wenn der Receiver für die Wiedergabe von HLS-Streams konfiguriert ist, ist der erwartete Standardcontainertyp Transport Stream (TS). Daher versucht der Empfänger, die MP4-Beispielstreams im TS-Format zu öffnen, wenn nur das Attribut contentUrl geändert wird. Im Lade-Request sollte das MediaInformation-Objekt mit zusätzlichen Attributen geändert werden, damit der Empfänger weiß, dass der Inhalt vom Typ MP4 und nicht TS ist. Fügen Sie der Datei „js/receiver.js“ im Load-Interceptor den folgenden Code hinzu, um die Eigenschaften contentUrl und contentType zu ändern. Fügen Sie 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;
            ...
          }
        });
      });
    });

Ausprobieren

Öffnen Sie noch einmal das Command and Control (CaC) Tool und legen Sie die App-ID auf die App-ID Ihres Empfängers fest. Wählen Sie Ihr Gerät über das Cast-Symbol aus.

Rufen Sie den Tab „Medien laden“ auf. Löschen Sie 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 zu unseren Media enthält.

Bild des Tab „Load Media“ (Media laden) im Command and Control (CaC) Tool

Wenn alles mit Ihren Änderungen am Receiver funktioniert hat, sollte der Interceptor das MediaInfo-Objekt in etwas umwandeln, das das SDK auf dem Bildschirm wiedergeben kann.

Klicken Sie auf die Schaltfläche „Nach Inhalt laden“, um zu prüfen, ob Ihre Media richtig wiedergegeben werden. Sie können die Content-ID in der Datei content.json ändern.

10. Für Smart Displays optimieren

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

In diesem Abschnitt wird beschrieben, wie du deine Empfängeranwendung optimierst, wenn sie auf Smart Displays gestartet wird, und wie du die Player-Steuerelemente anpasst.

Auf UI-Steuerelemente zugreifen

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

...

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

context.start();

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

context.start({ touchScreenOptimizedApp: true });

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

Videosteuerung

Bei MetadataType.MOVIE, MetadataType.TV_SHOW und MetadataType.GENERIC wird das UI-Steuerungsobjekt für Smart Displays wie im Beispiel unten angezeigt.

Bild eines Videos, das mit eingeblendeten UI-Steuerelementen abgespielt 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 wie unten dargestellt angezeigt:

Bild von Musik, die abgespielt wird, mit überlagerten 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 Objekt „UI-Steuerelemente“ bestimmt auch, ob ein ControlsButton basierend auf MediaStatus.supportedMediaCommands angezeigt wird.

Wenn der Wert von supportedMediaCommands gleich ALL_BASIC_MEDIA ist, wird das Standard-Steuerelementlayout wie unten dargestellt:

Bild von Media Player-Steuerelementen: Fortschrittsanzeige, Schaltfläche „Wiedergabe“, Schaltflächen „Vorspulen“ und „Zurückspulen“ aktiviert

Wenn der Wert von supportedMediaCommands gleich ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT ist, wird das Standard-Steuerelementlayout wie unten dargestellt:

Bild der Media Player-Steuerelemente: Fortschrittsbalken, Schaltfläche „Wiedergabe“, Schaltflächen „Vorwärts springen“ und „Rückwärts springen“ sowie die Schaltflächen „Vorherige in die Warteschlange stellen“ und „Nächste in die Warteschlange stellen“ sind aktiviert.

Wenn der Wert von „supportedMediaCommands“ gleich PAUSE | QUEUE_PREV | QUEUE_NEXT ist, wird das Standard-Steuerungslayout wie unten dargestellt:

Bild der Media Player-Steuerelemente: Fortschrittsbalken, Schaltfläche „Wiedergabe“ und die Schaltflächen „Vorherige in die Warteschlange aufnehmen“ und „Nächste in die Warteschlange aufnehmen“ sind aktiviert.

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

Bild der Media Player-Steuerelemente: Fortschrittsbalken, Schaltfläche „Wiedergabe“, Schaltflächen „Vorwärts springen“ und „Zurückspringen“, Schaltflächen „Vorherige in die Warteschlange aufnehmen“ und „Nächste in die Warteschlange aufnehmen“ sowie Schaltflächen für Untertitel

Wenn Sie den Wert von supportedMediaCommands nach dem Start eines Receiver-Kontexts 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.

Steuertasten anpassen

Mit PlayerDataBinder können Sie die Steuerelemente anpassen. Fügen Sie Ihrer js/receiver.js-Datei unter den touchControls 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. Media-Browsing auf Smart Displays implementieren

„Media Browse“ ist eine CAF Receiver-Funktion, mit der Nutzer auf Touchgeräten zusätzliche Inhalte entdecken können. Dazu verwenden Sie PlayerDataBinder, um die BrowseContent-Benutzeroberfläche festzulegen. Anschließend können Sie das Feld mit BrowseItems füllen, je nachdem, welche Inhalte Sie anzeigen möchten.

BrowseContent

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

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

  1. BrowseContent.title
  2. BrowseContent.items

Seitenverhältnis

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

BrowseItem

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

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

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

Media Browse-Daten festlegen

Sie können eine Liste von Media-Inhalten zum Durchsuchen bereitstellen, indem Sie setBrowseContent aufrufen. Fügen Sie den folgenden Code in Ihrer js/receiver.js-Datei unter playerDataBinder und in Ihrem MEDIA_CHANGED-Ereignis-Listener hinzu, um die Browsing-Elemente mit dem Titel „Demnächst“ 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 Element zum Durchsuchen von Medien klicken, wird der LOAD-Interceptor ausgelöst. Fügen Sie Ihrem LOAD-Interceptor den folgenden Code hinzu, um request.media.contentId dem request.media.entity aus dem Media-Browsing-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) => {
            ...
        });
    });

Sie können das BrowseContent-Objekt auch auf null setzen, um die Media Browse-Benutzeroberfläche zu entfernen.

12. Fehlerbehebung bei Receiver-Apps

Das Cast Receiver SDK bietet Entwicklern eine weitere Möglichkeit, Receiver-Apps mithilfe der CastDebugLogger API und eines zugehörigen Command and Control (CaC) Tool (Befehls- und Steuerungstool) zu debuggen, um Logs zu erfassen.

Initialisierung

Um die API einzubinden, fügen Sie das Quellskript CastDebugLogger in Ihre Datei „index.html“ ein. Die Quelle muss 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 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 der Debug-Logger aktiviert ist, wird auf dem Empfänger ein Overlay mit DEBUG MODE angezeigt.

Bild eines Videos, das abgespielt wird. In der oberen linken Ecke des Frames wird auf rotem Hintergrund die Meldung „DEBUG MODE“ (DEBUG-MODUS) angezeigt.

Spielerereignisse protokollieren

Mit CastDebugLogger können Sie ganz einfach Player-Ereignisse protokollieren, die vom CAF Receiver SDK ausgelöst werden, und verschiedene Logger-Ebenen verwenden, um die Ereignisdaten zu protokollieren. In der loggerLevelByEvents-Konfiguration wird mit cast.framework.events.EventType und cast.framework.events.category angegeben, welche Ereignisse protokolliert werden.

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

Log-Meldungen und benutzerdefinierte Tags

Mit der CastDebugLogger API können Sie Logmeldungen erstellen, die mit unterschiedlichen Farben im Debug-Overlay des Empfängers angezeigt werden. Die folgenden Log-Methoden sind verfügbar, sortiert nach Priorität (höchste bis niedrigste):

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

Bei jeder Log-Methode ist der erste Parameter ein benutzerdefiniertes Tag. Das kann ein beliebiger identifizierender String sein, der für Sie sinnvoll ist. Im CastDebugLogger werden Tags zum Filtern der Logs verwendet. Die Verwendung von Tags wird weiter unten ausführlich erläutert. Der zweite Parameter ist die Log-Nachricht.

Um Logs in Aktion zu sehen, 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 Nachrichten im Debug-Overlay angezeigt werden, indem Sie die Log-Ebene in loggerLevelByTags für jedes benutzerdefinierte Tag festlegen. Wenn Sie beispielsweise ein benutzerdefiniertes Tag mit der Logebene cast.framework.LoggerLevel.DEBUG aktivieren, werden alle Meldungen angezeigt, die mit Fehler-, Warnungs-, Info- und Debug-Logmeldungen hinzugefügt wurden. Wenn Sie ein benutzerdefiniertes Tag mit der Ebene WARNING aktivieren, werden nur Fehler- und Warnmeldungen angezeigt.

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

Fügen Sie den folgenden Code unter dem CORE-Ereignislogger 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,
};

Fehlerbehebungs-Overlay

Der Cast Debug Logger bietet ein Debug-Overlay auf dem Empfänger, um Ihre benutzerdefinierten Logmeldungen auf dem Cast-Gerät anzuzeigen. Mit showDebugLogs können Sie das Debug-Overlay ein- und ausblenden und mit clearDebugLogs Log-Nachrichten im Overlay löschen.

Fügen Sie den folgenden Code hinzu, um das Debug-Overlay auf Ihrem Empfängergerät in der Vorschau anzusehen.

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 Fehlerbehebungs-Overlay, einer Liste von Debug-Log-Nachrichten auf einem durchscheinenden Hintergrund über einem Videobild

13. Glückwunsch

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

Weitere Informationen finden Sie im Entwicklerleitfaden für Web Receiver.