Créer un récepteur Web personnalisé

1. Présentation

Logo Google Cast

Dans cet atelier de programmation, vous allez apprendre à créer une application Web Receiver personnalisée pour lire du contenu sur des appareils compatibles 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. Les utilisateurs peuvent ensuite utiliser leur appareil mobile ou le navigateur Chrome de leur ordinateur comme télécommande pour lire les contenus multimédias sur leur téléviseur.

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

La checklist de conception de Google Cast 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 qui agira en tant que récepteur personnalisé, capable d'afficher du contenu vidéo sur les appareils compatibles Cast.

Points abordés

  • Configurer le développement du récepteur
  • Principes de base d'un récepteur compatible Cast basé sur le framework d'application Cast
  • Recevoir une vidéo castée
  • Intégrer Debug Enregistreur
  • Optimiser votre récepteur pour les écrans connectés

Ce dont vous avez besoin

Expérience

  • Vous devez disposer de connaissances préalables en 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 expérience en tant que téléspectateur ?

Débutant Intermédiaire Expert

2. Obtenir l'exemple de code

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

puis décompresser le fichier ZIP téléchargé.

3. Déployer votre récepteur en local

Pour que vous puissiez utiliser votre récepteur Web avec un appareil Cast, celui-ci doit être hébergé dans un endroit où l'appareil Cast est accessible. Si vous disposez déjà d'un serveur compatible avec HTTPS, ignorez les instructions ci-dessous et notez l'URL, car vous en aurez besoin dans la section suivante.

Si vous ne disposez d'aucun serveur, vous pouvez utiliser Firebase Hosting ou ngrok.

Exécuter le serveur

Une fois le service de votre choix configuré, accédez à app-start et démarrez votre serveur.

Notez l'URL de votre récepteur hébergé. Vous l'utiliserez dans la section suivante.

4. Enregistrer une application dans la console de développement Cast

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 identifiant d'application que votre application émettrice doit utiliser pour effectuer des appels d'API, par exemple pour lancer une application réceptrice.

Image de la console pour les développeurs du SDK Google Cast, avec le bouton "Ajouter une application" en surbrillance

Cliquez sur "Ajouter une application".

Image de l'écran "New receiver Application" (Nouvelle application de récepteur) avec l'option "Custom receiver" (Récepteur personnalisé) encadrée

Sélectionnez "Récepteur personnalisé". C'est ce que nous sommes en train de créer.

Image de l'écran "Nouveau récepteur personnalisé" montrant une URL que quelqu'un saisit dans le champ "URL de l'application du destinataire"

Saisissez les informations de votre nouveau récepteur, en veillant à utiliser l'URL que vous avez obtenue

dans la dernière section. Notez l'ID application attribué à votre tout nouveau récepteur.

Vous devez également enregistrer votre appareil Google Cast afin qu'il puisse accéder à votre application réceptrice avant de le publier. Une fois publiée, votre application réceptrice sera disponible pour tous les appareils Google Cast. Pour les besoins de cet atelier de programmation, il est recommandé d'utiliser une application réceptrice non publiée.

Image de la console pour les développeurs du SDK Google Cast avec le bouton "Ajouter un appareil" en surbrillance

Cliquez sur "Ajouter un appareil".

Image de la boîte de dialogue "Ajouter un récepteur de cast"

Saisissez le numéro de série indiqué au dos de votre appareil Cast et attribuez-lui un nom descriptif. Vous pouvez également trouver le numéro de série en castant votre écran dans Chrome lorsque vous accédez à la console pour développeur du SDK Google Cast.

Il peut s'écouler entre 5 et 15 minutes avant que le récepteur et l'appareil ne soient prêts à être testés. Après 5 à 15 minutes d'attente, vous devez redémarrer l'appareil Cast.

5. Exécuter l'application exemple

Logo Google Chrome

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 d'un 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).

Image de l'onglet "Cast Connect & Logs Controls" (Commandes de connexion et du journal de diffusion) de l'outil Command and Control (CaC)

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

Image de l'onglet "Cast Connect & logs Controls" de l'outil Command and Control (CaC) indiquant qu'il est connecté à une application réceptrice

  1. Accédez à l'onglet "Charger le contenu multimédia" en haut de l'écran.

Image de l'onglet "Load Media" (Charger le contenu multimédia) de l'outil Command and Control (CaC)

  1. Cliquez sur le bouton "Charger par contenu" pour lire un exemple de vidéo.
  2. La lecture de la vidéo démarre sur votre appareil Google Cast pour vous montrer à quoi ressemble la fonctionnalité de base du récepteur lorsque vous utilisez le récepteur par défaut.

