Ajouter des fonctionnalités de base à votre récepteur Web personnalisé

Cette page contient des extraits de code et des descriptions des fonctionnalités disponibles pour une application de récepteur Web personnalisé.

  1. Un élément cast-media-player qui représente l'interface utilisateur du lecteur intégré fournie avec le récepteur Web.
  2. Style personnalisé de type CSS pour l'élément cast-media-player afin de styliser divers éléments d'interface utilisateur tels que background-image, splash-image et font-family.
  3. Un élément de script pour charger le framework du récepteur Web.
  4. Code JavaScript pour intercepter les messages et gérer les événements.
  5. File d'attente pour la lecture automatique.
  6. Options de configuration de la lecture.
  7. Options permettant de définir le contexte du récepteur Web.
  8. Options permettant de définir les commandes compatibles avec l'application réceptrice Web.
  9. Un appel JavaScript pour démarrer l'application réceptrice Web.

Configuration et options de l'application

Configurer l'application

CastReceiverContext est la classe la plus externe exposée au développeur. Elle gère le chargement des bibliothèques sous-jacentes et l'initialisation du SDK du récepteur Web. Le SDK fournit des API qui permettent aux développeurs d'applications de configurer le SDK via CastReceiverOptions. Ces configurations sont évaluées une fois par lancement d'application et sont transmises au SDK lors de la définition du paramètre facultatif dans l'appel à start.

L'exemple ci-dessous montre comment remplacer le comportement par défaut pour détecter si une connexion d'expéditeur est toujours active. Lorsque le récepteur Web n'a pas pu communiquer avec un émetteur pendant maxInactivity secondes, un événement SENDER_DISCONNECTED est envoyé. La configuration ci-dessous remplace ce délai avant expiration. Cela peut être utile lors du débogage des problèmes, car cela empêche l'application réceptrice Web de fermer la session Bureau à distance Chrome lorsqu'il n'y a aucun émetteur connecté à l'état IDLE.

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

Configurer le lecteur

Lors du chargement du contenu, le SDK Web Receiver permet de configurer des variables de lecture telles que les informations DRM, les configurations de nouvelle tentative et les gestionnaires de requêtes à l'aide de cast.framework.PlaybackConfig. Ces informations sont gérées par PlayerManager et sont évaluées au moment de la création des joueurs. Les lecteurs sont créés chaque fois qu'une nouvelle charge est transmise au SDK Web Receiver. Les modifications apportées à PlaybackConfig après la création du lecteur sont évaluées lors du chargement de contenu suivant. Le SDK fournit les méthodes suivantes pour modifier le PlaybackConfig.

  • CastReceiverOptions.playbackConfig pour remplacer les options de configuration par défaut lors de l'initialisation de CastReceiverContext.
  • PlayerManager.getPlaybackConfig() pour obtenir la configuration actuelle.
  • PlayerManager.setPlaybackConfig() pour remplacer la configuration actuelle. Ce paramètre est appliqué à tous les chargements ultérieurs ou jusqu'à ce qu'il soit à nouveau remplacé.
  • PlayerManager.setMediaPlaybackInfoHandler() pour appliquer des configurations supplémentaires uniquement à l'élément multimédia en cours de chargement, en plus des configurations actuelles. Le gestionnaire est appelé juste avant la création du lecteur. Les modifications apportées ici ne sont pas permanentes et ne sont pas incluses dans les requêtes adressées à getPlaybackConfig(). Lorsque l'élément multimédia suivant est chargé, ce gestionnaire est de nouveau appelé.

L'exemple ci-dessous montre comment définir PlaybackConfig lors de l'initialisation de CastReceiverContext. La configuration remplace les requêtes sortantes pour l'obtention des fichiers manifestes. Le gestionnaire spécifie que les requêtes CORS Access-Control doivent être effectuées à l'aide d'identifiants tels que des cookies ou des en-têtes d'autorisation.

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

