Zentrale Funktionen zu Ihrem benutzerdefinierten Web-Receiver hinzufügen

Diese Seite enthält Code-Snippets und Beschreibungen der Funktionen, die für eine benutzerdefinierte Web-Receiver-App verfügbar sind.

  1. Ein cast-media-player-Element, das die integrierte Player-Benutzeroberfläche des Webempfängers darstellt.
  2. Benutzerdefinierter CSS-ähnlicher Stil für das cast-media-player-Element, um verschiedene UI-Elemente wie background-image, splash-image und font-family zu gestalten.
  3. Ein Skriptelement zum Laden des Web-Receiver-Frameworks.
  4. JavaScript-Code zum Abfangen von Nachrichten und Verarbeiten von Ereignissen.
  5. In die Warteschlange für die automatische Wiedergabe stellen.
  6. Optionen zum Konfigurieren der Wiedergabe.
  7. Optionen zum Festlegen des Web-Receiver-Kontexts.
  8. Optionen zum Festlegen von Befehlen, die von der Web Receiver-App unterstützt werden.
  9. Ein JavaScript-Aufruf zum Starten der Web-Empfänger-Anwendung.

Anwendungskonfiguration und -optionen

Anwendung konfigurieren

CastReceiverContext ist die äußerste Klasse, die für Entwickler sichtbar ist. Sie verwaltet das Laden der zugrunde liegenden Bibliotheken und die Initialisierung des Web Receiver SDK. Das SDK bietet APIs, mit denen App-Entwickler das SDK über CastReceiverOptions konfigurieren können. Diese Konfigurationen werden einmal pro Anwendungsstart ausgewertet und an das SDK übergeben, wenn der optionale Parameter im Aufruf von start festgelegt wird.

Im folgenden Beispiel wird gezeigt, wie das Standardverhalten für die Erkennung, ob eine Senderverbindung noch aktiv ist, überschrieben wird. Wenn der Web-Empfänger maxInactivity Sekunden lang nicht mit einem Sender kommunizieren konnte, wird ein SENDER_DISCONNECTED-Ereignis gesendet. Die folgende Konfiguration überschreibt dieses Zeitlimit. Das kann bei der Fehlerbehebung nützlich sein, da so verhindert wird, dass die Web-Empfänger-App die Chrome Remote Debugger-Sitzung schließt, wenn keine verbundenen Sender im Status IDLE vorhanden sind.

const context = cast.framework.CastReceiverContext.getInstance();
const options = new cast.framework.CastReceiverOptions();
options.maxInactivity = 3600; // Development only
context.start(options);

Player konfigurieren

Beim Laden von Inhalten bietet das Web Receiver SDK die Möglichkeit, Wiedergabevariablen wie DRM-Informationen, Wiederholungskonfigurationen und Anfrage-Handler mit cast.framework.PlaybackConfig zu konfigurieren. Diese Informationen werden von PlayerManager verarbeitet und zum Zeitpunkt der Erstellung der Spieler ausgewertet. Player werden jedes Mal erstellt, wenn eine neue Last an das Web Receiver SDK übergeben wird. Änderungen an PlaybackConfig nach dem Erstellen des Players werden beim nächsten Laden von Inhalten ausgewertet. Das SDK bietet die folgenden Methoden zum Ändern des PlaybackConfig.

  • CastReceiverOptions.playbackConfig, um die Standardkonfigurationsoptionen beim Initialisieren von CastReceiverContext zu überschreiben.
  • PlayerManager.getPlaybackConfig(), um die aktuelle Konfiguration abzurufen.
  • PlayerManager.setPlaybackConfig(), um die aktuelle Konfiguration zu überschreiben. Diese Einstellung wird auf alle nachfolgenden Ladevorgänge angewendet oder bis sie wieder überschrieben wird.
  • PlayerManager.setMediaPlaybackInfoHandler(), um zusätzliche Konfigurationen nur für die geladene Mediendatei zusätzlich zu den aktuellen Konfigurationen anzuwenden. Der Handler wird unmittelbar vor der Erstellung des Players aufgerufen. Hier vorgenommene Änderungen sind nicht dauerhaft und werden nicht in Abfragen an getPlaybackConfig() einbezogen. Wenn die nächste Mediendatei geladen wird, wird dieser Handler noch einmal aufgerufen.

Im folgenden Beispiel wird gezeigt, wie Sie die PlaybackConfig beim Initialisieren der CastReceiverContext festlegen. Die Konfiguration überschreibt ausgehende Anfragen zum Abrufen von Manifesten. Der Handler gibt an, dass CORS-Access-Control-Anfragen mit Anmeldedaten wie Cookies oder Autorisierungsheadern erfolgen sollen.

const playbackConfig = new cast.framework.PlaybackConfig();
playbackConfig.manifestRequestHandler = requestInfo => {
  requestInfo.withCredentials = true;
};
context.start({playbackConfig: playbackConfig});