6. Préparer le projet de départ

Nous 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 appli de type émetteur s'exécute sur un appareil mobile ou un ordinateur portable.
  • Une appli de type récepteur s'exécute sur l'appareil Google Cast.

Vous êtes maintenant prêt à développer le projet de démarrage à l'aide de votre éditeur de texte préféré:

  1. Sélectionnez le répertoire Icône Dossierapp-start dans le téléchargement de l'exemple de code.
  2. Ouvrez js/receiver.js et index.html.

Notez que tout au long de cet atelier de programmation, http-server devrait récupérer 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 veille jusqu'à ce que l'émetteur reçoive une requête LOAD (en d'autres termes, la commande de lecture d'un contenu multimédia).

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

index.html

Ce fichier HTML contiendra l'interface utilisateur de notre application réceptrice. Pour le moment, il est vide. Nous le compléterons tout au long de l'atelier de programmation.

receiver.js

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

7. Un récepteur Cast de base

Un récepteur Cast de base initialise la session Cast au démarrage. Cela est nécessaire pour indiquer à toutes les applications émettrices connectées que l'affichage du destinataire a réussi. En outre, le nouveau SDK est préconfiguré pour gérer les contenus multimédias diffusés en streaming à débit adaptatif (à l'aide de DASH, HLS et Smooth Streaming) et des fichiers MP4 bruts prêts à l'emploi. Essayons ceci.

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 chargement receiver.js, de <footer> afin de fournir au SDK du récepteur l'espace nécessaire pour afficher l'UI du récepteur par défaut, 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, composé des éléments suivants:

  • l'acquisition d'une référence à CastReceiverContext, votre point d'entrée principal vers l'ensemble du SDK Récepteur
  • stocker une référence à PlayerManager, l'objet qui gère la lecture et vous fournit tous les hooks dont vous avez besoin pour brancher votre propre logique personnalisée ;
  • l'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();

8. Caster du contenu vidéo de base

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

Dans votre navigateur Web, accédez à l'outil Command and Control (CaC).

Image de l&#39;onglet &quot;Cast Connect & Logs Controls&quot; (Commandes de connexion et du journal de diffusion) de l&#39;outil Command and Control (CaC)

Veillez à remplacer l'ID d'application que vous avez enregistré précédemment dans le champ, puis cliquez sur "Définir l'ID d'application". Vous indiquez ainsi à l'outil d'utiliser votre récepteur lorsqu'il démarre la session de diffusion.

Caster un contenu multimédia

De manière générale, pour lire un contenu multimédia sur un appareil Cast, procédez comme suit:

  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 et suit l'état du contenu multimédia.
  5. L'émetteur envoie des commandes de lecture au destinataire pour contrôler la lecture en fonction des interactions de l'utilisateur avec l'application émettrice.

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

Dans le monde réel, l'expéditeur utilise un identifiant multimédia spécifique à l'application dans MediaInfo.contentId. Le destinataire 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 votre récepteur pour qu'il effectue une opération similaire dans la section suivante. Pour l'instant, cliquez sur l'icône Cast, puis sélectionnez votre appareil pour ouvrir le récepteur.

Image de l&#39;onglet &quot;Cast Connect & logs Controls&quot; de l&#39;outil Command and Control (CaC) indiquant qu&#39;il est connecté à une application réceptrice

Accédez à l'onglet"Load Media " (Charger le contenu multimédia), puis cliquez sur le bouton "Load by Content" (Charger par contenu). Le récepteur doit commencer à lire l'échantillon de contenu.

Image de l&#39;onglet &quot;Load Media&quot; (Charger le contenu multimédia) de l&#39;outil Command and Control (CaC)

Dès la première utilisation, le SDK Récepteur gère les éléments suivants:

  • Initialiser la session Cast
  • Gérer les requêtes LOAD entrantes des expéditeurs contenant des éléments lisibles
  • Fournissez 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, dans laquelle nous allons étendre notre récepteur pour communiquer avec un exemple d'API simple afin de traiter les requêtes LOAD entrantes des expéditeurs.

9. Intégrer une API externe

Conformément à la manière 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 traite les requêtes LOAD qui font référence au contenu multimédia prévu par sa clé API au lieu d'envoyer l'URL d'un élément lisible.

