Benutzerdefinierten Web Receiver erstellen

1. Überblick

Google Cast-Logo

In diesem Codelab erfährst du, wie du eine App für einen benutzerdefinierten Web-Receiver erstellst, 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 kann Ihre App Google Cast-fähige Geräte steuern, z. B. einen Fernseher oder ein Soundsystem. Das Cast SDK stellt Ihnen die erforderlichen UI-Komponenten gemäß der Checkliste für das Design von Google Cast zur Verfügung.

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

Ziele

Wenn Sie dieses Codelab abgeschlossen haben, verfügen Sie über eine HTML5-App, die als Ihr eigener benutzerdefinierter Receiver fungiert und Videoinhalte auf für Google Cast optimierten Geräten anzeigen kann.

Lerninhalte

  • Einrichtung für die Empfängerentwicklung
  • Grundlagen für für Google Cast optimierte Receiver, die auf dem Cast App Framework basieren
  • So erhalten Sie ein gestreamtes Video.
  • Informationen zum Integrieren des Debug-Loggers.
  • So optimierst du deinen Empfänger für Smart Displays.

Voraussetzungen

Plattform

  • Sie müssen über Vorkenntnisse in der Webentwicklung verfügen.
  • Außerdem benötigst du Vorkenntnisse im Fernsehen.

Wie werden Sie dieses Tutorial verwenden?

Nur lesen Lesen und die Übungen abschließen

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

Neuling Fortgeschritten Profi

Wie würdest du deine Erfahrung mit Fernsehen bewerten?

Neuling Fortgeschritten Profi

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 Webempfänger mit einem Übertragungsgerät verwenden können, muss es an einem Ort gehostet werden, an dem Ihr Übertragungsgerät eine Verbindung herstellen kann. Sollte Ihnen bereits ein Server zur Verfügung stehen, der HTTPS unterstützt, überspringen Sie die folgende Anleitung und merken Sie sich die URL, da Sie sie im nächsten Abschnitt benötigen.

Falls Ihnen 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, 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. Apps in der Cast-Entwicklerkonsole registrieren

Sie müssen Ihre Anwendung registrieren, um einen benutzerdefinierten Empfänger, wie in diesem Codelab integriert, auf Chromecast-Geräten ausführen zu können. Nachdem Sie Ihre Anwendung registriert haben, erhalten Sie eine Anwendungs-ID, die Ihre Senderanwendung 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 "Neue App hinzufügen"

Klicken Sie auf „Neue Anwendung hinzufügen“.

Screenshot des Bildschirms „New Receiver Application“ (Anwendung für neuen Empfänger), wobei die Option „Custom Receiver“ (Benutzerdefinierter Empfänger) hervorgehoben 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 des neuen Empfängers ein und verwende die URL, die du letztendlich erhalten hast

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

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

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

Klicke auf „Neues Gerät hinzufügen“.

Bild des Dialogfelds "Cast Receiver-Gerät 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 finden, indem Sie Ihren Bildschirm in Chrome streamen, wenn Sie die Google Cast SDK Developer Console aufrufen.

Es dauert 5 bis 15 Minuten, bis Empfänger und Gerät zum Testen 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 ein Beispiel einer fertigen Empfängeranwendung an. Der Empfänger, den wir erstellen werden, kann Medien mithilfe von Streaming mit adaptiver Bitrate wiedergeben. Wir verwenden Beispielinhalte, die für Dynamic Adaptive Streaming over HTTP (DASH) codiert sind.

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

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

  1. Sie sollten unser CaC-Tool sehen.
  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.

Bild der Registerkarte „Cast Connect & Logger Controls“ des Command and Control (CaC)-Tools, das anzeigt, dass es mit einer Empfänger-App verbunden ist

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

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

  1. Klicke auf die Schaltfläche "Nach Inhalt laden", um ein Beispielvideo abzuspielen.
  2. Das Video wird auf Ihrem Google Cast-Gerät wiedergegeben, um die grundlegenden Receiver-Funktionen bei Verwendung des Standardempfängers zu zeigen.