L'exemple ci-dessous montre comment remplacer PlaybackConfig à l'aide du getter et du setter fournis dans PlayerManager. Ce paramètre configure le lecteur pour qu'il reprenne la lecture du contenu après le chargement d'un segment.

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

L'exemple ci-dessous montre comment remplacer PlaybackConfig pour une requête de chargement spécifique à l'aide du gestionnaire d'informations de lecture multimédia. Le gestionnaire appelle une méthode getLicenseUrlForMedia implémentée par l'application pour obtenir l'élément licenseUrl à partir de l'élément contentId de l'élément actuel.

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

  return playbackConfig;
});

Écouteur d'événements

Le SDK du récepteur Web permet à votre application de récepteur Web de gérer les événements du lecteur. L'écouteur d'événements accepte un paramètre cast.framework.events.EventType (ou un tableau de ces paramètres) qui spécifie les événements qui doivent déclencher l'écouteur. Les tableaux préconfigurés de cast.framework.events.EventType utiles pour le débogage se trouvent dans cast.framework.events.category. Le paramètre d'événement fournit des informations supplémentaires sur l'événement.

Par exemple, si vous souhaitez savoir quand une modification mediaStatus est diffusée, vous pouvez utiliser la logique suivante pour gérer l'événement :

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

Interception de messages

Le SDK du récepteur Web permet à votre application de récepteur Web d'intercepter les messages et d'exécuter du code personnalisé sur ces messages. L'intercepteur de messages utilise un paramètre cast.framework.messages.MessageType qui spécifie le type de message à intercepter.

L'intercepteur doit renvoyer la requête modifiée ou une promesse qui se résout avec la valeur de la requête modifiée. Le renvoi de null empêchera l'appel du gestionnaire de messages par défaut. Pour en savoir plus, consultez Charger des contenus multimédias.

Par exemple, si vous souhaitez modifier les données de la requête de chargement, vous pouvez utiliser la logique suivante pour les intercepter et les modifier :

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

Gestion des exceptions

Lorsque des erreurs se produisent dans l'intercepteur de messages, votre application de récepteur Web doit renvoyer les éléments cast.framework.messages.ErrorType et cast.framework.messages.ErrorReason appropriés.

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

Interception de messages et écouteur d'événements

Voici quelques-unes des principales différences entre l'interception de messages et l'écouteur d'événements :

  • Un écouteur d'événements ne vous permet pas de modifier les données de la requête.
  • Un écouteur d'événements est idéal pour déclencher des analyses ou une fonction personnalisée.
playerManager.addEventListener(cast.framework.events.category.CORE,
    event => {
        console.log(event);
    });
  • L'interception de messages vous permet d'écouter un message, de l'intercepter et de modifier les données de la requête elles-mêmes.
  • L'interception de messages est particulièrement utile pour gérer une logique personnalisée concernant les données de requête.

Chargement de contenu multimédia

MediaInformation fournit de nombreuses propriétés pour charger des contenus multimédias dans le message cast.framework.messages.MessageType.LOAD, y compris entity, contentUrl et contentId.

  • entity est la propriété suggérée à utiliser dans votre implémentation pour vos applications émettrice et réceptrice. La propriété est une URL de lien profond qui peut être une playlist ou un contenu multimédia. Votre application doit analyser cette URL et renseigner au moins l'un des deux autres champs.
  • contentUrl correspond à l'URL de lecture que le lecteur utilisera pour charger le contenu. Par exemple, cette URL peut pointer vers un fichier manifeste DASH.
  • contentId peut être l'URL d'un contenu lisible (semblable à celle de la propriété contentUrl) ou un identifiant unique pour le contenu ou la playlist en cours de chargement. Si vous utilisez cette propriété comme identifiant, votre application doit renseigner une URL lisible dans contentUrl.