En général, les applications procèdent de cette manière pour les raisons suivantes:

  • L'expéditeur ne connaît peut-être pas l'URL du 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 traitons les requêtes LOAD avec les opérations suivantes:

  • Lire la requête LOAD entrante et sa contentId personnalisée
  • Envoyez un appel GET à notre API pour rechercher l'élément pouvant être diffusé en streaming à l'aide de son contentId.
  • Remplacez la requête LOAD par l'URL du flux.
  • Modifiez l'objet MediaInformation pour définir les paramètres de type de flux.
  • Transmettez la requête au SDK pour la lecture, ou refusez la commande si nous ne parvenons pas à rechercher le contenu multimédia demandé.

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 principalement prête à l'emploi.

Exemple d'API

Dans votre navigateur, accédez à l'adresse https://storage.googleapis.com/cpe-sample-media/content.json et accédez à notre exemple de catalogue vidéo. Le contenu inclut 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émuxé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 mapper la clé de chaque entrée (par exemple, bbb, fbb_ad) à l'URL du flux une fois que le récepteur a été appelé avec une requête LOAD.

Intercepter la requête LOAD

Au cours de cette étape, nous allons créer un intercepteur de charge avec une fonction qui envoie une requête XHR au fichier JSON hébergé. Une fois le fichier JSON obtenu, nous analyserons le contenu et définirons 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 de 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 charge, nous allons spécifier le type de contenu au récepteur. Le récepteur dispose ainsi de l'URL de la 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 pouvez passer à la phase de test pour essayer de charger du contenu DASH. Si vous souhaitez tester le chargement avec du contenu HLS, passez à l'étape suivante.

Utiliser le contenu HLS de l'exemple d'API

L'exemple d'API inclut du contenu HLS ainsi que DASH. En plus de définir le paramètre contentType comme nous l'avons fait à l'étape précédente, vous devez ajouter des propriétés supplémentaires à la requête de chargement pour pouvoir utiliser les URL HLS de l'exemple d'API. Lorsque le récepteur est configuré pour lire des flux HLS, le type de conteneur par défaut attendu est le 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 des propriétés supplémentaires afin que le destinataire sache que le contenu est de type MP4 et non TS. Ajoutez le code suivant à votre fichier js/receiver.js dans l'intercepteur de charge 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 l'ID d'application sur celui du destinataire. Sélectionnez votre appareil à l'aide de l'icône Cast.

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

Image de l&#39;onglet &quot;Load Media&quot; (Charger le contenu multimédia) de l&#39;outil Command and Control (CaC)

En supposant que tout fonctionne correctement avec les modifications que vous avez apportées au récepteur, l'intercepteur doit s'occuper de mettre en forme 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 que le contenu multimédia est bien lu. N'hésitez pas à remplacer Content ID par un autre ID dans le fichier content.json.

10. Optimiser votre application pour les écrans connectés

Les écrans connectés sont des appareils dotés d'une fonctionnalité tactile 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 des écrans connectés et comment personnaliser les commandes du lecteur.

Accéder aux commandes d'interface utilisateur

Vous pouvez accéder à l'objet Commandes d'interface utilisateur pour les écrans connectés à 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. Dans cet atelier de programmation, nous utilisons l'élément <cast-media-player>.

context.start({ touchScreenOptimizedApp: true });

Des boutons de commande par défaut sont attribués à chaque emplacement en fonction de MetadataType et de 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 s'affichera comme dans l'exemple ci-dessous.

Image d&#39;une vidéo en cours de lecture, avec les commandes de l&#39;interface utilisateur superposées

  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 s'affiche comme suit:

Image d&#39;une musique en cours de lecture, avec commandes d&#39;interface utilisateur superposées

  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 élément 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:

Image des commandes du lecteur multimédia: barre de progression, bouton de lecture, boutons &quot;Avancer&quot; et &quot;Précédent&quot; activés

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:

Image des commandes du lecteur multimédia: barre de progression, bouton &quot;Lecture&quot;, boutons &quot;Avancer&quot; et &quot;Précédent&quot; activés, et boutons &quot;File d&#39;attente précédent&quot; et &quot;Dans la file d&#39;attente suivant&quot; activés

Lorsque la valeur de "supportedMediaCommands" est égale à PAUSE | QUEUE_PREV | QUEUE_NEXT, la disposition des commandes par défaut s'affiche comme suit:

Image des commandes du lecteur multimédia: barre de progression, bouton &quot;Lecture&quot;, et boutons &quot;File d&#39;attente précédent&quot; et &quot;Dans la file d&#39;attente suivant&quot; activés

