Tutorial

Comment accéder aux caméras Avant et Arrière avec getUserMedia() de JavaScript.

Published on November 13, 2020
author

Chris Nwamba

Français
Comment accéder aux caméras Avant et Arrière avec getUserMedia() de JavaScript.

Introduction

Le HTML5 a permis l’introduction d’API donnant accès aux composants matériels des appareils, y compris de l’API MediaDevices. Cette API permet d’accéder à des périphériques d’entrée média comme l’audio et la vidéo.

Avec l’aide de cette API, les développeurs peuvent accéder à des appareils audio et vidéo pour diffuser et afficher des flux vidéo en direct dans le navigateur. Dans ce tutoriel, vous accéderez au flux vidéo à partir de l’appareil de l’utilisateur et l’afficherez dans le navigateur à l’aide du getUserMedia méthode.

L’API getUserMedia utilise les périphériques d’entrée média pour produire un MediaStream. Ce MediaStream contient les types de médias demandés, qu’ils soient audio ou vidéo. Grâce au flux renvoyé par l’API, les flux vidéo peuvent être affichés sur le navigateur, ce qui est utile pour la communication en temps réel sur le navigateur.

Lorsqu’il est utilisé avec l’ API MediaStream Recording, vous pouvez enregistrer et stocker des données médias saisies sur le navigateur. Cette API ne fonctionne que sur les origines sécurisées (comme les autres API nouvellement introduites), mais elle fonctionne également sur localhost et sur les URL des fichiers.

Conditions préalables

  • Une connaissance de base de JavaScript. Si vous ne connaissez pas JavaScript, essayez de consulter la série Comment coder en JavaScript.

Ce tutoriel explique d’abord les concepts et présente des exemples avec Codepen. Dans la dernière étape, vous créerez un flux vidéo fonctionnel pour le navigateur.

Étape 1 - Vérification de la prise en charge de l’appareil

Tout d’abord, vous verrez comment vérifier si le navigateur de l’utilisateur prend en charge l’API mediaDevices. Cette API existe dans le navigateur et contient l’état actuel et l’identité de l’agent utilisateur. Le contrôle est effectué à l’aide du code suivant, qui peut être collé dans Codepen :

if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
  console.log("Let's get this party started")
}

Tout d’abord, cela permet de vérifier si l’API mediaDevices existe dans le navigateur et vérifie ensuite si l’API getUserMedia est disponible dans le mediaDevices. Si cela revient comme true, vous pouvez commencer.

Étape 2 - Demander la permission de l’utilisateur

Après avoir confirmé la prise en charge de getUserMedia par le navigateur, vous devez demander l’autorisation d’utiliser les périphériques de saisie des médias sur l’agent utilisateur. Généralement, après qu’un utilisateur ait accordé sa permission, une Promise est renvoyée, qui se transforme en flux média. Cette Promise n’est pas renvoyée lorsque la permission est refusée par l’utilisateur, ce qui bloque l’accès à ces appareils.

Collez la ligne suivante dans le Codepen pour demander l’autorisation :

navigator.mediaDevices.getUserMedia({video: true})

L’objet fourni comme argument pour la méthode getUserMedia est appelé constraints. Cela permet de déterminer les périphériques d’entrée média auxquels vous demandez l’autorisation d’accéder. Par exemple, si l’objet contient audio : true, l’utilisateur(rice) sera invité(e) à accorder l’accès au dispositif d’entrée audio.

Étape 3 - Comprendre les contraintes des médias

Cette section couvrira le concept général de constraints. L’objet constraints est un objet MediaStreamConstraints qui spécifie les types de médias à demander et les exigences de chaque type de média. Vous pouvez spécifier les exigences pour le flux demandé en utilisant l’objet constraints comme la résolution du flux à utiliser (avant, arrière).

Vous devez préciser soit audio ou vidéo lors de la demande. Une erreur NotFoundError sera renvoyée si les types de médias demandés ne peuvent être trouvés sur le navigateur de l’utilisateur.

Si vous avez l’intention de demander un flux vidéo d’une résolution de 1280 x 720, vous pouvez mettre à jour l’objet constraints pour qu’il ressemble à ceci :

{
  video: {
    width: 1280,
    height: 720,
  }
}

