Créer un récepteur Cast de base

googlecastnew500.png

Dans cet atelier de programmation, vous allez apprendre à créer une application réceptrice compatible Cast afin de lire du contenu sur un appareil Google Cast.

Qu'est-ce que Google Cast ?

Google Cast permet aux utilisateurs de caster des contenus depuis un appareil mobile sur un téléviseur. Ils peuvent ensuite se servir de leur appareil mobile ou du navigateur Chrome de leur ordinateur de bureau comme d'une télécommande pour contrôler la lecture sur le téléviseur.

Le SDK Google Cast vous permet d'utiliser votre application afin de contrôler des appareils compatibles Google Cast (un téléviseur ou un système audio, par exemple). Le SDK Cast met à votre disposition les composants d'interface utilisateur nécessaires, en fonction de la checklist de conception de Google Cast.

Cette checklist a été conçue pour garantir une expérience utilisateur simple et prévisible sur toutes les plates-formes compatibles. En savoir plus

Qu'allons-nous créer ?

À la fin de cet atelier de programmation, vous disposerez d'une application HTML5 servant de récepteur personnalisé, capable d'afficher du contenu vidéo sur des appareils compatibles Cast.

Points abordés

  • Comment préparer le développement du récepteur.
  • Principes de base d'un récepteur compatible Cast basé sur le framework d'application Cast.
  • Comment recevoir une vidéo castée.
  • Comment intégrer Debug Logger.
  • Comment optimiser votre récepteur pour les écrans connectés.

Prérequis

  • La dernière version du navigateur Google Chrome.
  • node.js, npm, le module http-server et ngrok.
  • Un appareil Google Cast, comme Chromecast ou Android TV, configuré pour accéder à Internet.
  • Un téléviseur ou un moniteur dotés d'une entrée HDMI.

Expérience

  • Vous devez avoir une connaissance préalable du développement Web.
  • Vous devez également avoir une expérience préalable en tant que téléspectateur. :)

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

Comment évalueriez-vous votre expérience de création d'applications Web ?

Débutant Intermédiaire Expert

Comment évalueriez-vous votre niveau en tant que téléspectateur ?

Débutant Intermédiaire Expert

Vous pouvez télécharger l'intégralité de l'exemple de code sur votre ordinateur…

Télécharger la source

et décompresser ensuite le fichier ZIP téléchargé.

Pour utiliser votre récepteur avec un appareil Cast, vous devez l'héberger à un emplacement auquel cet appareil a accès. Si vous disposez déjà d'un serveur compatible avec HTTPS, ignorez les instructions suivantes et prenez note de l'URL, car vous en aurez besoin dans la section suivante.

Si vous ne disposez pas d'un serveur, ne vous inquiétez pas. Vous pourrez installer node.js, le module de nœud http-server et ngrok.

npm install -g http-server
npm install -g ngrok

Exécuter le serveur

Si vous utilisez http-server, accédez à votre console et procédez comme suit :

cd app-start
http-server

Vous devriez voir un code semblable à celui-ci :

Starting up http-server, serving ./
Available on:
  http://127.0.0.1:8080
  http://172.19.17.192:8080
Hit CTRL-C to stop the server

Notez le port local utilisé et procédez comme suit dans un nouveau terminal pour exposer votre récepteur local via HTTPS à l'aide de ngrok :

ngrok http 8080

Cette commande va configurer un tunnel ngrok vers votre serveur HTTP local et vous attribuer un point de terminaison sécurisé par HTTPS disponible dans le monde entier que vous pourrez utiliser à l'étape suivante (https://116ec943.eu.ngrok.io) :

ngrok by @inconshreveable                                                                                                                                                                                                                                     (Ctrl+C to quit)

Session Status         online
Version                2.2.4
Web Interface          http://127.0.0.1:8080
Forwarding             http://116ec943.eu.ngrok.io -> localhost:8080
Forwarding             https://116ec943.eu.ngrok.io -> localhost:8080

ngrok et http-server doivent rester actifs pendant toute la durée de l'atelier de programmation. Toutes les modifications apportées en local seront instantanément appliquées.

Vous devez enregistrer votre application pour pouvoir exécuter un récepteur personnalisé, tel qu'il est intégré dans cet atelier de programmation, sur des appareils Chromecast. Une fois votre application enregistrée, vous recevez un ID application que votre application émettrice doit utiliser pour effectuer des appels d'API (pour lancer une application réceptrice, par exemple).

d8b39f5d33d33db4.png