Lorsque des pistes de texte sont disponibles, le bouton de sous-titres est toujours affiché sur SLOT_1.

Image des commandes du lecteur multimédia: barre de progression, bouton &quot;Lecture&quot;, boutons &quot;Avancer&quot; et &quot;Précédent&quot;, boutons &quot;File d&#39;attente précédent&quot; et &quot;Dans la file d&#39;attente suivant&quot;, et boutons &quot;Sous-titres&quot; activés

Pour modifier de façon dynamique la valeur de supportedMediaCommands après avoir démarré un contexte de récepteur, vous pouvez appeler PlayerManager.setSupportedMediaCommands afin de remplacer la valeur. Vous pouvez également ajouter une commande en utilisant addSupportedMediaCommands ou supprimer une commande existante en utilisant removeSupportedMediaCommands.

Personnaliser les boutons de commande

Vous pouvez personnaliser les commandes à l'aide de PlayerDataBinder. Ajoutez le code suivant à votre fichier js/receiver.js sous touchControls pour définir le premier emplacement de vos 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();

11. Implémenter Media Browse sur les écrans connectés

Media Browse est une fonctionnalité CAF Receiver qui permet aux utilisateurs d'explorer des contenus supplémentaires sur des appareils tactiles. Pour implémenter cela, vous allez utiliser PlayerDataBinder afin de définir l'interface utilisateur de 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:

Image de l&#39;interface utilisateur &quot;BrowseContent&quot; montrant deux miniatures de vidéos et une partie d&#39;une troisième vidéo

  1. BrowseContent.title
  2. BrowseContent.items

Format

Utilisez le targetAspectRatio property pour sélectionner le meilleur format pour vos composants Image. Le SDK Récepteur CAF prend en charge 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:

Image de l&#39;interface utilisateur &quot;BrowseContent&quot; montrant deux miniatures de vidéos et une partie d&#39;une troisième vidéo

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

Configurer les données de Media Browse

Vous pouvez fournir une liste de contenus multimédias à parcourir 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 "À suivre".

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

Cliquer sur un élément de navigation multimédia déclenche l'intercepteur LOAD. Ajoutez le code suivant à votre intercepteur LOAD pour mapper 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'UI Media Browse.

12. Déboguer les applications réceptrices

Le SDK du récepteur de cast offre aux développeurs une autre option pour déboguer facilement les applications réceptrices en utilisant l'API CastDebugLogger et un outil Command and Control (CaC) associé pour capturer 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 js/receiver.js, en haut du fichier et 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.
context.addEventListener(cast.framework.system.EventType.READY, () => {
  if (!castDebugLogger.debugOverlayElement_) {
      castDebugLogger.setEnabled(true);
  }
});

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

Image d&#39;une vidéo en cours de lecture avec le message &quot;MODE DÉBOGAGE&quot; sur fond rouge dans l&#39;angle supérieur gauche de l&#39;image

Événements du lecteur de journaux

CastDebugLogger vous permet de consigner facilement les événements du lecteur déclenchés par le SDK CAF Receiver et d'utiliser différents niveaux d'enregistreur pour consigner les données des événements. La configuration loggerLevelByEvents utilise cast.framework.events.EventType et cast.framework.events.category pour spécifier les événements à consigner.

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

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

Messages de journal et balises personnalisées

L'API CastDebugLogger vous permet de créer des messages de journal qui apparaissent dans différentes couleurs dans la superposition de débogage du récepteur. Les méthodes de journalisation suivantes sont disponibles, classées de la priorité la plus haute à la plus basse:

  • 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 qui vous semble pertinente. CastDebugLogger utilise des balises pour filtrer les journaux. L'utilisation des balises est expliquée 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 contrôler les messages à afficher dans 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 avec des messages d'erreur, d'avertissement, d'information et 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 pour son niveau d'enregistreur, tous les messages de journal s'affichent dans la superposition 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,
};

Débogage en superposition

Le journal de débogage Cast fournit une superposition 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 prévisualiser le calque de débogage sur votre récepteur.

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

Image montrant la superposition de débogage, une liste de messages de journal de débogage sur un arrière-plan translucide au-dessus d&#39;une image vidéo

13. Félicitations !

Vous savez maintenant créer une application de type "récepteur Web" personnalisée à l'aide du SDK Cast Web Receiver.

Pour en savoir plus, consultez le guide du développeur Web Receiver.