6. Startprojekt vorbereiten

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

  • eine Absender-App auf einem Mobilgerät oder Laptop
  • 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 durcharbeitest, sollte http-server die von dir vorgenommenen Änderungen übernehmen. Sollte dies nicht der Fall sein, beenden Sie den Vorgang und starten Sie http-server neu.

App-Design

Die Empfänger-App initialisiert die Streaming-Sitzung und wartet so lange, bis eine LOAD-Anfrage (also der Befehl zur Wiedergabe eines Medienelements) von einem Sender eintrifft.

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. Sie ist vorerst leer und wird während des gesamten Code-Labs immer wieder hinzugefügt.

receiver.js

Dieses Skript verwaltet die gesamte Logik für unsere Empfänger-App. 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. Ein einfacher Streaming-Receiver

Ein einfacher Cast-Receiver initialisiert die Streaming-Sitzung beim Start. Dies ist erforderlich, um allen verbundenen Senderanwendungen mitzuteilen, dass der Empfänger erfolgreich aufgerufen wurde. Darüber hinaus ist das neue SDK vorkonfiguriert, um Streaming-Medien mit adaptiver Bitrate (mit DASH, HLS und Smooth Streaming) sowie MP4-Dateien zu verarbeiten. 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ügen Sie den folgenden Code in index.html <body> ein, bevor das <footer>, das receiver.js, lädt, um dem Empfänger-SDK Platz bereitzustellen, um die standardmäßige Empfänger-UI aufzurufen, 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 das PlayerManager, das Objekt, das die Wiedergabe verarbeitet, und stellt dir alle Hooks bereit, die du zum Einbinden deiner eigenen benutzerdefinierten Logik benötigst
  • SDK durch Aufrufen von start() für CastReceiverContext initialisieren

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

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

context.start();

8. Einfache Videoinhalte streamen

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

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

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

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

Medien werden gestreamt

Damit Sie Medien auf einem Übertragungsgerät abspielen 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 der Nutzerinteraktion mit der Sender-App zu steuern.

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

Ein realer Absender verwendet eine anwendungsspezifische Medien-ID in MediaInfo.contentId. Der Empfänger verwendet die contentId als Kennung, um geeignete 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 vorerst auf das Cast-Symbol und wähle dein Gerät aus, um deinen Receiver zu öffnen.

Bild der Registerkarte „Cast Connect & Logger Controls“ des Command and Control (CaC)-Tools, das anzeigt, dass es mit einer Empfänger-App verbunden ist

Navigieren Sie zum Tab "Medien laden" und klicken Sie auf die Schaltfläche "Nach Inhalt laden". Der Empfänger sollte die Hörprobe wiedergeben.

Bild des Tabs &quot;Load Media&quot; (Medien laden) des Command and Control (CaC)-Tools

Das Receiver SDK ist sofort einsatzbereit und verarbeitet Folgendes:

  • Streamingsitzung initialisieren
  • Eingehende LOAD-Anfragen von Absendern verarbeiten, die abspielbare Assets enthalten
  • Stellen Sie eine einfache 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 um eine einfache Beispiel-API, mit der eingehende LOAD-Anfragen von Absendern verarbeitet werden können.

9. In externe API einbinden

In Übereinstimmung mit der Art und Weise, wie die meisten Entwickler in realen Apps mit ihren Cast Receivern 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 App ist darauf ausgelegt, Authentifizierungen, andere Geschäftslogiken 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 und tun Folgendes:

  • Die eingehende LOAD-Anfrage und ihre benutzerdefinierte contentId lesen.
  • Rufe unsere API mit einem GET-Aufruf auf, um das streamfähige Asset anhand seiner contentId zu ermitteln.
  • Ändere die LOAD-Anfrage mit der URL des Streams.
  • Ändern Sie das Objekt MediaInformation, um die Parameter für den Streamtyp 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 für die Anpassung häufiger Empfängeraufgaben, während sie sich dennoch auf eine größtenteils vorkonfigurierte Umgebung verlässt.

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 sowohl DASH- als auch 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 Stream-URL 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 stellt. Sobald die Datei JSON 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 wird beschrieben, wie Sie die media-Eigenschaft der Ladeanfrage für DASH-Inhalte konfigurieren.