Nous vous suggérons d'utiliser entity pour stocker l'ID réel ou les paramètres de clé, et contentUrl pour l'URL du contenu multimédia. L'extrait suivant montre un exemple où entity est présent dans la requête LOAD et où l'élément contentUrl lisible est récupéré :

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

Fonctionnalités de l'appareil

La méthode getDeviceCapabilities fournit des informations sur l'appareil Cast connecté et l'appareil vidéo ou audio qui lui est associé. La méthode getDeviceCapabilities fournit des informations d'assistance pour l'Assistant Google, le Bluetooth, ainsi que les appareils audio et les écrans connectés.

Cette méthode renvoie un objet que vous pouvez interroger en transmettant l'un des énumérations spécifiées pour obtenir la capacité de l'appareil pour cette énumération. Les énumérations sont définies dans cast.framework.system.DeviceCapabilities.

Cet exemple vérifie si l'appareil récepteur Web est capable de lire du contenu HDR et DolbyVision (DV) avec les clés IS_HDR_SUPPORTED et IS_DV_SUPPORTED, respectivement.

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

Gérer les interactions des utilisateurs

Un utilisateur peut interagir avec votre application Web Receiver via des applications émettrices (Web, Android et iOS), des commandes vocales sur les appareils avec Assistant Google intégré, des commandes tactiles sur les écrans connectés et des télécommandes sur les appareils Android TV. Le SDK Cast fournit différentes API permettant à l'application Web Receiver de gérer ces interactions, de mettre à jour l'interface utilisateur de l'application via les états d'action de l'utilisateur et, éventuellement, d'envoyer les modifications pour mettre à jour les services de backend.

Commandes multimédias compatibles

Les états des commandes de l'interface utilisateur sont déterminés par MediaStatus.supportedMediaCommands pour les contrôleurs étendus de l'émetteur iOS et Android, les applications de récepteur et de télécommande exécutées sur les appareils tactiles, et les applications de récepteur sur les appareils Android TV. Lorsqu'un Command au niveau du bit particulier est activé dans la propriété, les boutons associés à cette action sont activés. Si la valeur n'est pas définie, le bouton est désactivé. Ces valeurs peuvent être modifiées sur le récepteur Web de la manière suivante :

  1. Utiliser PlayerManager.setSupportedMediaCommands pour définir le Commands spécifique
  2. Ajouter une commande à l'aide de addSupportedMediaCommands
  3. Supprimer une commande existante à l'aide de removeSupportedMediaCommands.
playerManager.setSupportedMediaCommands(cast.framework.messages.Command.SEEK |
  cast.framework.messages.Command.PAUSE);

Lorsque le récepteur prépare le MediaStatus mis à jour, il inclut les modifications dans la propriété supportedMediaCommands. Lorsque l'état est diffusé, les applications émettrices connectées mettent à jour les boutons de leur UI en conséquence.

Pour en savoir plus sur les commandes multimédias et les appareils tactiles compatibles, consultez le guide Accessing UI controls.

Gérer les états des actions utilisateur

Lorsque les utilisateurs interagissent avec l'UI ou envoient des commandes vocales, ils peuvent contrôler la lecture du contenu et les propriétés liées à l'élément en cours de lecture. Les requêtes qui contrôlent la lecture sont gérées automatiquement par le SDK. Les requêtes qui modifient les propriétés de l'élément en cours de lecture, telles qu'une commande LIKE, doivent être gérées par l'application réceptrice. Le SDK fournit une série d'API pour gérer ces types de requêtes. Pour prendre en charge ces requêtes, vous devez effectuer les opérations suivantes :

  • Définissez l'élément MediaInformation userActionStates avec les préférences d'un utilisateur lors du chargement d'un élément multimédia.
  • Intercepter les messages USER_ACTION et déterminer l'action demandée.
  • Mettez à jour MediaInformation UserActionState pour mettre à jour l'UI.

