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.
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.
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.
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.
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'
}
}
}
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.
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 :
<!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.
.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 :
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 :
feather.replace()
: cette méthode d’appel instancie feather qui est un ensemble d’icônes pour le développement web.constraints
contient la configuration initiale du flux. Elle sera étendue pour inclure le périphérique média choisi par l’utilisateur.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>
.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.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 :
...
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
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.
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!