Im folgenden Beispiel wird gezeigt, wie Sie PlaybackConfig mit dem in PlayerManager bereitgestellten Getter und Setter überschreiben. Mit dieser Einstellung wird der Player so konfiguriert, dass die Wiedergabe des Contents fortgesetzt wird, nachdem ein Segment geladen wurde.

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
const playbackConfig = (Object.assign(
            new cast.framework.PlaybackConfig(), playerManager.getPlaybackConfig()));
playbackConfig.autoResumeNumberOfSegments = 1;
playerManager.setPlaybackConfig(playbackConfig);

Im folgenden Beispiel wird gezeigt, wie Sie die PlaybackConfig für eine bestimmte Ladeanfrage mithilfe des Media Playback Info Handlers überschreiben. Der Handler ruft eine von der Anwendung implementierte Methode getLicenseUrlForMedia auf, um die licenseUrl aus der contentId des aktuellen Elements abzurufen.

playerManager.setMediaPlaybackInfoHandler((loadRequestData, playbackConfig) => {
  const mediaInformation = loadRequestData.media;
  playbackConfig.licenseUrl = getLicenseUrlForMedia(mediaInformation.contentId);

  return playbackConfig;
});

Event-Listener

Mit dem Web Receiver SDK kann Ihre Web Receiver-Anwendung Player-Ereignisse verarbeiten. Der Ereignis-Listener verwendet einen cast.framework.events.EventType-Parameter (oder ein Array dieser Parameter), der die Ereignisse angibt, die den Listener auslösen sollen. Vorkonfigurierte Arrays von cast.framework.events.EventType, die für das Debugging nützlich sind, finden Sie in cast.framework.events.category. Der Ereignisparameter liefert zusätzliche Informationen zum Ereignis.

Wenn Sie beispielsweise wissen möchten, wann eine Änderung von mediaStatus übertragen wird, können Sie die folgende Logik verwenden, um das Ereignis zu verarbeiten:

const playerManager =
    cast.framework.CastReceiverContext.getInstance().getPlayerManager();
playerManager.addEventListener(
    cast.framework.events.EventType.MEDIA_STATUS, (event) => {
      // Write your own event handling code, for example
      // using the event.mediaStatus value
});

Abfangen von Nachrichten

Mit dem Web Receiver SDK kann deine Web Receiver-App Nachrichten abfangen und benutzerdefinierten Code für diese Nachrichten ausführen. Der Nachrichten-Interceptor verwendet einen cast.framework.messages.MessageType-Parameter, der angibt, welche Art von Nachricht abgefangen werden soll.

Der Interceptor sollte die geänderte Anfrage oder ein Promise zurückgeben, das mit dem geänderten Anfragewert aufgelöst wird. Wenn null zurückgegeben wird, wird der Standard-Nachrichten-Handler nicht aufgerufen. Weitere Informationen finden Sie unter Medien laden.

Wenn Sie beispielsweise die Daten der Ladeanfrage ändern möchten, können Sie die folgende Logik verwenden, um sie abzufangen und zu ändern:

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

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_FAILED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      if (!loadRequestData.media.entity) {
        return loadRequestData;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          if (!asset) {
            throw cast.framework.messages.ErrorReason.INVALID_REQUEST;
          }

          loadRequestData.media.contentUrl = asset.url;
          loadRequestData.media.metadata = asset.metadata;
          loadRequestData.media.tracks = asset.tracks;
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

context.start();

Fehlerbehandlung

Wenn im Nachrichten-Interceptor Fehler auftreten, sollte deine Web Receiver-App einen entsprechenden cast.framework.messages.ErrorType und cast.framework.messages.ErrorReason zurückgeben.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      const error = new cast.framework.messages.ErrorData(
                      cast.framework.messages.ErrorType.LOAD_CANCELLED);
      if (!loadRequestData.media) {
        error.reason = cast.framework.messages.ErrorReason.INVALID_PARAM;
        return error;
      }

      ...

      return fetchAssetAndAuth(loadRequestData.media.entity,
                               loadRequestData.credentials)
        .then(asset => {
          ...
          return loadRequestData;
        }).catch(reason => {
          error.reason = reason; // cast.framework.messages.ErrorReason
          return error;
        });
    });

Nachrichtenabfangung im Vergleich zu Event-Listener

Hier sind einige wichtige Unterschiede zwischen dem Abfangen von Nachrichten und dem Event-Listener:

  • Mit einem Event-Listener können Sie die Anfragedaten nicht ändern.
  • Ein Event-Listener eignet sich am besten zum Auslösen von Analysen oder einer benutzerdefinierten Funktion.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • Mit dem Abfangen von Nachrichten können Sie eine Nachricht abhören, abfangen und die Anfragedaten selbst ändern.
  • Das Abfangen von Nachrichten eignet sich am besten für die Verarbeitung benutzerdefinierter Logik in Bezug auf Anfragedaten.

Medien werden geladen