L'extrait de code suivant intercepte la requête LOAD et renseigne le MediaInformation de LoadRequestData. Dans ce cas, l'utilisateur aime le contenu en cours de chargement.

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

L'extrait de code suivant intercepte le message USER_ACTION et gère l'appel du backend avec la modification demandée. Il appelle ensuite la méthode pour mettre à jour UserActionState sur le récepteur.

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

L'extrait de code suivant simule un appel à un service de backend. La fonction vérifie l'UserActionRequestData pour voir le type de modification demandé par l'utilisateur et n'effectue un appel réseau que si l'action est compatible avec le backend.

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

L'extrait de code suivant prend l'UserActionRequestData et ajoute ou supprime l'UserActionState de l'MediaInformation. La mise à jour de l'élément UserActionState de MediaInformation modifie l'état du bouton associé à l'action demandée. Cette modification est répercutée dans l'UI des commandes de l'écran connecté, l'application de télécommande et l'UI d'Android TV. Il est également diffusé via des messages MediaStatus sortants pour mettre à jour l'interface utilisateur de la télécommande agrandie pour les expéditeurs iOS et Android.

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

Commandes vocales

Les commandes multimédias suivantes sont actuellement compatibles avec le SDK Web Receiver pour les appareils avec Assistant Google intégré. Les implémentations par défaut de ces commandes se trouvent dans cast.framework.PlayerManager.

Commande Description
Lire Lancer ou reprendre la lecture à partir de l'état de pause.
Pause Mettre en pause le contenu en cours de lecture.
Précédent Passer à l'élément multimédia précédent dans votre file d'attente multimédia.
Suivant Passez à l'élément multimédia suivant dans votre file d'attente multimédia.
Arrêter Arrêtez la lecture du contenu multimédia en cours.
Repeat None Désactivez la répétition des éléments multimédias dans la file d'attente une fois que le dernier élément de la file d'attente a été lu.
Répéter un titre Répéter indéfiniment le contenu multimédia en cours de lecture.
Tout lire en boucle Répéter tous les éléments de la file d'attente une fois que le dernier élément de la file d'attente a été lu.
Tout répéter et lecture aléatoire Une fois la lecture du dernier élément de la file d'attente terminée, lisez la file d'attente de manière aléatoire et répétez tous les éléments qu'elle contient.
Brassage Lit les éléments multimédias de votre file d'attente multimédia de manière aléatoire.
Sous-titres activés/désactivés Activez ou désactivez les sous-titres pour vos contenus multimédias. L'activation/la désactivation est également disponible par langue.
Accéder à une heure absolue Accède à l'heure absolue spécifiée.
Rechercher une heure relative par rapport à l'heure actuelle Avance ou recule de la durée spécifiée par rapport à la position de lecture actuelle.
Rejouer Relancez la lecture du contenu multimédia en cours ou lisez le dernier élément multimédia lu si rien n'est en cours de lecture.
Définir la vitesse de lecture Modifier la vitesse de lecture des contenus multimédias. Cette opération doit être gérée par défaut. Vous pouvez utiliser l'intercepteur de messages SET_PLAYBACK_RATE pour remplacer les requêtes de taux entrantes.

Commandes multimédias vocales compatibles

Pour empêcher une commande vocale de déclencher une commande multimédia sur un appareil compatible avec l'Assistant, vous devez d'abord définir les commandes multimédias que vous prévoyez de prendre en charge. Vous devez ensuite appliquer ces commandes en activant la propriété CastReceiverOptions.enforceSupportedCommands. L'interface utilisateur des émetteurs du SDK Cast et des appareils tactiles sera modifiée pour refléter ces configurations. Si l'option n'est pas activée, les commandes vocales entrantes seront exécutées.

Par exemple, si vous autorisez PAUSE depuis vos applications émettrices et vos appareils tactiles, vous devez également configurer votre récepteur pour qu'il reflète ces paramètres. Une fois configurées, toutes les commandes vocales entrantes seront ignorées si elles ne figurent pas dans la liste des commandes compatibles.