Cliquez sur "Add new application" (Ajouter une application).

e8c19e57b85c7d.png

Sélectionnez "Custom Receiver" (Récepteur personnalisé), c'est-à-dire ce que nous sommes en train de créer.

bf364a7d382e3c58.png

Saisissez les informations sur votre nouveau récepteur. Assurez-vous d'utiliser l'URL que vous avez obtenue

à la dernière section. Prenez note de l'ID application attribué à votre nouveau récepteur.

Vous devez également enregistrer votre appareil Google Cast pour qu'il puisse accéder à votre application réceptrice avant sa publication. Une fois votre application réceptrice publiée, elle est accessible à tous les appareils Google Cast. Pour les besoins de cet atelier de programmation, il est conseillé d'utiliser une application réceptrice non publiée.

a446325da6ebd627.png

Cliquez sur "Add new Device" (Ajouter un nouvel appareil).

a21355793a3f4cd5.png

Saisissez le numéro de série indiqué au dos de votre appareil Cast et attribuez un nom descriptif à l'appareil. Pour connaître le numéro de série, vous pouvez également caster votre écran dans Chrome lorsque vous accédez à la console développeur du SDK Google Cast.

Veuillez patienter entre 5 et 15 minutes pour que le récepteur et l'appareil soient prêts à être testés. Une fois cette période écoulée, vous devez redémarrer votre appareil Cast.

Google_Chrome_logo_icon.png

En attendant que notre nouvelle application réceptrice soit prête à être testée, voyons à quoi ressemble un exemple d'application réceptrice terminée. Le récepteur que nous allons créer sera capable de lire des contenus multimédias à l'aide de la technique de streaming à débit adaptatif. Nous utiliserons un exemple de contenu encodé pour le streaming adaptatif dynamique sur HTTP (DASH).

Dans votre navigateur, ouvrez l'outil Command and Control (CaC).