MediaInformation bietet zahlreiche Properties zum Laden von Medien in der cast.framework.messages.MessageType.LOAD-Nachricht, darunter entity, contentUrl und contentId.

  • entity ist die empfohlene Property, die du in deiner Implementierung sowohl für die Sender- als auch für die Empfänger-App verwenden solltest. Die Property ist eine Deeplink-URL, die entweder eine Playlist oder Medieninhalte sein kann. Ihre Anwendung sollte diese URL parsen und mindestens eines der anderen beiden Felder ausfüllen.
  • contentUrl entspricht der abspielbaren URL, die der Player zum Laden des Inhalts verwendet. Diese URL könnte beispielsweise auf ein DASH-Manifest verweisen.
  • Die contentId kann entweder die URL eines abspielbaren Inhalts (ähnlich der URL der contentUrl-Property) oder eine eindeutige Kennung für den Inhalt oder die Playlist sein, die geladen wird. Wenn du diese Property als Kennung verwendest, sollte deine Anwendung eine abspielbare URL in contentUrl angeben.

Es wird empfohlen, entity zum Speichern der echten ID oder der Schlüsselparameter und contentUrl für die URL der Medien zu verwenden. Ein Beispiel dafür sehen Sie im folgenden Snippet, in dem die entity in der LOAD-Anfrage vorhanden ist und die spielbare contentUrl abgerufen wird:

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, loadRequestData => {
      ...

      if (!loadRequestData.media.entity) {
        // Copy the value from contentId for legacy reasons if needed
        loadRequestData.media.entity = loadRequestData.media.contentId;
      }

      return thirdparty.fetchAssetAndAuth(loadRequestData.media.entity,
                                          loadRequestData.credentials)
        .then(asset => {
          loadRequestData.media.contentUrl = asset.url;
          ...
          return loadRequestData;
        });
    });

Gerätefunktionen

Die Methode getDeviceCapabilities liefert Geräteinformationen zum verbundenen Übertragungsgerät und zum daran angeschlossenen Video- oder Audiogerät. Die Methode getDeviceCapabilities liefert Supportinformationen für Google Assistant, Bluetooth sowie das verbundene Display und die Audiogeräte.

Diese Methode gibt ein Objekt zurück, das Sie abfragen können, indem Sie eines der angegebenen Enums übergeben, um die Gerätefunktion für dieses Enum zu erhalten. Die Enums sind in cast.framework.system.DeviceCapabilities definiert.

In diesem Beispiel wird mit den Schlüsseln IS_HDR_SUPPORTED und IS_DV_SUPPORTED geprüft, ob das Webempfängergerät HDR und DolbyVision (DV) wiedergeben kann.

const context = cast.framework.CastReceiverContext.getInstance();
context.addEventListener(cast.framework.system.EventType.READY, () => {
  const deviceCapabilities = context.getDeviceCapabilities();
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_HDR_SUPPORTED] value
  }
  if (deviceCapabilities &&
      deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED]) {
    // Write your own event handling code, for example
    // using the deviceCapabilities[cast.framework.system.DeviceCapabilities.IS_DV_SUPPORTED] value
  }
});
context.start();

Nutzerinteraktionen verarbeiten

Nutzer können über Sender-Apps (Web, Android und iOS), Sprachbefehle auf Geräten mit integriertem Assistant, Touchbedienung auf Smart Displays und Fernbedienungen auf Android TV-Geräten mit deiner Web Receiver-Anwendung interagieren. Das Cast SDK bietet verschiedene APIs, mit denen die Web Receiver-Anwendung diese Interaktionen verarbeiten, die Benutzeroberfläche der Anwendung über Nutzeraktionsstatus aktualisieren und optional die Änderungen senden kann, um Backend-Dienste zu aktualisieren.

Unterstützte Medienbefehle

Die Zustände der UI-Steuerelemente werden durch MediaStatus.supportedMediaCommands für die erweiterten Controller für iOS- und Android-Sender, Empfänger- und Fernbedienungs-Apps auf Touch-Geräten und Empfänger-Apps auf Android TV-Geräten gesteuert. Wenn ein bestimmtes bitweises Command im Attribut aktiviert ist, werden die Schaltflächen aktiviert, die sich auf diese Aktion beziehen. Wenn der Wert nicht festgelegt ist, ist die Schaltfläche deaktiviert. Diese Werte können auf dem Web-Receiver folgendermaßen geändert werden:

  1. PlayerManager.setSupportedMediaCommands verwenden, um die spezifische Commands festzulegen
  2. Neuen Befehl mit addSupportedMediaCommands hinzufügen
  3. Entfernen eines vorhandenen Befehls mit removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Wenn der Empfänger die aktualisierte MediaStatus vorbereitet, werden die Änderungen im Attribut supportedMediaCommands berücksichtigt. Wenn der Status übertragen wird, aktualisieren die verbundenen Sender-Apps die Schaltflächen in ihrer Benutzeroberfläche entsprechend.

