Faire défiler et zoomer sur un onglet capturé

François Beaufort
François Beaufort

Il est déjà possible de partager des onglets, des fenêtres et des écrans sur la plate-forme Web avec l'API Screen Capture. Lorsqu'une application Web appelle getDisplayMedia(), Chrome invite l'utilisateur à partager un onglet, une fenêtre ou un écran avec l'application Web en tant que vidéo MediaStreamTrack.

De nombreuses applications Web qui utilisent getDisplayMedia() affichent un aperçu vidéo de la surface capturée. Par exemple, les applications de visioconférence diffusent souvent cette vidéo aux utilisateurs à distance tout en l'affichant dans un HTMLVideoElement local, de sorte que l'utilisateur local voit constamment un aperçu de ce qu'il partage.

Cette documentation présente la nouvelle API Captured Surface Control dans Chrome, qui permet à votre application Web de faire défiler un onglet capturé, ainsi que de lire et d'écrire le niveau de zoom d'un onglet capturé.

Un utilisateur fait défiler et zoome sur un onglet capturé (démonstration).

Pourquoi utiliser le contrôle de surface capturée ?

Toutes les applications de visioconférence présentent le même inconvénient. Si l'utilisateur souhaite interagir avec un onglet ou une fenêtre capturés, il doit passer à cette surface, ce qui l'éloigne de l'application de visioconférence. Cela pose certains problèmes :

  • L'utilisateur ne peut pas voir l'application capturée et les flux vidéo des utilisateurs à distance en même temps, sauf s'il utilise le Picture-in-picture ou des fenêtres côte à côte distinctes pour l'onglet de visioconférence et l'onglet partagé. Cela peut être difficile sur un écran plus petit.
  • L'utilisateur doit passer de l'application de visioconférence à la surface capturée, ce qui est contraignant.
  • L'utilisateur perd l'accès aux commandes exposées par l'application de visioconférence lorsqu'il n'est pas dessus. Par exemple, une application de chat intégrée, les réactions emoji, les notifications concernant les utilisateurs qui demandent à rejoindre l'appel, les commandes multimédias et de mise en page, ainsi que d'autres fonctionnalités utiles de visioconférence.
  • Le présentateur ne peut pas déléguer le contrôle à des participants à distance. Cela conduit à un scénario bien trop familier où les utilisateurs à distance demandent au présentateur de changer de diapositive, de faire défiler un peu vers le haut et vers le bas ou d'ajuster le niveau de zoom.

L'API Captured Surface Control résout ces problèmes.

Comment utiliser la commande de surface capturée ?

Pour utiliser correctement Captured Surface Control, vous devez suivre quelques étapes, comme capturer explicitement un onglet de navigateur et obtenir l'autorisation de l'utilisateur avant de pouvoir faire défiler et zoomer sur l'onglet capturé.

Capturer un onglet de navigateur

Commencez par inviter l'utilisateur à choisir une surface à partager à l'aide de getDisplayMedia(), puis associez un objet CaptureController à la session de capture. Nous utiliserons bientôt cet objet pour contrôler la surface capturée.

const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });

Ensuite, générez un aperçu local de la surface capturée sous la forme d'un élément <video> :

const previewTile = document.querySelector('video');
previewTile.srcObject = stream;

Si l'utilisateur choisit de partager une fenêtre ou un écran, cela ne relève pas du champ d'application pour le moment. Toutefois, s'il choisit de partager un onglet, nous pouvons continuer.

const [track] = stream.getVideoTracks();

if (track.getSettings().displaySurface !== 'browser') {
  // Bail out early if the user didn't pick a tab.
  return;
}

Invite d'autorisation

La première invocation de forwardWheel(), increaseZoomLevel(), decreaseZoomLevel() ou resetZoomLevel() sur un objet CaptureController donné génère une invite d'autorisation. Si l'utilisateur accorde l'autorisation, d'autres appels de ces méthodes sont autorisés.

Un geste de l'utilisateur est requis pour afficher une invite d'autorisation. L'application ne doit donc appeler les méthodes susmentionnées que si elle dispose déjà de l'autorisation ou en réponse à un geste de l'utilisateur, tel qu'un click sur un bouton approprié dans l'application Web.

Faire défiler

À l'aide de forwardWheel(), une application de capture peut transférer les événements de roue d'un élément source de l'application de capture elle-même vers la fenêtre d'affichage de l'onglet capturé. Ces événements sont indiscernables des interactions directes des utilisateurs pour l'application capturée.

En supposant que l'application de capture utilise un élément <video> appelé "previewTile", le code suivant montre comment relayer les événements de roue d'envoi vers l'onglet capturé :

const previewTile = document.querySelector('video');
try {
  // Relay the user's action to the captured tab.
  await controller.forwardWheel(previewTile);
} catch (error) {
  // Inspect the error.
  // ...
}

La méthode forwardWheel() accepte une seule entrée, qui peut être l'une des suivantes :

  • Élément HTML à partir duquel les événements de roue seront transférés à l'onglet capturé.
  • null, indiquant que la redirection doit s'arrêter.

Un appel réussi à forwardWheel() remplace les appels précédents.

La promesse renvoyée par forwardWheel() peut être rejetée dans les cas suivants :

  • Si la session de capture n'a pas encore commencé ou a déjà été arrêtée.
  • Si l'utilisateur n'a pas accordé l'autorisation requise.

Zoom

L'interaction avec le niveau de zoom de l'onglet capturé s'effectue via les surfaces d'API CaptureController suivantes :

getSupportedZoomLevels()