7dbd91a75140c46f.png

  1. Vous devriez normalement accéder à notre outil CaC.
  2. Utilisez l'ID d'exemple de récepteur "CC1AD845" par défaut, puis cliquez sur le bouton "Set App ID" (Définir l'ID application).
  3. Cliquez sur l'icône Cast en haut à gauche, puis sélectionnez votre appareil Google Cast.

a02db8244a963fd6.png

  1. Accédez à l'onglet "Load Media" (Charger le contenu multimédia) dans la partie supérieure de la page.

acd63df355a0493.png

  1. Cliquez sur le bouton "Load by Content" (Charger par contenu) pour lire un échantillon vidéo.
  2. La lecture de la vidéo démarre sur votre appareil Google Cast pour vous donner un aperçu de la fonctionnalité réceptrice de base lorsque le récepteur par défaut est utilisé.

Notre objectif est de rendre l'application de départ que vous avez téléchargée compatible avec Google Cast. Voici quelques termes liés à Google Cast que nous utiliserons dans cet atelier de programmation :

  • Une application émettrice s'exécute sur un appareil mobile ou un ordinateur portable.
  • Une application réceptrice s'exécute sur l'appareil Google Cast.

Vous êtes maintenant prêt à développer votre projet de départ à l'aide de votre éditeur de texte favori :

  1. Sélectionnez le répertoire android_studio_folder.pngapp-start à partir de l'exemple de code téléchargé.
  2. Ouvrez js/receiver.js et index.html.

Notez que, tout au long de cet atelier de programmation, http-server devrait appliquer les modifications que vous apportez. Si ce n'est pas le cas, essayez de fermer, puis de redémarrer http-server.

Conception de l'application

L'application réceptrice initialise la session Cast et reste en attente jusqu'à la réception d'une requête LOAD (c'est-à-dire la commande de lecture d'un contenu multimédia) en provenance de l'émetteur.

L'application se compose d'une vue principale, définie dans index.html, et d'un fichier JavaScript nommé js/receiver.js, contenant toute la logique nécessaire au bon fonctionnement du récepteur.

index.html

Ce fichier HTML contient l'interface utilisateur de notre application réceptrice. Pour l'instant, il est vide. Nous le compléterons au cours de l'atelier de programmation.

receiver.js

Ce script gère toute la logique de notre application réceptrice. Actuellement, il s'agit simplement d'un fichier vide. Cependant, dans la section suivante, nous le transformerons en un récepteur Cast entièrement fonctionnel avec seulement quelques lignes de code.

Un récepteur Cast de base initialise la session Cast au démarrage. Cela s'avère nécessaire pour indiquer à toutes les applications émettrices connectées que l'ouverture du récepteur a réussi. En outre, le nouveau SDK est préconfiguré pour gérer directement les contenus en streaming à débit adaptatif (à l'aide de DASH, HLS et Smooth Streaming), ainsi que les fichiers MP4 ordinaires. Faisons un essai !

Initialisation

Ajoutez le code suivant à index.html dans l'en-tête :

<head>
  ...

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

Ajoutez le code suivant à index.html <body> avant le <footer> qui charge receiver.js, afin de fournir au SDK du récepteur l'espace nécessaire pour afficher l'interface utilisateur par défaut du récepteur qui est envoyée avec le script que vous venez d'ajouter.

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

Nous devons maintenant initialiser le SDK dans js/receiver.js. Cela implique les opérations suivantes :

  • Acquisition d'une référence à CastReceiverContext, votre point d'entrée principal vers l'intégralité du SDK Récepteur
  • Stockage d'une référence à PlayerManager, l'objet qui gère la lecture et vous fournit tous les hooks dont vous avez besoin pour connecter votre logique personnalisée
  • Initialisation du SDK en appelant start() sur CastReceiverContext.

Ajoutez le code suivant à js/receiver.js.

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

context.start();

Pour les besoins de cet atelier de programmation, utilisez l'outil CaC pour tester votre nouveau récepteur.

Ouvrez votre navigateur Web pour accéder à l'outil Command and Control (CAC).

72039b93a476e35e.png

Veillez à indiquer dans le champ votre propre ID application, tel que vous l'avez enregistré précédemment, puis à cliquer sur "Set App ID" (Définir l'ID application). Vous indiquez ainsi à l'outil d'utiliser votre récepteur au démarrage de la session Cast.

Caster du contenu multimédia

En règle générale, pour lire du contenu multimédia sur un appareil Cast, la procédure est la suivante :

  1. L'émetteur crée un objet MediaInfo JSON à partir du SDK Cast qui modélise un élément multimédia.
  2. L'émetteur se connecte à l'appareil Cast pour lancer l'application réceptrice.
  3. Le récepteur charge l'objet MediaInfo via une requête LOAD pour lire le contenu.
  4. Le récepteur surveille l'état du contenu multimédia et en effectue le suivi.
  5. L'émetteur envoie des commandes de lecture au récepteur pour contrôler la lecture en fonction des interactions de l'utilisateur avec l'application émettrice.

Au cours de cette première tentative, nous allons renseigner dans MediaInfo une URL d'élément lisible (stockée dans MediaInfo.contentUrl).

Dans des conditions réelles, l'émetteur utilise un identifiant multimédia spécifique à une application dans MediaInfo.contentId. Le récepteur utilise contentId comme identifiant pour effectuer les appels d'API backend appropriés afin de résoudre l'URL réelle de l'élément et de la définir sur MediaInfo.contentUrl. Il gère également des tâches telles que l'acquisition de licences DRM ou l'injection d'informations sur les coupures publicitaires.

Nous allons étendre les fonctionnalités du récepteur pour exécuter une opération semblable à celle de la section suivante. Pour le moment, cliquez sur l'icône Cast et sélectionnez votre appareil pour ouvrir le récepteur.

4954e949c3d3b232.png

Accédez à l'onglet "Load Media (Charger le contenu multimédia), puis cliquez sur le bouton "Load by Content" (Charger par contenu). Votre récepteur doit démarrer la lecture de l'échantillon de contenu.

ccd8cc258d0c1522.png

Par défaut, le SDK Récepteur gère les opérations suivantes :

  • Initialiser la session Cast
  • Gérer les requêtes LOAD entrantes en provenance d'émetteurs contenant des éléments lisibles
  • Fournir une interface utilisateur de base, prête à être affichée sur grand écran

N'hésitez pas à explorer l'outil CaC et son code avant de passer à la section suivante. Nous allons étendre les fonctionnalités de notre récepteur pour qu'il communique avec un exemple d'API simple afin de traiter les requêtes LOAD entrantes en provenance des émetteurs.

Conformément à la façon dont la plupart des développeurs interagissent avec leurs récepteurs Cast dans des applications réelles, nous allons modifier notre récepteur pour qu'il gère les requêtes LOAD qui font référence au contenu multimédia prévu en fonction de sa clé API plutôt qu'en envoyant une URL d'élément lisible.

Les applications procèdent généralement de la sorte pour les raisons suivantes :

  • Il se peut que l'émetteur ne connaisse pas l'URL de contenu.
  • L'application Cast est conçue pour gérer l'authentification, une autre logique métier ou les appels d'API directement sur le récepteur.

Cette fonctionnalité est principalement implémentée dans la méthode setMessageInterceptor() PlayerManager. Cela vous permet d'intercepter les messages entrants par type et de les modifier avant qu'ils n'atteignent le gestionnaire de messages interne du SDK. Dans cette section, nous allons traiter les requêtes LOAD en procédant comme suit :

  • Lire la requête LOAD entrante et son contentId personnalisé.
  • Effectuer un appel GET vers notre API pour rechercher l'élément pouvant être diffusé en streaming à l'aide de son contentId.
  • Modifier la requête LOAD avec l'URL du flux.
  • Modifier l'objet MediaInformation pour définir les paramètres de type de flux.
  • Transmettre la requête au SDK pour lecture ou refuser la commande si la recherche du contenu multimédia demandé s'avère impossible.

L'exemple d'API fourni présente les hooks du SDK permettant de personnaliser les tâches courantes du récepteur, tout en s'appuyant sur une expérience essentiellement prédéfinie.

Exemple d'API

Saisissez l'adresse https://storage.googleapis.com/cpe-sample-media/content.json dans le navigateur et consultez notre catalogue d'échantillons vidéo. Le contenu comprend des URL d'images poster au format png, ainsi que des flux DASH et HLS. Les flux DASH et HLS pointent vers des sources audio et vidéo démultiplexées stockées dans des conteneurs mp4 fragmentés.

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

  [...]

}