Dans l'exemple ci-dessous, nous fournissons le CastReceiverOptions lors du démarrage de CastReceiverContext. Nous avons ajouté la compatibilité avec la commande PAUSE et forcé le lecteur à n'accepter que cette commande. Désormais, si une commande vocale demande une autre opération, telle que SEEK, elle sera refusée. L'utilisateur sera informé que la commande n'est pas encore prise en charge.

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

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

Vous pouvez appliquer une logique distincte pour chaque commande que vous souhaitez limiter. Supprimez l'option enforceSupportedCommands et, pour chaque commande que vous souhaitez restreindre, vous pouvez intercepter le message entrant. Ici, nous interceptons la requête fournie par le SDK afin que les commandes SEEK émises sur les appareils avec Assistant Google intégré ne déclenchent pas de recherche dans votre application Web Receiver.

Pour les commandes multimédias que votre application ne prend pas en charge, renvoyez un motif d'erreur approprié, tel que 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;
  });

Mise en arrière-plan à partir de l'activité vocale

Si la plate-forme Cast met en arrière-plan le son de votre application en raison d'une activité de l'Assistant, par exemple l'écoute de la voix de l'utilisateur ou la réponse, un message FocusState de NOT_IN_FOCUS est envoyé à l'application Web Receiver au début de l'activité. Un autre message avec IN_FOCUS est envoyé lorsque l'activité se termine. Selon votre application et le contenu multimédia en cours de lecture, vous pouvez mettre en pause le contenu multimédia lorsque le FocusState est NOT_IN_FOCUS en interceptant le type de message FOCUS_STATE.

Par exemple, il est préférable de mettre en pause la lecture d'un livre audio si l'Assistant répond à une requête de l'utilisateur.

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

Langue des sous-titres spécifiée par la voix

Lorsqu'un utilisateur n'indique pas explicitement la langue des sous-titres, la langue utilisée pour les sous-titres est la même que celle dans laquelle la commande a été prononcée. Dans ces scénarios, le paramètre isSuggestedLanguage du message entrant indique si la langue associée a été suggérée ou explicitement demandée par l'utilisateur.

Par exemple, isSuggestedLanguage est défini sur true pour la commande "OK Google, active les sous-titres", car la langue a été déduite de la langue dans laquelle la commande a été prononcée. Si la langue est explicitement demandée, par exemple dans "Ok Google, active les sous-titres en anglais", isSuggestedLanguage est défini sur false.

Métadonnées et casting vocal

Bien que les commandes vocales soient gérées par défaut par le récepteur Web, vous devez vous assurer que les métadonnées de votre contenu sont complètes et exactes. Cela permet de s'assurer que les commandes vocales sont correctement gérées par l'Assistant et que les métadonnées s'affichent correctement sur les nouveaux types d'interfaces, comme l'application Google Home et les écrans connectés tels que Google Home Hub.

Transfert de diffusion

La préservation de l'état de la session est à la base du transfert de diffusion, qui permet aux utilisateurs de déplacer des flux audio et vidéo existants d'un appareil à l'autre à l'aide de commandes vocales, de l'application Google Home ou d'écrans connectés. La lecture du contenu multimédia s'arrête sur un appareil (la source) et se poursuit sur un autre (la destination). Tout appareil Cast équipé du dernier micrologiciel peut servir de source ou de destination dans un transfert de diffusion.

Le flux d'événements pour le transfert de diffusion est le suivant :

  1. Sur l'appareil source :
    1. La lecture du contenu multimédia s'arrête.
    2. L'application réceptrice Web reçoit une commande pour enregistrer l'état actuel du contenu multimédia.
    3. L'application réceptrice Web est arrêtée.
  2. Sur l'appareil de destination :
    1. L'application Web Receiver est chargée.
    2. L'application réceptrice Web reçoit une commande pour restaurer l'état du contenu multimédia enregistré.
    3. La lecture du contenu multimédia reprend.