Weitere Informationen zu unterstützten Medienbefehlen und Touch-Geräten findest du im Accessing UI controls-Leitfaden.

Status von Nutzeraktionen verwalten

Wenn Nutzer mit der Benutzeroberfläche interagieren oder Sprachbefehle senden, können sie die Wiedergabe der Inhalte und die Eigenschaften des wiedergegebenen Elements steuern. Anfragen, die die Wiedergabe steuern, werden automatisch vom SDK verarbeitet. Anfragen, die Attribute für das aktuell wiedergegebene Element ändern, z. B. ein LIKE-Befehl, müssen von der Empfänger-App verarbeitet werden. Das SDK bietet eine Reihe von APIs, um diese Arten von Anfragen zu verarbeiten. Damit diese Anfragen unterstützt werden, muss Folgendes getan werden:

  • Legen Sie beim Laden einer Mediendatei die MediaInformation-userActionStates mit den Einstellungen eines Nutzers fest.
  • USER_ACTION-Nachrichten abfangen und die angeforderte Aktion bestimmen.
  • Aktualisieren Sie die UserActionState MediaInformation, um die Benutzeroberfläche zu aktualisieren.

Im folgenden Snippet wird die LOAD-Anfrage abgefangen und die MediaInformation von LoadRequestData ausgefüllt. In diesem Fall mag der Nutzer den Inhalt, der geladen wird.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.LOAD, (loadRequestData) => {
      const userActionLike = new cast.framework.messages.UserActionState(
          cast.framework.messages.UserAction.LIKE);
      loadRequestData.media.userActionStates = [userActionLike];

      return loadRequestData;
    });

Das folgende Snippet fängt die USER_ACTION-Nachricht ab und verarbeitet den Aufruf des Back-Ends mit der angeforderten Änderung. Anschließend wird ein Aufruf zum Aktualisieren des UserActionState auf dem Empfänger ausgeführt.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.USER_ACTION,
  (userActionRequestData) => {
    // Obtain the media information of the current content to associate the action to.
    let mediaInfo = playerManager.getMediaInformation();

    // If there is no media info return an error and ignore the request.
    if (!mediaInfo) {
        console.error('Not playing media, user action is not supported');
        return new cast.framework.messages.ErrorData(messages.ErrorType.BAD_REQUEST);
    }

    // Reach out to backend services to store user action modifications. See sample below.
    return sendUserAction(userActionRequestData, mediaInfo)

    // Upon response from the backend, update the client's UserActionState.
    .then(backendResponse => updateUserActionStates(backendResponse))

    // If any errors occurred in the backend return them to the cast receiver.
    .catch((error) => {
      console.error(error);
      return error;
    });
});

Das folgende Snippet simuliert einen Aufruf eines Backend-Dienstes. Die Funktion prüft die UserActionRequestData, um die Art der vom Nutzer angeforderten Änderung zu ermitteln, und führt nur dann einen Netzwerkaufruf durch, wenn die Aktion vom Backend unterstützt wird.

function sendUserAction(userActionRequestData, mediaInfo) {
  return new Promise((resolve, reject) => {
    switch (userActionRequestData.userAction) {
      // Handle user action changes supported by the backend.
      case cast.framework.messages.UserAction.LIKE:
      case cast.framework.messages.UserAction.DISLIKE:
      case cast.framework.messages.UserAction.FOLLOW:
      case cast.framework.messages.UserAction.UNFOLLOW:
      case cast.framework.messages.UserAction.FLAG:
      case cast.framework.messages.UserAction.SKIP_AD:
        let backendResponse = {userActionRequestData: userActionRequestData, mediaInfo: mediaInfo};
        setTimeout(() => {resolve(backendResponse)}, 1000);
        break;
      // Reject all other user action changes.
      default:
        reject(
          new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType.INVALID_REQUEST));
    }
  });
}

Im folgenden Snippet wird der UserActionRequestData verwendet und der UserActionState entweder hinzugefügt oder aus dem MediaInformation entfernt. Wenn Sie den UserActionState des MediaInformation aktualisieren, ändert sich der Status der Schaltfläche, die mit der angeforderten Aktion verknüpft ist. Diese Änderung wird in der Benutzeroberfläche für die Smart Display-Steuerung, in der Fernbedienungs-App und in der Android TV-Benutzeroberfläche angezeigt. Sie wird auch über ausgehende MediaStatus-Nachrichten übertragen, um die Benutzeroberfläche des erweiterten Controllers für iOS- und Android-Sender zu aktualisieren.