À l'étape suivante, nous allons associer la clé de chaque entrée (par exemple, bbb, fbb_ad) à l'URL du flux une fois que le récepteur aura été appelé avec une requête LOAD.

Intercepter la requête LOAD

Au cours de cette étape, nous allons créer un intercepteur de chargement (LOAD) avec une fonction qui envoie une requête XHR au fichier JSON hébergé. Une fois le fichier JSON obtenu, nous allons analyser le contenu et définir les métadonnées. Dans les sections suivantes, nous allons personnaliser les paramètres MediaInformation pour spécifier le type de contenu.

Ajoutez le code suivant à votre fichier js/receiver.js, juste avant l'appel vers 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);
          }
        });
      });
    });

La section suivante explique comment configurer la propriété media de la requête de chargement pour le contenu DASH.

Utiliser le contenu DASH de l'exemple d'API

Maintenant que nous avons préparé l'intercepteur de chargement, nous allons indiquer le type de contenu au récepteur. Le récepteur disposera ainsi de l'URL de playlist principale et du type MIME du flux. Ajoutez le code suivant au fichier js/receiver.js dans le Promise() de l'intercepteur LOAD :

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

Une fois cette étape terminée, vous pourrez effectuer un test de chargement avec du contenu DASH. Si vous préférez tester le chargement avec du contenu HLS, passez à l'étape suivante.

Utiliser le contenu HLS de l'exemple d'API

L'exemple d'API comprend à la fois du contenu HLS et DASH. Outre la définition de la propriété contentType, comme nous l'avons fait à l'étape précédente, la requête de chargement nécessite des propriétés supplémentaires pour pouvoir utiliser les URL HLS de l'exemple d'API. Lorsque le récepteur est configuré pour la lecture de flux HLS, le type de conteneur attendu par défaut est TS (flux de transport). Par conséquent, le récepteur tente d'ouvrir les exemples de flux MP4 au format TS si seule la propriété contentUrl est modifiée. Dans la requête de chargement, l'objet MediaInformation doit être modifié avec les propriétés supplémentaires pour que le récepteur sache que le contenu est de type MP4 et non TS. Ajoutez le code suivant à votre fichier js/receiver.js dans l'intercepteur de chargement pour modifier les propriétés contentUrl et contentType. Ajoutez également les propriétés HlsSegmentFormat et HlsVideoSegmentFormat.

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

Test

Ouvrez à nouveau l'outil Command and Control (CaC) et définissez votre ID application sur celui de votre récepteur. Sélectionnez votre appareil à l'aide de l'icône Cast.

Accédez à l'onglet "Load Media" (Charger le contenu multimédia). Cette fois, supprimez le contenu du champ "Content URL" (URL de contenu) à côté du bouton "Load by Content" (Charger par contenu), ce qui force l'application à envoyer une requête LOAD ne contenant que la référence contentId à notre contenu multimédia.

3e830710c562189f.png