DASH-Content mit der Beispiel-API

Nachdem wir den Load-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 im Promise() des LOAD-Abfangers 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 Abschnitt „Testen“ fortfahren und versuchen, DASH-Inhalte zu laden. Wenn du das Laden mit HLS-Content testen möchtest, solltest du stattdessen den nächsten Schritt lesen.

HLS-Inhalt der Beispiel-API verwenden

Die Beispiel-API enthält HLS-Inhalte 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 Transportstream (TS) erwartet. Infolgedessen versucht der Empfänger, die Beispiel-MP4-Streams im TS-Format zu öffnen, wenn nur das Attribut contentUrl geändert wird. In der Ladeanfrage sollte das MediaInformation-Objekt mit zusätzlichen Attributen geändert werden, damit der Empfänger weiß, dass der Inhalt vom Typ MP4 und nicht vom Typ TS ist. Fügen Sie im Load-Abfangprogramm den folgenden Code in die Datei „js/receiver.js“ ein, um die Attribute 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;
            ...
          }
        });
      });
    });

Testen

Öffnen Sie wieder das Command and Control (CaC)-Tool und legen Sie als App-ID die App-ID des 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 „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 &quot;Load Media&quot; (Medien laden) des Command and Control (CaC)-Tools

Vorausgesetzt, dass mit deinen Änderungen am Empfänger alles reibungslos funktioniert hat, sollte der Interceptor dafür sorgen, dass das MediaInfo-Objekt so gestaltet wird, dass es das SDK auf dem Bildschirm wiedergeben kann.

Klicken Sie auf die Schaltfläche "Nach Inhalt laden", um zu sehen, ob Ihre Medien korrekt wiedergegeben werden. Sie können die Content ID-ID in der Datei content.json jederzeit ändern.

10. Für Smart Displays optimieren

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 die Receiver-App beim Start auf Smart Displays optimieren und die Steuerelemente des Players anpassen kannst.

Auf UI-Steuerelemente zugreifen

Auf das UI-Steuerelemente-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 du das <cast-media-player>-Element nicht verwendest, musst du touchScreenOptimizedApp in CastReceiverOptions festlegen. In diesem Codelab verwenden wir das Element <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Die standardmäßigen Steuerungsschaltflä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-Steuerelemente-Objekt für Smart Displays wie im folgenden Beispiel angezeigt.

Abbildung eines Videos mit eingeblendeten UI-Steuerelementen

  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:

Bild von Musik, die mit eingeblendeten UI-Steuerelementen abgespielt wird

  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 basierend auf MediaStatus.supportedMediaCommands auch, ob ein ControlsButton angezeigt wird oder nicht.

Wenn der Wert von supportedMediaCommands gleich ALL_BASIC_MEDIA ist, wird das Standardlayout für Steuerelemente so angezeigt:

Abbildung der Mediaplayer-Steuerung: Fortschrittsbalken, Wiedergabeschaltfläche, Schaltflächen „Vorspulen“ und „Zurückspulen“ aktiviert

Wenn der Wert von supportedMediaCommands gleich ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT ist, wird das Standardlayout für Steuerelemente so angezeigt:

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

Wenn der Wert von „supportedMediaCommands“ gleich PAUSE | QUEUE_PREV | QUEUE_NEXT ist, wird das standardmäßige Layout für Steuerelemente so angezeigt:

Abbildung der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Wiedergabeschaltfläche und Schaltflächen „Vorherige Warteschlange“ und „Nächste in der Warteschlange“ aktiviert

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

Abbildung der Steuerelemente des Mediaplayers: Fortschrittsanzeige, Schaltfläche „Wiedergabe“, Schaltflächen „Vorwärts springen“ und „Zurückspulen“, Schaltflächen „Vorherige Warteschlange“ und „Nächste in der Warteschlange“ und 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.