Avec cette mise à jour, le navigateur essaiera de correspondre aux paramètres de qualité spécifiés pour le flux. Si l’appareil vidéo ne peut pas fournir cette résolution, le navigateur renvoie les autres résolutions disponibles.

Pour garantir que le navigateur renvoie une résolution qui ne soit pas inférieure à celle fournie, vous devrez utiliser la propriété min. Voici comment vous pourriez mettre à jour l’objet constraints pour inclure la propriété min :

{
  video: {
    width: {
      min: 1280,
    },
    height: {
      min: 720,
    }
  }
}

Cela permettra de garantir que la résolution de flux renvoyée sera au moins 1280 x 720. Si cette exigence minimale ne peut pas être respectée, la Promise sera rejetée avec une OverconstrainedError.

Dans certains cas, vous pouvez être préoccupé(e) par la sauvegarde des données et avoir besoin que le flux ne dépasse pas une résolution donnée. Cela peut s’avérer utile lorsque l’utilisateur est sur un plan limité. Pour activer cette fonctionnalité, mettez à jour l’objet constraints pour qu’il contienne un champ max :

{
  video: {
    width: {
      min: 1280,
      max: 1920,
    },
    height: {
      min: 720,
      max: 1080
    }
  }
}

Avec ces paramètres, le navigateur veillera à ce que le flux de retour ne soit pas inférieur à 1280 x 720 et ne dépasse pas 1920 x 1080.

D’autres termes peuvent être utilisés, notamment exact et ideal. Le paramètre ideal est généralement utilisé avec les propriétés min et max pour trouver le meilleur paramètre possible le plus proche des valeurs idéales fournies.

Vous pouvez mettre à jour les constraints pour utiliser le mot-clé ideal :

{
  video: {
    width: {
      min: 1280,
      ideal: 1920,
      max: 2560,
    },
    height: {
      min: 720,
      ideal: 1080,
      max: 1440
    }
  }
}

Pour indiquer au navigateur d’utiliser la caméra avant ou arrière (sur les appareils mobiles) sur les appareils, vous pouvez spécifier une propriété facingMode dans l’objet video :

{
  video: {
    width: {
      min: 1280,
      ideal: 1920,
      max: 2560,
    },
    height: {
      min: 720,
      ideal: 1080,
      max: 1440
    },
    facingMode: 'user'
  }
}

Ce paramètre permet d’utiliser la caméra frontale à tout moment dans tous les appareils. Pour utiliser la caméra arrière sur les appareils mobiles, vous pouvez modifier la propriété facingMode à environment.

{
  video: {
    ...
    facingMode: {
      exact: 'environment'
    }
  }
}

Étape 4 - Utiliser la méthode enumerateDevices

Lorsque la méthode enumerateDevices est appelée, elle renvoie tous les supports d’entrée disponibles sur le PC de l’utilisateur.

Avec cette méthode, vous pouvez fournir à l’utilisateur des options sur le périphérique d’entrée à utiliser pour la diffusion de contenu audio ou vidéo en continu. Cette méthode renvoie une Promise résolue en un tableau MediaDeviceInfo contenant des informations sur chaque appareil.

Un exemple d’utilisation de cette méthode est présenté dans l’extrait ci-dessous :

async function getDevices() {
  const devices = await navigator.mediaDevices.enumerateDevices();
}

Un exemple de réponse pour chacun des dispositifs ressemblerait à ce qui suit :

{
  deviceId: "23e77f76e308d9b56cad920fe36883f30239491b8952ae36603c650fd5d8fbgj",
  groupId: "e0be8445bd846722962662d91c9eb04ia624aa42c2ca7c8e876187d1db3a3875",
  kind: "audiooutput",
  label: "",
}

Remarque : une étiquette ne sera pas renvoyée si un flux n’est pas disponible ou si l’utilisateur a accordé des autorisations d’accès au dispositif.

Étape 5 - Afficher le flux vidéo sur le navigateur

Vous êtes passé(e) par le processus de demande et d’obtention de l’accès aux appareils multimédias, vous avez configuré des contraintes pour inclure les résolutions requises et vous avez sélectionné la caméra dont vous aurez besoin pour enregistrer la vidéo.

Après avoir parcouru toutes ces étapes, vous voudrez au moins voir si le flux est diffusé en fonction des paramètres configurés. Pour ce faire, vous utiliserez l’élément <vidéo> pour afficher le flux vidéo sur le navigateur.

