Capturer un flux vidéo à partir de n'importe quel élément

François Beaufort
François Beaufort
Elad Alon
Elad Alon

L'API Capture d'écran vous permet de capturer l'intégralité de l'onglet actif. L'API Element Capture vous permet de capturer et d'enregistrer un élément HTML spécifique. Elle transforme une capture de l'intégralité de l'onglet en capture d'une sous-arborescence DOM spécifique, ne capturant que les descendants directs de l'élément cible. En d'autres termes, il recadre et supprime les contenus masqués et occultants.

Pourquoi utiliser la capture d'éléments ?

Considérer les exigences d'une application de visioconférence peut vous aider à comprendre où la capture d'élément est utile. Si vous disposez d'une application de visioconférence qui vous permet d'intégrer des applications tierces dans un iFrame, vous pouvez parfois capturer cet iFrame en tant que vidéo et la transmettre à des participants à distance.

Capture d'écran d'une visioconférence dans Chrome.
Elad utilise une application tierce lors d'une visioconférence avec François.

Le fait d'appeler getDisplayMedia() et de laisser l'utilisateur choisir l'onglet actif transmettrait la totalité de l'onglet actif. Cela est susceptible de lui transmettre la propre vidéo des gens. Vous pouvez le recadrer à l'aide de la fonctionnalité Region Capture.

Cependant, que se passe-t-il si le présentateur interagit avec l'application de visioconférence et qu'un contenu, comme une liste déroulante, se superpose au contenu destiné à la capture ?

Capture d'écran d'une liste déroulante recouvrant le contenu destiné à la capture
Une liste déroulante s'affiche au-dessus du contenu à capturer.

La capture de région ne vous serait pas utile dans ce cas. Il est possible qu'une partie de cette liste soit visible sur l'écran des participants à distance.

Capture d'écran d'une liste déroulante.
La liste déroulante de Elad s'affiche au-dessus du contenu reçu par François.

Le fait que la capture de région capture des parties des éléments de cette manière (ce que l'on appelle le contenu d'obturation) pose plusieurs problèmes:

  • Le masquage de contenu peut empêcher l'affichage du contenu que l'utilisateur souhaitait partager.
  • Le masquage du contenu peut être privé (par exemple, les notifications de chat).
  • Masquer le contenu peut être déroutant. Par exemple, une nouvelle mise en page de l'application peut rapidement amener les vidéos des participants à distance sur la cible capturée.

L'API Element Capture résout tous ces problèmes en vous permettant de cibler l'élément que vous souhaitez partager.

Capture d'écran de l'élément cible sans liste déroulante dans la vue.
François ne voit pas la liste déroulante d'Elad.

Comment utiliser la capture d'éléments ?

captureTarget est un élément de votre page qui comporte le contenu que l'utilisateur souhaite capturer. Vous voulez que l'application Web de visioconférence enregistre captureTarget et la partage avec des participants à distance. Vous obtenez donc un RestrictionTarget à partir de captureTarget. Après avoir restreint la piste vidéo à l'aide de ce RestrictionTarget, les images de cette piste vidéo se composent désormais uniquement des pixels qui font partie de captureTarget et de ses descendants DOM directs.

Si captureTarget change de taille, de forme ou de lieu, la piste vidéo suit le mouvement sans nécessiter d'entrée supplémentaire de la part de l'une ou l'autre des applications Web. Le fait de masquer le contenu qui apparaît, disparaît ou se déplace n'est pas non plus nécessaire.

Vérifiez à nouveau ces étapes:

Commencez par autoriser l'utilisateur à capturer l'onglet actuel.

// Ask the user for permission to start capturing the current tab.
const stream = await navigator.mediaDevices.getDisplayMedia({
 preferCurrentTab: true,
});
const [track] = stream.getVideoTracks();

Définissez un RestrictionTarget en appelant RestrictionTarget.fromElement() avec un élément de votre choix en entrée.