function updateUserActionStates(backendResponse) {
  // Unwrap the backend response.
  let mediaInfo = backendResponse.mediaInfo;
  let userActionRequestData = backendResponse.userActionRequestData;

  // If the current item playing has changed, don't update the UserActionState for the current item.
  if (playerManager.getMediaInformation().entity !== mediaInfo.entity) {
    return;
  }

  // Check for existing userActionStates in the MediaInformation.
  // If none, initialize a new array to populate states with.
  let userActionStates = mediaInfo.userActionStates || [];

  // Locate the index of the UserActionState that will be updated in the userActionStates array.
  let index = userActionStates.findIndex((currUserActionState) => {
    return currUserActionState.userAction == userActionRequestData.userAction;
  });

  if (userActionRequestData.clear) {
    // Remove the user action state from the array if cleared.
    if (index >= 0) {
      userActionStates.splice(index, 1);
    }
    else {
      console.warn("Could not find UserActionState to remove in MediaInformation");
    }
  } else {
    // Add the UserActionState to the array if enabled.
    userActionStates.push(
      new cast.framework.messages.UserActionState(userActionRequestData.userAction));
  }

  // Update the UserActionState array and set the new MediaInformation
  mediaInfo.userActionStates = userActionStates;
  playerManager.setMediaInformation(mediaInfo, true);
  return;
}

Sprachbefehle

Die folgenden Medienbefehle werden derzeit im Web Receiver SDK für Geräte mit integriertem Assistant unterstützt. Die Standardimplementierungen dieser Befehle finden Sie in cast.framework.PlayerManager.

Befehl Beschreibung
Spielen Wiedergabe starten oder fortsetzen, wenn sie pausiert ist.
Pausieren Aktuell wiedergegebene Inhalte pausieren
Zurück Zur vorherigen Mediendatei in der Medienwarteschlange springen.
Weiter Zur nächsten Mediendatei in der Medienwarteschlange springen.
Beenden Die Wiedergabe der aktuellen Medien wird beendet.
Keine Wiederholung Deaktiviert die Wiederholung von Mediendateien in der Warteschlange, sobald die letzte Mediendatei in der Warteschlange abgespielt wurde.
Titel wiederholen Die Wiedergabe der aktuellen Medien wird unbegrenzt wiederholt.
Alle wiederholen Alle Elemente in der Warteschlange wiederholen, sobald das letzte Element in der Warteschlange abgespielt wurde.
Alle wiederholen und Zufallsmix Sobald das letzte Element in der Warteschlange abgespielt wurde, wird die Warteschlange gemischt und alle Elemente in der Warteschlange werden wiederholt.
Zufallsmix Mediendateien in der Medienwarteschlange zufällig wiedergeben.
Untertitel ein/aus Untertitel für deine Medien aktivieren/deaktivieren Die Aktivierung/Deaktivierung ist auch nach Sprache möglich.
Springe zu absoluter Zeit Springt zur angegebenen absoluten Zeit.
Spule zu einer Zeit relativ zur aktuellen Zeit vor oder zurück. Springt um den angegebenen Zeitraum relativ zur aktuellen Wiedergabezeit vor oder zurück.
Nochmal spielen Startet die Wiedergabe der aktuell wiedergegebenen Medien neu oder spielt die zuletzt wiedergegebene Mediendatei ab, wenn gerade nichts wiedergegeben wird.
Wiedergabegeschwindigkeit festlegen Wiedergabegeschwindigkeit von Medien ändern Dies sollte standardmäßig erledigt werden. Mit dem Nachrichten-Interceptor SET_PLAYBACK_RATE können Sie eingehende Preisanfragen überschreiben.

Unterstützte Sprachbefehle für Medien

Wenn du verhindern möchtest, dass ein Sprachbefehl einen Medienbefehl auf einem Gerät mit integriertem Assistant auslöst, musst du zuerst die unterstützten Medienbefehle festlegen, die du unterstützen möchtest. Anschließend müssen Sie diese Befehle erzwingen, indem Sie das Attribut CastReceiverOptions.enforceSupportedCommands aktivieren. Die Benutzeroberfläche auf Cast SDK-Sendern und Geräten mit Touchscreen wird entsprechend diesen Konfigurationen geändert. Wenn das Flag nicht aktiviert ist, werden die eingehenden Sprachbefehle ausgeführt.

Wenn du beispielsweise PAUSE von deinen Sender-Apps und Geräten mit Touchbedienung zulässt, musst du auch deinen Empfänger so konfigurieren, dass diese Einstellungen berücksichtigt werden. Wenn diese Option konfiguriert ist, werden alle eingehenden Sprachbefehle verworfen, die nicht in der Liste der unterstützten Befehle enthalten sind.

Im folgenden Beispiel wird die CastReceiverOptions beim Starten der CastReceiverContext angegeben. Wir haben Unterstützung für den Befehl PAUSE hinzugefügt und den Player so konfiguriert, dass er nur diesen Befehl unterstützt. Wenn ein Sprachbefehl einen anderen Vorgang wie SEEK anfordert, wird er abgelehnt. Der Nutzer wird darüber informiert, dass der Befehl noch nicht unterstützt wird.

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

context.start({
  enforceSupportedCommands: true,
  supportedCommands: cast.framework.messages.Command.PAUSE
});