Les éléments de l'état du contenu multimédia sont les suivants :

  • Position ou code temporel spécifique du titre, de la vidéo ou de l'élément multimédia.
  • Sa place dans une file d'attente plus large (comme une playlist ou une radio d'artiste)
  • L'utilisateur authentifié.
  • État de la lecture (par exemple, en cours de lecture ou en pause).

Activer le transfert de diffusion

Pour implémenter le transfert de diffusion pour votre récepteur Web :

  1. Mettez à jour supportedMediaCommands à l'aide de la commande STREAM_TRANSFER :
    playerManager.addSupportedMediaCommands(
    cast.framework.messages.Command.STREAM_TRANSFER, true);
  2. Vous pouvez éventuellement remplacer les intercepteurs de messages SESSION_STATE et RESUME_SESSION, comme décrit dans Conserver l'état de la session. Ne les remplacez que si des données personnalisées doivent être stockées dans l'instantané de session. Sinon, l'implémentation par défaut pour conserver les états de session sera compatible avec le transfert de diffusion.

Conserver l'état de la session

Le SDK Web Receiver fournit une implémentation par défaut pour les applications Web Receiver afin de préserver les états de session en prenant un instantané de l'état actuel du contenu multimédia, en convertissant l'état en requête de chargement et en reprenant la session avec la requête de chargement.

La requête de chargement générée par le récepteur Web peut être remplacée dans l'intercepteur de messages SESSION_STATE si nécessaire. Si vous souhaitez ajouter des données personnalisées à la demande de chargement, nous vous suggérons de les placer dans loadRequestData.customData.

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

Les données personnalisées peuvent être récupérées à partir de loadRequestData.customData dans l'intercepteur de messages RESUME_SESSION.

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

Préchargement du contenu

Le récepteur Web accepte le préchargement des éléments multimédias après l'élément en cours de lecture dans la file d'attente.

L'opération de préchargement télécharge à l'avance plusieurs segments des éléments à venir. La spécification est effectuée sur la valeur preloadTime de l'objet QueueItem (par défaut, 20 secondes si elle n'est pas fournie). La durée est exprimée en secondes, par rapport à la fin de l'élément en cours de lecture . Seules les valeurs positives sont valides. Par exemple, si la valeur est de 10 secondes, cet élément sera préchargé 10 secondes avant la fin de l'élément précédent. Si le délai de préchargement est supérieur au temps restant sur l'élément actuel, le préchargement se produit dès que possible. Par conséquent, si une valeur de préchargement très élevée est spécifiée sur queueItem, nous pouvons obtenir l'effet suivant : chaque fois que nous lisons l'élément actuel, nous préchargeons déjà l'élément suivant. Toutefois, nous laissons le développeur définir et choisir cette valeur, car elle peut affecter la bande passante et les performances de streaming de l'élément en cours de lecture.

Le préchargement fonctionne par défaut pour les contenus en streaming HLS, DASH et Smooth.

Les fichiers vidéo MP4 et audio standards tels que MP3 ne seront pas préchargés, car les appareils Cast ne sont compatibles qu'avec un seul élément multimédia et ne peuvent pas être utilisés pour le préchargement pendant la lecture d'un élément de contenu existant.

Messages personnalisés

L'échange de messages est la principale méthode d'interaction pour les applications de récepteur Web.

Un émetteur envoie des messages à un récepteur Web à l'aide des API d'émetteur de la plate-forme sur laquelle il s'exécute (Android, iOS, Web). L'objet d'événement (qui est la manifestation d'un message) transmis aux écouteurs d'événements comporte un élément de données (event.data) dans lequel les données prennent les propriétés du type d'événement spécifique.