Anpassen der Steuerungsschaltflächen

Sie können 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 für die 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 auf Touchgeräten zusätzliche Inhalte entdecken können. Zur Implementierung verwenden Sie PlayerDataBinder, um die BrowseContent-UI festzulegen. Anschließend können Sie ihn basierend auf den Inhalten, die Sie darstellen möchten, mit BrowseItems füllen.

BrowseContent

Im Folgenden finden Sie ein Beispiel für die BrowseContent-UI und ihre Eigenschaften:

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

  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, LANDSCAPE_16_TO_9.

BrowseItem

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

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

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

Daten zum Durchsuchen von Medien festlegen

Sie können eine Liste mit Medieninhalten zum Durchsuchen bereitstellen, indem Sie setBrowseContent aufrufen. Fügen Sie der Datei js/receiver.js unter playerDataBinder und im Event-Listener MEDIA_CHANGED den folgenden Code hinzu, um die durchsuchbaren Elemente mit dem 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);
  });

Durch Klicken auf ein medienstöberbares Element wird der LOAD-Abfangvorgang ausgelöst. Fügen Sie dem LOAD-Interceptor den folgenden Code hinzu, um request.media.contentId dem request.media.entity aus dem Mediensuchelement 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 Objekt BrowseContent auch auf null setzen, um die Benutzeroberfläche für die Mediensuche zu entfernen.

12. Fehler in Empfangs-Apps beheben

Das Cast Receiver SDK bietet Entwicklern eine weitere Option, mit der sie Empfänger-Apps einfach debuggen können. Dazu verwenden sie die CastDebugLogger API und ein zugehöriges Befehls- und Steuertool (CaC), um Protokolle zu erfassen.

Initialisierung

Wenn Sie die API einbinden möchten, fügen Sie der Datei „index.html“ das Quellskript CastDebugLogger hinzu. 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 am Anfang 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 die Debug-Protokollierung aktiviert ist, wird auf dem Empfänger ein Overlay mit DEBUG MODE angezeigt.

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

Player-Ereignisse protokollieren

Mit CastDebugLogger kannst du ganz einfach Player-Ereignisse protokollieren, die vom CAF Receiver SDK ausgelöst werden, und verschiedene Protokollierungsebenen verwenden, um die Ereignisdaten zu 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 Deklaration castDebugLogger hinzu, 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
}

Logeinträge und benutzerdefinierte Tags

Mit der CastDebugLogger API können Sie Protokollmeldungen erstellen, die in verschiedenen Farben im Debug-Overlay des Empfängers angezeigt werden. Die folgenden Protokollmethoden stehen zur Verfügung, in der Reihenfolge von der höchsten zur niedrigsten Priorität:

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

Der erste Parameter für jede Logmethode ist ein benutzerdefiniertes Tag. Dabei kann es sich um einen beliebigen identifizierenden String handeln, den Sie für sinnvoll 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.

Damit Logs in Aktion angezeigt werden, fügen Sie dem 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 für jedes benutzerdefinierte Tag in loggerLevelByTags die Protokollebene festlegen. Wenn Sie beispielsweise ein benutzerdefiniertes Tag mit der Logebene „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 Fehler- und Warnmeldungen angezeigt.

Die loggerLevelByTags-Konfiguration ist optional. Wenn ein benutzerdefiniertes Tag nicht für seine Logger-Ebene 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

Das Cast Debug Logger stellt ein Debug-Overlay auf dem Empfänger bereit, um Ihre benutzerdefinierten Protokollnachrichten auf dem Übertragungsgerät anzuzeigen. Verwenden Sie showDebugLogs, um das Debug-Overlay umzuschalten, und clearDebugLogs, um Protokollmeldungen im Overlay zu löschen.

Fügen Sie den folgenden Code hinzu, um eine Vorschau des Debug-Overlays auf dem 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 Debug-Overlay, einer Liste von Debug-Protokollmeldungen auf einem durchscheinenden Hintergrund über einem Videoframe

13. Glückwunsch

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

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