En supposant que tout fonctionne correctement avec les modifications que vous avez apportées au récepteur, l'intercepteur doit transformer l'objet MediaInfo en un élément que le SDK peut lire à l'écran.

Cliquez sur le bouton "Load by Content" (Charger par contenu) pour vérifier si votre contenu multimédia est lu correctement. N'hésitez pas à remplacer le Content ID par un autre ID dans le fichier content.json.

Les écrans connectés sont des appareils dotés de fonctionnalités tactiles qui permettent aux applications réceptrices de prendre en charge les commandes tactiles.

Cette section explique comment optimiser votre application réceptrice lorsqu'elle est lancée sur un écran connecté. Vous y apprendrez également comment personnaliser les commandes du lecteur.

Accéder aux commandes d'interface utilisateur

L'objet Commandes d'interface utilisateur pour les écrans connectés est accessible à l'aide de cast.framework.ui.Controls.GetInstance(). Ajoutez le code suivant à votre fichier js/receiver.js au-dessus de context.start() :

...

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

context.start();

Si vous n'utilisez pas l'élément <cast-media-player>, vous devez définir touchScreenOptimizedApp dans CastReceiverOptions. Il est utilisé dans cet atelier de programmation.

context.start({ touchScreenOptimizedApp: true });

Des boutons de commande par défaut sont attribués à chaque emplacement en fonction de MetadataType et MediaStatus.supportedMediaCommands.

Commandes vidéo

Pour MetadataType.MOVIE, MetadataType.TV_SHOW et MetadataType.GENERIC, l'objet Commandes d'interface utilisateur pour les écrans connectés est affiché comme dans l'exemple ci-dessous.

5f5a3d567813cf10.png

  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

Commandes audio

Pour MetadataType.MUSIC_TRACK, l'objet Commandes d'interface utilisateur pour les écrans connectés est affiché comme suit :

e93d4557f324e8c0.png

  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

Mettre à jour les commandes multimédias compatibles

L'objet Commandes d'interface utilisateur détermine également si un ControlsButton est affiché ou non en fonction de MediaStatus.supportedMediaCommands.

Lorsque la valeur de supportedMediaCommands est égale à ALL_BASIC_MEDIA, la disposition des commandes par défaut se présente comme suit :

5b97ada8d239239c.png

Lorsque la valeur de supportedMediaCommands est égale à ALL_BASIC_MEDIA | QUEUE_PREV | QUEUE_NEXT, la disposition des commandes par défaut se présente comme suit :

2d8267d4d8b68e87.png

Lorsque la valeur de supportedMediaCommands est égale à PAUSE | QUEUE_PREV | QUEUE_NEXT, la disposition des commandes par défaut se présente comme suit :

39c9afe44c4fa8dc.png

Lorsque des pistes de texte sont disponibles, le bouton des sous-titres (CC) s'affiche toujours au niveau de SLOT_1.

771952ab29e2eb21.png

Pour modifier de manière dynamique la valeur de supportedMediaCommands après le démarrage d'un contexte de récepteur, vous pouvez appeler PlayerManager.setSupportedMediaCommands afin d'ignorer la valeur. Vous pouvez également ajouter ou supprimer une commande en utilisant, respectivement, addSupportedMediaCommands ou removeSupportedMediaCommands.

Personnaliser les boutons de commande

Vous pouvez personnaliser les commandes en utilisant PlayerDataBinder. Ajoutez le code suivant sous touchControls dans votre fichier js/receiver.js pour définir le premier emplacement des commandes :

...

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

Media Browse est une fonctionnalité CAF Receiver qui permet aux utilisateurs d'explorer des contenus supplémentaires sur des appareils tactiles. Pour implémenter cette fonctionnalité, vous allez utiliser PlayerDataBinder afin de définir l'interface utilisateur BrowseContent. Vous pouvez ensuite y insérer BrowseItems en fonction du contenu que vous souhaitez afficher.

BrowseContent

Vous trouverez ci-dessous un exemple de l'interface utilisateur BrowseContent et de ses propriétés :

e40623e1907d983a.png

  1. BrowseContent.title
  2. BrowseContent.items

Format

Utilisez targetAspectRatio property pour sélectionner le meilleur format pour vos éléments image. Le SDK Récepteur CAF accepte trois formats : SQUARE_1_TO_1, PORTRAIT_2_TO_3 et LANDSCAPE_16_TO_9.

BrowseItem

Utilisez BrowseItem pour afficher le titre, le sous-titre, la durée et l'image de chaque élément :