Sie können für jeden Befehl, den Sie einschränken möchten, eine separate Logik anwenden. Entfernen Sie das Flag enforceSupportedCommands und fangen Sie für jeden Befehl, den Sie einschränken möchten, die eingehende Nachricht ab. Hier fangen wir die vom SDK bereitgestellte Anfrage ab, damit SEEK-Befehle, die an Geräte mit integriertem Assistant gesendet werden, keinen Suchvorgang in deiner Web Receiver-Anwendung auslösen.

Gib für Medienbefehle, die deine Anwendung nicht unterstützt, einen entsprechenden Fehlergrund zurück, z. B. NOT_SUPPORTED.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.SEEK,
  seekData => {
    // Block seeking if the SEEK supported media command is disabled
    if (!(playerManager.getSupportedMediaCommands() & cast.framework.messages.Command.SEEK)) {
      let e = new cast.framework.messages.ErrorData(cast.framework.messages.ErrorType
      .INVALID_REQUEST);
      e.reason = cast.framework.messages.ErrorReason.NOT_SUPPORTED;
      return e;
    }

    return seekData;
  });

Hintergrundaktivität durch Sprachaktivität

Wenn die Cast-Plattform den Ton deiner Anwendung aufgrund von Assistant-Aktivitäten wie dem Zuhören oder Antworten in den Hintergrund stellt, wird zu Beginn der Aktivität eine FocusState-Nachricht mit dem Wert NOT_IN_FOCUS an die Web Receiver-Anwendung gesendet. Wenn die Aktivität beendet ist, wird eine weitere Nachricht mit IN_FOCUS gesendet. Je nach Anwendung und wiedergegebenen Medien kann es sinnvoll sein, die Medienwiedergabe zu pausieren, wenn der FocusState NOT_IN_FOCUS ist. Dazu fängst du den Nachrichtentyp FOCUS_STATE ab.

Es ist beispielsweise eine gute Nutzererfahrung, die Wiedergabe eines Hörbuchs zu pausieren, wenn Assistant auf eine Nutzeranfrage antwortet.

playerManager.setMessageInterceptor(cast.framework.messages.MessageType.FOCUS_STATE,
  focusStateRequestData => {
    // Pause content when the app is out of focus. Resume when focus is restored.
    if (focusStateRequestData.state == cast.framework.messages.FocusState.NOT_IN_FOCUS) {
      playerManager.pause();
    } else {
      playerManager.play();
    }

    return focusStateRequestData;
  });

Per Sprachbefehl festgelegte Untertitelsprache

Wenn ein Nutzer die Sprache für die Untertitel nicht explizit angibt, wird die Sprache verwendet, in der der Befehl gesprochen wurde. In diesen Szenarien gibt der Parameter isSuggestedLanguage der eingehenden Nachricht an, ob die zugehörige Sprache vom Nutzer vorgeschlagen oder explizit angefordert wurde.

Beispiel: isSuggestedLanguage wird für den Befehl „Hey Google, schalte die Untertitel ein“ auf true gesetzt, da die Sprache aus der Sprache abgeleitet wurde, in der der Befehl gesprochen wurde. Wenn die Sprache explizit angefordert wird, z. B. „Hey Google, aktiviere englische Untertitel“, wird isSuggestedLanguage auf false gesetzt.

Metadaten und Voice Casting

Sprachbefehle werden standardmäßig vom Web-Receiver verarbeitet. Du solltest jedoch darauf achten, dass die Metadaten für deine Inhalte vollständig und korrekt sind. So wird sichergestellt, dass Sprachbefehle von Assistant richtig verarbeitet werden und die Metadaten auf neuen Arten von Oberflächen wie der Google Home App und Smart Displays wie Google Home Hub richtig angezeigt werden.

Stream-Übertragung

Das Beibehalten des Sitzungsstatus ist die Grundlage für die Stream-Übertragung, bei der Nutzer vorhandene Audio- und Videostreams per Sprachbefehl, über die Google Home App oder über Smart Displays auf andere Geräte übertragen können. Die Medienwiedergabe wird auf einem Gerät (der Quelle) beendet und auf einem anderen Gerät (dem Ziel) fortgesetzt. Jedes Cast-Gerät mit der neuesten Firmware kann als Quelle oder Ziel bei einer Stream-Übertragung dienen.

Der Ereignisablauf für die Stream-Übertragung sieht so aus:

  1. Auf dem Quellgerät:
    1. Die Medienwiedergabe wird beendet.
    2. Die Web-Empfänger-Anwendung erhält einen Befehl zum Speichern des aktuellen Medienstatus.
    3. Die Web-Empfänger-Anwendung wird beendet.
  2. Auf dem Zielgerät:
    1. Die Web-Empfänger-Anwendung wird geladen.
    2. Die Webempfänger-Anwendung empfängt einen Befehl zum Wiederherstellen des gespeicherten Medienstatus.
    3. Die Wiedergabe wird fortgesetzt.