Comme mentionné précédemment, la méthode getUserMedia renvoie une Promise qui peut être résolue en un flux. Le flux renvoyé peut être converti en une URL objet en utilisant la méthode createObjectURL. Cette URL sera définie comme une source vidéo.

Vous allez créer une courte démo dans laquelle nous laissons l’utilisateur choisir parmi la liste des appareils vidéo disponibles avec la méthode enumerateDevices.

Ceci est une méthode navigateur.mediaDevices. Elle énumère les périphériques médias disponibles, tels que les microphones et les caméras. Elle renvoie une Promise résolvable à un ensemble d’objets détaillant les périphériques médias disponibles.

Créez un fichier index.html et mettez à jour le contenu avec le code ci-dessous :

index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
<div class="display-cover">
    <video autoplay></video>
    <canvas class="d-none"></canvas>

    <div class="video-options">
        <select name="" id="" class="custom-select">
            <option value="">Select camera</option>
        </select>
    </div>

    <img class="screenshot-image d-none" alt="">

    <div class="controls">
        <button class="btn btn-danger play" title="Play"><i data-feather="play-circle"></i></button>
        <button class="btn btn-info pause d-none" title="Pause"><i data-feather="pause"></i></button>
        <button class="btn btn-outline-success screenshot d-none" title="ScreenShot"><i data-feather="image"></i></button>
    </div>
</div>

<script src="https://unpkg.com/feather-icons"></script>
<script src="script.js"></script>
</body>
</html>

Dans l’extrait ci-dessus, vous avez mis en place les éléments dont vous aurez besoin et quelques contrôles pour la vidéo. Un bouton permettant de prendre des captures d’écran du flux vidéo en cours est également inclus.

Maintenant, mettons un peu de style dans ces éléments.

Créez un fichier style.css et copiez les styles suivants dans celui-ci. Bootstrap a été inclus pour réduire la quantité de CSS que vous devrez écrire pour faire fonctionner les composants.

style.css
.screenshot-image {
    width: 150px;
    height: 90px;
    border-radius: 4px;
    border: 2px solid whitesmoke;
    box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
    position: absolute;
    bottom: 5px;
    left: 10px;
    background: white;
}

.display-cover {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 70%;
    margin: 5% auto;
    position: relative;
}

video {
    width: 100%;
    background: rgba(0, 0, 0, 0.2);
}

.video-options {
    position: absolute;
    left: 20px;
    top: 30px;
}

.controls {
    position: absolute;
    right: 20px;
    top: 20px;
    display: flex;
}

.controls > button {
    width: 45px;
    height: 45px;
    text-align: center;
    border-radius: 100%;
    margin: 0 6px;
    background: transparent;
}

.controls > button:hover svg {
    color: white !important;
}

@media (min-width: 300px) and (max-width: 400px) {
    .controls {
        flex-direction: column;
    }

    .controls button {
        margin: 5px 0 !important;
    }
}

.controls > button > svg {
    height: 20px;
    width: 18px;
    text-align: center;
    margin: 0 auto;
    padding: 0;
}

.controls button:nth-child(1) {
    border: 2px solid #D2002E;
}

.controls button:nth-child(1) svg {
    color: #D2002E;
}

.controls button:nth-child(2) {
    border: 2px solid #008496;
}

.controls button:nth-child(2) svg {
    color: #008496;
}

.controls button:nth-child(3) {
    border: 2px solid #00B541;
}

.controls button:nth-child(3) svg {
    color: #00B541;
}

.controls > button {
    width: 45px;
    height: 45px;
    text-align: center;
    border-radius: 100%;
    margin: 0 6px;
    background: transparent;
}

.controls > button:hover svg {
    color: white;
}

L’étape suivante consiste à ajouter des fonctionnalités à la démo. En utilisant la méthode enumerateDevices vous obtiendrez les appareils vidéo disponibles et vous les paramèterez comme options au sein de l’élément de sélection. Créez un fichier appelé script.js et mettez-le à jour avec l’extrait suivant :

script.js
feather.replace();

const controls = document.querySelector('.controls');
const cameraOptions = document.querySelector('.video-options>select');
const video = document.querySelector('video');
const canvas = document.querySelector('canvas');
const screenshotImage = document.querySelector('img');
const buttons = [...controls.querySelectorAll('button')];
let streamStarted = false;