838a0db6c9224710.png

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

Définir les données de Media Browse

Vous pouvez fournir une liste de contenus multimédias à explorer en appelant setBrowseContent. Ajoutez le code suivant à votre fichier js/receiver.js, sous playerDataBinder, et dans votre écouteur d'événements MEDIA_CHANGED pour définir les éléments de navigation avec le titre "Up Next".

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

Si vous cliquez sur un élément Media Browse, l'intercepteur LOAD est déclenché. Ajoutez le code suivant à votre intercepteur LOAD pour associer request.media.contentId à request.media.entity à partir de l'élément Media Browse :

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

Vous pouvez également définir l'objet BrowseContent sur null pour supprimer l'interface utilisateur de Media Browse.

Le SDK Récepteur Cast propose une autre option pour permettre aux développeurs de déboguer facilement les applications réceptrices en utilisant l'API CastDebugLogger et un outil Command and Control (CaC) associé pour récupérer les journaux.

Initialisation

Pour intégrer l'API, ajoutez le script source CastDebugLogger dans votre fichier index.html. La source doit être déclarée dans la balise <head> après la déclaration du SDK Récepteur Cast.

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

Dans la partie supérieure du fichier js/receiver.js, sous playerManager, ajoutez le code suivant pour récupérer l'instance CastDebugLogger et activer l'enregistreur :

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.
castDebugLogger.setEnabled(true);

Lorsque l'enregistreur de débogage est activé, DEBUG MODE s'affiche en incrustation sur le récepteur.

d9cb99e7742fc240.png

Événements de lecteur de journal

CastDebugLogger vous permet d'enregistrer facilement des événements de lecteur qui sont déclenchés par le SDK Récepteur CAF et d'utiliser différents niveaux d'enregistreur pour consigner les données d'événement. La configuration loggerLevelByEvents utilise cast.framework.events.EventType et cast.framework.events.category pour indiquer les événements qui seront enregistrés.

Ajoutez le code suivant sous la déclaration castDebugLogger pour enregistrer le déclenchement d'un événement CORE du lecteur ou la diffusion d'une modification mediaStatus :

// Debug Logger
const castDebugLogger = cast.debug.CastDebugLogger.getInstance();

// Enable debug logger and show a 'DEBUG MODE' overlay at top left corner.
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
}

Messages de journal et balises personnalisées

L'API CastDebugLogger vous permet de créer des messages de journal qui sont affichés dans différentes couleurs sur le calque de débogage du récepteur. Les méthodes d'enregistrement suivantes sont disponibles. Elles sont classées par ordre décroissant de priorité :

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

Pour chaque méthode d'enregistrement, le premier paramètre est une balise personnalisée. Il peut s'agir de n'importe quelle chaîne d'identification que vous jugez pertinente. CastDebugLogger utilise des balises pour filtrer les journaux. L'utilisation de balises est décrite en détail ci-dessous. Le deuxième paramètre est le message de journal.

Pour voir les journaux en action, ajoutez-les à votre intercepteur LOAD.

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

Vous pouvez déterminer les messages affichés sur le calque de débogage en définissant le niveau de journalisation dans loggerLevelByTags pour chaque balise personnalisée. Par exemple, l'activation d'une balise personnalisée avec le niveau de journalisation cast.framework.LoggerLevel.DEBUG affiche tous les messages ajoutés comportant une erreur, un avertissement, des informations et des messages de débogage. L'activation d'une balise personnalisée avec le niveau WARNING n'affiche que les messages de journal d'erreur et d'avertissement.

La configuration de loggerLevelByTags est facultative. Si aucune balise personnalisée n'est configurée avec le niveau d'enregistreur, tous les messages de journal s'affichent sur le calque de débogage.

Ajoutez le code suivant sous l'enregistreur d'événements CORE :

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

Calque de débogage

L'enregistreur de débogage Cast propose un calque de débogage sur le récepteur pour afficher vos messages de journal personnalisés sur l'appareil Cast. Utilisez showDebugLogs pour activer/désactiver le calque de débogage et clearDebugLogs pour effacer les messages de journal sur le calque.

Ajoutez le code suivant pour afficher un aperçu du calque de débogage sur votre récepteur.

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

356c6ac94318539c.png

Vous êtes maintenant en mesure de créer une application réceptrice personnalisée à l'aide de la dernière version du SDK Récepteur Cast. Vous trouverez d'autres exemples d'applications sur GitHub à l'adresse github.com/googlecast.