Cette méthode renvoie une liste des niveaux de zoom pris en charge par le navigateur pour le type de surface capturé. Les valeurs de cette liste sont exprimées en pourcentage par rapport au "niveau de zoom par défaut", qui est défini sur 100 %. La liste est croissante de manière monotone et contient la valeur 100.

Cette méthode ne peut être appelée que pour les types de surfaces d'affichage compatibles, c'est-à-dire uniquement pour les onglets pour le moment.

controller.getSupportedZoomLevels() peut être appelé si les conditions suivantes sont remplies :

  • controller est associé à une capture active.
  • La capture est celle d'un onglet.

Dans le cas contraire, une erreur est générée.

L'autorisation "captured-surface-control" n'est pas requise pour appeler cette méthode.

zoomLevel

Cet attribut en lecture seule contient le niveau de zoom actuel de l'onglet capturé. Il s'agit d'un attribut pouvant être nul, qui contient null si le type de surface capturé n'a pas de définition significative du niveau de zoom. Pour le moment, le niveau de zoom n'est défini que pour les onglets, et non pour les fenêtres ni les écrans.

Une fois la capture terminée, l'attribut contient la dernière valeur du niveau de zoom.

L'autorisation "captured-surface-control" n'est pas requise pour lire cet attribut.

onzoomlevelchange

Ce gestionnaire d'événements permet d'écouter les modifications apportées au niveau de zoom de l'onglet capturé. Ces événements se produisent :

  • Lorsque l'utilisateur interagit avec le navigateur pour modifier manuellement le niveau de zoom de l'onglet capturé.
  • En réponse aux appels de l'application de capture aux méthodes de réglage du zoom (décrites ci-dessous).

L'autorisation "captured-surface-control" n'est pas requise pour lire cet attribut.

increaseZoomLevel(), decreaseZoomLevel() et resetZoomLevel()

Ces méthodes permettent de manipuler le niveau de zoom de l'onglet capturé.

increaseZoomLevel() et decreaseZoomLevel() permettent de passer au niveau de zoom suivant ou précédent, respectivement, selon l'ordre renvoyé par getSupportedZoomLevels(). resetZoomLevel() définit la valeur sur 100.

L'autorisation "captured-surface-control" est requise pour appeler ces méthodes. Si l'application de capture ne dispose pas de cette autorisation, l'utilisateur est invité à l'accorder ou à la refuser.

Ces méthodes renvoient toutes une promesse qui est résolue si l'appel réussit et rejetée dans le cas contraire. Voici quelques raisons possibles expliquant le refus :

  • Autorisation manquante.
  • Appelé avant le début de la capture.
  • Appelé après la fin de la capture.
  • Appelé sur un controller associé à une capture d'un type de surface d'affichage non compatible. (c'est-à-dire tout sauf la capture d'onglet).
  • Tentatives d'augmenter ou de diminuer la valeur au-delà de la valeur maximale ou minimale, respectivement.

Il est notamment recommandé d'éviter d'appeler decreaseZoomLevel() si controller.zoomLevel == controller.getSupportedZoomLevels().at(0), et de protéger les appels à increaseZoomLevel() de la même manière avec .at(-1).

L'exemple suivant montre comment permettre à l'utilisateur d'augmenter le niveau de zoom d'un onglet capturé directement depuis l'application de capture :

const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
  if (controller.zoomLevel >= controller.getSupportedZoomLevels().at(-1)) {
    return;
  }
  try {
    await controller.increaseZoomLevel();
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

L'exemple suivant montre comment réagir aux changements de niveau de zoom d'un onglet capturé :

controller.addEventListener('zoomlevelchange', (event) => {
  const zoomLevelLabel = document.querySelector('#zoomLevelLabel');
  zoomLevelLabel.textContent = `${controller.zoomLevel}%`;
});

Détection de caractéristiques

Pour vérifier si les API Captured Surface Control sont prises en charge, utilisez :

if (!!window.CaptureController?.prototype.forwardWheel) {
  // CaptureController forwardWheel() is supported.
}

Il est également possible d'utiliser l'une des autres surfaces de l'API Captured Surface Control, comme increaseZoomLevel ou decreaseZoomLevel, ou même de les vérifier toutes.

Prise en charge des navigateurs

Le contrôle de surface capturée est disponible à partir de Chrome 136 sur ordinateur uniquement.

Sécurité et confidentialité

La règle d'autorisation "captured-surface-control" vous permet de gérer l'accès de votre application de capture et des iFrames tiers intégrés à la commande de surface capturée. Pour comprendre les compromis de sécurité, consultez la section Considérations sur la confidentialité et la sécurité de l'explication sur le contrôle de la surface capturée.

Démo

Vous pouvez tester Captured Surface Control en exécutant la démonstration.

Commentaires

L'équipe Chrome et la communauté des normes Web souhaitent connaître votre expérience avec Captured Surface Control.

Parlez-nous de la conception

Y a-t-il quelque chose qui ne fonctionne pas comme prévu dans la capture de surface ? Manque-t-il des méthodes ou des propriétés dont vous avez besoin pour implémenter votre idée ? Vous avez une question ou un commentaire sur le modèle de sécurité ? Signalez un problème lié aux spécifications dans le dépôt GitHub ou ajoutez vos commentaires à un problème existant.

Vous rencontrez un problème d'implémentation ?

Avez-vous trouvé un bug dans l'implémentation de Chrome ? Ou l'implémentation est-elle différente de la spécification ? Signalez un bug sur https://new.crbug.com. Veillez à inclure autant de détails que possible, ainsi que des instructions pour reproduire le problème.