const [play, pause, screenshot] = buttons;

const constraints = {
  video: {
    width: {
      min: 1280,
      ideal: 1920,
      max: 2560,
    },
    height: {
      min: 720,
      ideal: 1080,
      max: 1440
    },
  }
};

const getCameraSelection = async () => {
  const devices = await navigator.mediaDevices.enumerateDevices();
  const videoDevices = devices.filter(device => device.kind === 'videoinput');
  const options = videoDevices.map(videoDevice => {
    return `<option value="${videoDevice.deviceId}">${videoDevice.label}</option>`;
  });
  cameraOptions.innerHTML = options.join('');
};

play.onclick = () => {
  if (streamStarted) {
    video.play();
    play.classList.add('d-none');
    pause.classList.remove('d-none');
    return;
  }
  if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
    const updatedConstraints = {
      ...constraints,
      deviceId: {
        exact: cameraOptions.value
      }
    };
    startStream(updatedConstraints);
  }
};

const startStream = async (constraints) => {
  const stream = await navigator.mediaDevices.getUserMedia(constraints);
  handleStream(stream);
};

const handleStream = (stream) => {
  video.srcObject = stream;
  play.classList.add('d-none');
  pause.classList.remove('d-none');
  screenshot.classList.remove('d-none');
  streamStarted = true;
};

getCameraSelection();

Dans l’extrait ci-dessus, il y a deux choses qui se passent. Décomposons celles-ci :

  1. feather.replace() : cette méthode d’appel instancie feather qui est un ensemble d’icônes pour le développement web.
  2. La variable constraints contient la configuration initiale du flux. Elle sera étendue pour inclure le périphérique média choisi par l’utilisateur.
  3. getCameraSelection : cette fonction appelle la méthode enumerateDevices. Ensuite, vous filtrez le tableau à partir de la Promise résolue et sélectionnez les périphériques d’entrée vidéo À partir des résultats filtrés, vous créez <option> pour l’élément <select>.
  4. L’appel de la méthode getUserMedia se fait à l’intérieur de l’écouteur onclick du bouton de lecture. Ici, vous vérifierez si cette méthode est prise en charge par le navigateur de l’utilisateur avant de lancer le flux.
  5. Ensuite, vous appellerez la fonction startStream qui prend un argument constraints. Elle appelle la méthode getUserMedia avec les constraints fournies.handleStream est appelé en utilisant le flux de la Promise résolue Cette méthode fixe le flux renvoyé à l’élément vidéo srcObject.

Ensuite, vous ajouterez des écouteurs de clics aux boutons de commande de la page pour faire une pause, arrêter et faire des captures d'écran. De plus, vous ajouterez un auditeur à l’élément <select> pour mettre à jour les contraintes de flux avec le périphérique vidéo sélectionné.

Mettez à jour le fichier script.js avec le code ci-dessous :

script.js
...
cameraOptions.onchange = () => {
  const updatedConstraints = {
    ...constraints,
    deviceId: {
      exact: cameraOptions.value
    }
  };
  startStream(updatedConstraints);
};

const pauseStream = () => {
  video.pause();
  play.classList.remove('d-none');
  pause.classList.add('d-none');
};

const doScreenshot = () => {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  canvas.getContext('2d').drawImage(video, 0, 0);
  screenshotImage.src = canvas.toDataURL('image/webp');
  screenshotImage.classList.remove('d-none');
};

pause.onclick = pauseStream;
screenshot.onclick = doScreenshot;

Maintenant, lorsque vous ouvrez l’index.html dans le navigateur, cliquer le bouton Play permet de lancer le flux.

Voici une démo complète :

https://codepen.io/chrisbeast/pen/ebYwpX

Conclusion

Ce tutoriel a introduit l’API getUserMedia. C’est un ajout intéressant à HTML5, qui facilite le processus de capture des médias sur le web.

L’API prend un paramètre (constraints) qui peut être utilisé pour configurer l’accès aux périphériques d’entrée audio et vidéo. Il peut également être utilisé pour spécifier la résolution vidéo requise pour votre application.

Vous pouvez étendre la démo pour donner à l’utilisateur la possibilité de sauvegarder les captures d’écran réalisées, ainsi que d’enregistrer et de stocker des données vidéo et audio à l’aide de l’API MediaStream Recording.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Chris Nwamba

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.