// Associate captureTarget with a new RestrictionTarget
const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Appelez ensuite restrictTo() sur la piste vidéo avec RestrictionTarget comme entrée. Une fois la dernière promesse résolue, toutes les images suivantes sont limitées.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

// Enjoy! Transmit remotely.

Présentation détaillée

Détection de fonctionnalités

Pour vérifier si RestrictionTarget.fromElement() est compatible, utilisez:

if ("RestrictionTarget" in self && "fromElement" in RestrictionTarget) {
  // Deriving a restriction target is supported.
}

Établir un objet RestrictionTarget

Concentrez-vous sur l'élément appelé captureTarget. Pour en déduire un RestrictionTarget, appelez RestrictionTarget.fromElement(captureTarget). En cas de succès, la promesse renvoyée sera résolue avec un nouvel objet RestrictionTarget. Sinon, elle sera refusée si vous avez généré un nombre déraisonnable d'objets RestrictionTarget.

const captureTarget = document.querySelector("#captureTarget");
const restrictionTarget = await RestrictionTarget.fromElement(captureTarget);

Contrairement à un élément, un objet RestrictionTarget est sérialisable. Il peut être transmis à un autre document à l'aide de Window.postMessage(), par exemple.

Restriction

Lors de la capture d'un onglet, la piste vidéo expose restrictTo(). Lors de la capture de l'onglet actuel, vous pouvez appeler restrictTo() avec null ou toute RestrictionTarget dérivée d'un élément de l'onglet actuel.

Les appels à restrictTo(restrictionTarget) modifient la piste vidéo en une capture de captureTarget, comme s'il avait été dessiné seul, indépendamment du reste du DOM. Tous les descendants de captureTarget sont également capturés. Les frères et sœurs de captureTarget sont éliminés de la capture. Résultat : toutes les images envoyées sur la piste semblent avoir été recadrées pour correspondre aux contours de captureTarget, et tout contenu obstrué et occulté est supprimé.

// Start restricting the self-capture video track using the RestrictionTarget.
await track.restrictTo(restrictionTarget);

Les appels à restrictTo(null) rétablissent l'état d'origine du canal.

// Stop restricting.
await track.restrictTo(null);

Si l'appel de restrictTo() réussit, la promesse renvoyée est résolue lorsqu'il est possible de garantir que toutes les images vidéo suivantes seront limitées à captureTarget.

En cas d'échec, la promesse est rejetée. Un appel au restrictTo() échoue pour l'une des raisons suivantes:

  • Si l'élément restrictionTarget a été saisi dans un onglet autre que celui en cours de capture. Notez qu'en cliquant sur le bouton "Partager cet onglet à la place", les utilisateurs peuvent modifier à tout moment l'onglet capturé.
  • Si restrictionTarget est dérivé d'un élément qui n'existe plus.
  • Si la piste comporte des clones. Consultez le problème 1509418.
  • Si la piste en cours n'est pas une piste vidéo prise par vous-même,
  • Si l'élément à partir duquel restrictionTarget a été dérivé ne peut pas faire l'objet de restrictions.

Considérations liées à la capture automatique

Lorsqu'une application appelle getDisplayMedia() et que l'utilisateur choisit de capturer son propre onglet, nous appelons cela une "auto-capture".

La méthode restrictTo() est utilisée sur n'importe quelle piste vidéo de capture d'onglet, et pas seulement pour la capture automatique. Toutefois, pour le moment, la capture des éléments n'est activée que pour l'auto-capture. Il est donc conseillé de vérifier si l'utilisateur a sélectionné l'onglet actif avant d'essayer de limiter la piste. Pour ce faire, utilisez Capture Handle. Vous pouvez également demander au navigateur d'encourager l'utilisateur à effectuer une capture automatique à l'aide de preferCurrentTab.

Transparence