Zu den Elementen des Medienstatus gehören:

  • Bestimmte Position oder Zeitstempel des Songs, Videos oder der Mediendatei.
  • Die Position des Titels in einer größeren Warteschlange (z. B. einer Playlist oder einem Künstler-Radio)
  • Der authentifizierte Nutzer.
  • Wiedergabestatus (z. B. „Wiedergabe“ oder „Pausiert“)

Stream-Übertragung aktivieren

So implementierst du die Stream-Übertragung für deinen Web Receiver:

  1. Aktualisieren Sie supportedMediaCommands mit dem Befehl STREAM_TRANSFER:
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. Optional können Sie die Nachrichten-Interceptors SESSION_STATE und RESUME_SESSION überschreiben, wie unter Sitzungsstatus beibehalten beschrieben. Überschreiben Sie diese nur, wenn benutzerdefinierte Daten als Teil des Sitzungs-Snapshots gespeichert werden müssen. Andernfalls wird die Stream-Übertragung von der Standardimplementierung zum Beibehalten von Sitzungsstatus unterstützt.

Sitzungsstatus beibehalten

Das Web Receiver SDK bietet eine Standardimplementierung für Web Receiver-Apps, um Sitzungsstatus beizubehalten. Dazu wird ein Snapshot des aktuellen Medienstatus erstellt, der Status in eine Ladeanfrage umgewandelt und die Sitzung mit der Ladeanfrage fortgesetzt.

Die vom Webempfänger generierte Ladeanfrage kann bei Bedarf im Nachrichten-Interceptor SESSION_STATE überschrieben werden. Wenn Sie der Ladeanfrage benutzerdefinierte Daten hinzufügen möchten, empfehlen wir, sie in loadRequestData.customData einzufügen.

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.SESSION_STATE,
    function (sessionState) {
        // Override sessionState.loadRequestData if needed.
        const newCredentials = updateCredentials_(sessionState.loadRequestData.credentials);
        sessionState.loadRequestData.credentials = newCredentials;

        // Add custom data if needed.
        sessionState.loadRequestData.customData = {
            'membership': 'PREMIUM'
        };

        return sessionState;
    });

Die benutzerdefinierten Daten können im RESUME_SESSION-Nachrichten-Interceptor aus loadRequestData.customData abgerufen werden.

let cred_ = null;
let membership_ = null;

playerManager.setMessageInterceptor(
    cast.framework.messages.MessageType.RESUME_SESSION,
    function (resumeSessionRequest) {
        let sessionState = resumeSessionRequest.sessionState;

        // Modify sessionState.loadRequestData if needed.
        cred_ = sessionState.loadRequestData.credentials;

        // Retrieve custom data.
        membership_ = sessionState.loadRequestData.customData.membership;

        return resumeSessionRequest;
    });

Vorabladen von Inhalten

Der Web-Empfänger unterstützt das Vorabladen von Mediendateien nach dem aktuellen Wiedergabeelement in der Warteschlange.

Beim Vorabladen werden mehrere Segmente der anstehenden Elemente vorab heruntergeladen. Die Angabe erfolgt über den Wert preloadTime im Objekt QueueItem. Wenn kein Wert angegeben ist, wird standardmäßig 20 Sekunden verwendet. Die Zeit wird in Sekunden relativ zum Ende des aktuell wiedergegebenen Elements angegeben . Nur positive Werte sind gültig. Wenn der Wert beispielsweise 10 Sekunden beträgt, wird dieses Element 10 Sekunden vor dem Ende des vorherigen Elements vorab geladen. Wenn die Zeit bis zum Vorabladen länger ist als die verbleibende Zeit für das aktuelle Element, wird das Vorabladen so schnell wie möglich durchgeführt. Wenn also ein sehr großer Wert für „preload“ für das „queueItem“ angegeben wird, wird das nächste Element bereits vorab geladen, während das aktuelle Element wiedergegeben wird. Wir überlassen die Einstellung und Auswahl jedoch dem Entwickler, da dieser Wert die Bandbreite und die Streaming-Leistung des aktuell wiedergegebenen Elements beeinflussen kann.

Das Vorabladen funktioniert standardmäßig für HLS-, DASH- und Smooth-Streaming-Inhalte.

Normale MP4-Video- und Audiodateien wie MP3 werden nicht vorab geladen, da Cast-Geräte nur ein Medienelement unterstützen und nicht zum Vorabladen verwendet werden können, während ein vorhandenes Inhaltselement noch wiedergegeben wird.

Benutzerdefinierte Nachrichten

Der Nachrichtenaustausch ist die wichtigste Interaktionsmethode für Web-Empfänger-Anwendungen.

Ein Sender sendet Nachrichten an einen Web-Empfänger. Dazu verwendet er die Sender-APIs für die Plattform, auf der der Sender ausgeführt wird (Android, iOS, Web). Das Ereignisobjekt (die Manifestation einer Nachricht), das an die Event-Listener übergeben wird, hat ein Datenelement (event.data), wobei die Daten die Eigenschaften des jeweiligen Ereignistyps annehmen.