Une application réceptrice Web peut choisir d'écouter les messages sur un espace de noms spécifié. De ce fait, l'application réceptrice Web est considérée comme compatible avec ce protocole d'espace de noms. Il appartient ensuite à tous les émetteurs connectés souhaitant communiquer sur cet espace de noms d'utiliser le protocole approprié.

Tous les espaces de noms sont définis par une chaîne et doivent commencer par "urn:x-cast:" suivi d'une chaîne. (par exemple, "urn:x-cast:com.example.cast.mynamespace").

Voici un extrait de code permettant au récepteur Web d'écouter les messages personnalisés des expéditeurs connectés :

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

De même, les applications de récepteur Web peuvent tenir les expéditeurs informés de l'état du récepteur Web en envoyant des messages aux expéditeurs connectés. Une application de récepteur Web peut envoyer des messages à l'aide de sendCustomMessage(namespace, senderId, message) sur CastReceiverContext. Un récepteur Web peut envoyer des messages à un expéditeur individuel, soit en réponse à un message reçu, soit en raison d'un changement d'état de l'application. Au-delà de la messagerie point à point (avec une limite de 64 ko), un récepteur Web peut également diffuser des messages à tous les émetteurs connectés.

Appareils Cast pour l'audio

Consultez le guide Google Cast pour les appareils audio pour obtenir de l'aide sur la lecture audio uniquement.

Android TV

Cette section explique comment le récepteur Web Google utilise vos entrées pour la lecture et la compatibilité avec Android TV.

Intégrer votre application à la télécommande

Le récepteur Web Google exécuté sur l'appareil Android TV traduit les entrées des commandes de l'appareil (par exemple, la télécommande) en messages de lecture multimédia définis pour l'espace de noms urn:x-cast:com.google.cast.media, comme décrit dans Messages de lecture multimédia. Votre application doit accepter ces messages pour contrôler la lecture de contenus multimédias dans l'application afin de permettre un contrôle de base de la lecture à partir des entrées de contrôle d'Android TV.

Consignes de compatibilité avec Android TV

Voici quelques recommandations et erreurs courantes à éviter pour vous assurer que votre application est compatible avec Android TV :

  • Sachez que la chaîne user-agent contient à la fois "Android" et "CrKey". Certains sites peuvent rediriger vers un site réservé aux mobiles, car ils détectent le libellé "Android". Ne partez pas du principe que la présence du terme "Android" dans la chaîne user-agent indique toujours un utilisateur mobile.
  • La pile multimédia d'Android peut utiliser GZIP transparent pour récupérer des données. Assurez-vous que vos données multimédias peuvent répondre à Accept-Encoding: gzip.
  • Les événements multimédias HTML5 d'Android TV peuvent être déclenchés à des moments différents de ceux de Chromecast, ce qui peut révéler des problèmes qui étaient masqués sur Chromecast.
  • Lorsque vous mettez à jour le contenu multimédia, utilisez les événements liés au contenu multimédia déclenchés par les éléments <audio>/<video>, tels que timeupdate, pause et waiting. Évitez d'utiliser des événements liés à la mise en réseau tels que progress, suspend et stalled, car ils ont tendance à dépendre de la plate-forme. Pour en savoir plus sur la gestion des événements multimédias dans votre récepteur, consultez Événements multimédias.
  • Lorsque vous configurez les certificats HTTPS de votre site récepteur, veillez à inclure les certificats CA intermédiaires. Consultez la page de test SSL Qualsys pour vérifier si le chemin de certification de confiance de votre site inclut un certificat CA étiqueté "téléchargement supplémentaire". Si c'est le cas, il est possible qu'il ne se charge pas sur les plates-formes Android.
  • Alors que Chromecast affiche la page du récepteur sur un plan graphique 720p, d'autres plates-formes Cast, y compris Android TV, peuvent afficher la page jusqu'à 1080p. Assurez-vous que votre page de récepteur s'adapte correctement à différentes résolutions.