Les images vidéo reçues par l'application via getDisplayMedia() n'incluent pas de version alpha. Si une application définit une cible de capture partiellement transparente, la suppression de la version alpha peut avoir les conséquences suivantes:

  • Les couleurs peuvent changer. Les éléments cibles partiellement transparents dessinés sur un arrière-plan clair peuvent sembler plus sombres lorsque le canal alpha est supprimé, et ceux dessinés sur un arrière-plan sombre peuvent sembler plus clairs.
  • Les couleurs qui étaient invisibles ou imperceptibles par l'utilisateur lorsque la version alpha était définie sur sa valeur maximale s'affichent une fois la version alpha supprimée. Par exemple, des zones noires inattendues peuvent apparaître dans les images capturées si les sections transparentes comportent le code RVBA rgba(0, 0, 0, 0).
Capture d'écran du résultat d'une cible de capture transparente non rectangulaire.
Le flux vidéo cible de capture transparente non rectangulaire (à droite) est un rectangle à fond noir contenant un cercle bleu opaque.

Cibles de capture non éligibles

Il est toujours possible de commencer à limiter une piste à toute cible de capture valide. Toutefois, les frames ne sont pas produits dans certaines conditions, par exemple si l'élément ou un ancêtre est display:none. La raison générale est que la restriction ne s'applique qu'à un élément qui comprend une zone rectangulaire unique, cohérente et bidimensionnelle, dont les pixels peuvent être déterminés logiquement indépendamment de tout élément parent ou frère.

Pour vous assurer que l'élément peut faire l'objet de restrictions, il est important qu'il forme son propre contexte d'empilement. Pour ce faire, vous pouvez spécifier la propriété CSS isolation et la définir sur isolate.

<div id="captureTarget" style="isolation: isolate;"></iframe>

Notez que l'élément cible peut être ou non éligible à la restriction à tout moment, par exemple si l'application modifie ses propriétés CSS. Il appartient à l'application d'utiliser des cibles de capture raisonnables et d'éviter de modifier leurs propriétés de manière inattendue. Si l'élément cible n'est plus éligible, de nouvelles images ne seront simplement diffusées sur le titre que lorsque l'élément cible sera à nouveau éligible à des restrictions.

Activation de la capture d'éléments...

L'API Element Capture est disponible dans Chrome sur ordinateur via l'indicateur Element Capture et peut être activée sur chrome://flags/#element-capture.

Cette fonctionnalité entame également une phase d'évaluation à partir de Chrome 121 sur ordinateur, ce qui permet aux développeurs d'activer la fonctionnalité pour les visiteurs de leurs sites afin de collecter des données auprès d'utilisateurs réels. Pour en savoir plus sur ces phases, consultez Premiers pas avec les phases d'évaluation.

Sécurité et confidentialité

Pour comprendre les compromis en termes de sécurité, consultez la section Considérations liées à la confidentialité et à la sécurité de la spécification Element Capture.

Le navigateur Chrome dessine une bordure bleue autour des bords des onglets capturés.

Démonstration

Vous pouvez jouer avec Element Capture en exécutant la démonstration sur Glitch. Pensez à consulter le code source.

Commentaires

L'équipe Chrome et la communauté des normes Web souhaitent en savoir plus sur votre expérience avec Element Capture.

Parlez-nous de la conception

Y a-t-il quelque chose qui ne fonctionne pas comme prévu dans la capture de région ? Ou manque-t-il des méthodes ou des propriétés dont vous avez besoin pour mettre en œuvre votre idée ? Vous avez une question ou un commentaire sur le modèle de sécurité ?

  • Signalez un problème de spécification dans le dépôt GitHub ou faites part de vos commentaires à un problème existant.

Un problème d'implémentation ?

Avez-vous détecté un bug dans l'implémentation de Chrome ? Ou la mise en œuvre est-elle différente des spécifications ?

  • Pour signaler un bug, rendez-vous sur https://new.crbug.com. Veillez à inclure autant de détails que possible, ainsi que des instructions simples pour reproduire le bug. Glitch est idéal pour partager des représentations rapides et faciles.

Remerciements

Photo de Paul Skorupskas, publiée sur Unsplash