Eine Web Receiver-Anwendung kann Nachrichten in einem bestimmten Namespace überwachen. Dadurch unterstützt die Web-Receiver-Anwendung das Namespace-Protokoll. Es liegt dann an den verbundenen Absendern, die in diesem Namespace kommunizieren möchten, das entsprechende Protokoll zu verwenden.

Alle Namespaces werden durch einen String definiert und müssen mit „urn:x-cast:“ beginnen, gefolgt von einem beliebigen String. Beispiel: „urn:x-cast:com.example.cast.mynamespace“.

Hier ist ein Code-Snippet für den Web-Empfänger, um benutzerdefinierte Nachrichten von verbundenen Absendern zu empfangen:

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

const CUSTOM_CHANNEL = 'urn:x-cast:com.example.cast.mynamespace';
context.addCustomMessageListener(CUSTOM_CHANNEL, function(customEvent) {
  // handle customEvent.
});

context.start();

Ebenso können Web Receiver-Anwendungen Sender über den Status des Web Receivers informieren, indem sie Nachrichten an verbundene Sender senden. Eine Web Receiver-Anwendung kann Nachrichten mit sendCustomMessage(namespace, senderId, message) auf CastReceiverContext senden. Ein Web-Empfänger kann Nachrichten an einen einzelnen Absender senden, entweder als Antwort auf eine empfangene Nachricht oder aufgrund einer Änderung des Anwendungsstatus. Neben der Punkt-zu-Punkt-Nachrichtenübermittlung (mit einem Limit von 64 KB) kann ein Web-Empfänger auch Nachrichten an alle verbundenen Absender senden.

Cast für Audiogeräte

Informationen zur reinen Audiowiedergabe findest du im Leitfaden zu Google Cast für Audiogeräte.

Android TV

In diesem Abschnitt wird erläutert, wie der Google Web Receiver Ihre Eingaben für die Wiedergabe verwendet und wie die Kompatibilität mit Android TV funktioniert.

Anwendung in die Fernbedienung einbinden

Der Google Web Receiver, der auf dem Android TV-Gerät ausgeführt wird, übersetzt die Eingaben von den Steuereingängen des Geräts (z.B. Handfernbedienung) in Nachrichten zur Medienwiedergabe, die für den Namespace urn:x-cast:com.google.cast.media definiert sind, wie unter Nachrichten zur Medienwiedergabe beschrieben. Ihre Anwendung muss diese Nachrichten unterstützen, um die Medienwiedergabe der Anwendung zu steuern und eine grundlegende Wiedergabesteuerung über die Steuereingaben von Android TV zu ermöglichen.

Richtlinien für die Android TV-Kompatibilität

Hier sind einige Empfehlungen und häufige Fehler, die du vermeiden solltest, damit deine App mit Android TV kompatibel ist:

  • Beachte, dass der User-Agent-String sowohl „Android“ als auch „CrKey“ enthält. Einige Websites leiten möglicherweise zu einer mobilen Website weiter, weil sie das Label „Android“ erkennen. Gehe nicht davon aus, dass „Android“ im User-Agent-String immer auf einen mobilen Nutzer hinweist.
  • Der Medien-Stack von Android verwendet möglicherweise transparentes GZIP zum Abrufen von Daten. Achten Sie darauf, dass Ihre Mediendaten auf Accept-Encoding: gzip reagieren können.
  • Android TV-HTML5-Medienereignisse werden möglicherweise zu anderen Zeiten als Chromecast-Ereignisse ausgelöst. Dadurch können Probleme sichtbar werden, die auf Chromecast nicht aufgetreten sind.
  • Verwenden Sie beim Aktualisieren der Medien medienbezogene Ereignisse, die von <audio>/<video>-Elementen ausgelöst werden, z. B. timeupdate, pause und waiting. Vermeiden Sie netzwerkbezogene Ereignisse wie progress, suspend und stalled, da diese in der Regel plattformabhängig sind. Weitere Informationen zum Umgang mit Medienereignissen im Empfänger findest du unter Medienereignisse.
  • Achten Sie beim Konfigurieren der HTTPS-Zertifikate Ihrer Empfängerwebsite darauf, Zwischenzertifikate der Zertifizierungsstelle einzuschließen. Auf der Qualsys-SSL-Testseite können Sie prüfen, ob der vertrauenswürdige Zertifizierungspfad für Ihre Website ein CA-Zertifikat mit der Bezeichnung „Extra Download“ enthält. In diesem Fall wird es möglicherweise nicht auf Android-basierten Plattformen geladen.
  • Während Chromecast die Empfängerseite auf einer 720p-Grafikebene anzeigt, können andere Cast-Plattformen, einschließlich Android TV, die Seite mit bis zu 1080p anzeigen. Achte darauf, dass deine Empfängerseite bei verschiedenen Auflösungen korrekt skaliert wird.