Premiers pas avec les périphériques multimédias

Lors du développement pour le Web, la norme WebRTC fournit des API permettant d'accéder caméras et micros connectés à l'ordinateur ou au smartphone. Ces appareils sont communément appelés périphériques multimédias et sont accessibles via JavaScript via l'objet navigator.mediaDevices, qui implémente MediaDevices de commande. À partir de cet objet, nous pouvons énumérer tous les appareils connectés, écouter changement d'appareil (quand un appareil est connecté ou déconnecté), et ouvrir un appareil pour récupérer un flux multimédia (voir ci-dessous).

La méthode la plus courante consiste à utiliser la fonction getUserMedia(), qui renvoie une promesse qui se résout en MediaStream pour le contenu multimédia correspondant. appareils. Cette fonction accepte un seul objet MediaStreamConstraints qui spécifie nos exigences. Par exemple, si vous souhaitez simplement ouvrir le micro et la caméra par défaut, nous faisons ce qui suit.

Utiliser des promesses

const constraints = {
    'video': true,
    'audio': true
}
navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
        console.log('Got MediaStream:', stream);
    })
    .catch(error => {
        console.error('Error accessing media devices.', error);
    });

Utiliser async/await

const openMediaDevices = async (constraints) => {
    return await navigator.mediaDevices.getUserMedia(constraints);
}

try {
    const stream = openMediaDevices({'video':true,'audio':true});
    console.log('Got MediaStream:', stream);
} catch(error) {
    console.error('Error accessing media devices.', error);
}

L'appel de getUserMedia() déclenche une demande d'autorisation. Si l'utilisateur accepte l'autorisation, la promesse est résolue avec une MediaStream contenant une vidéo et une piste audio. Si l'autorisation est refusée, Une exception PermissionDeniedError est générée. Si aucun appareil ne correspond connecté, une erreur NotFoundError est générée.

La documentation de référence complète de l'API pour l'interface MediaDevices est disponible sur le site MDN web d'assistance.

Interroger des appareils multimédias

Dans une application plus complexe, il est fort probable que nous voudrions vérifier caméras et micros connectés et envoyer les commentaires appropriés aux utilisateur. Pour ce faire, appelez la fonction enumerateDevices(). Cela permettra renvoyer une promesse qui renvoie vers un tableau de MediaDevicesInfo qui décrit chaque appareil multimédia connu. Nous pouvons l'utiliser pour présenter une UI à l'utilisateur, ce qui qu’ils choisissent celui qu’ils préfèrent. Chaque MediaDevicesInfo contient une propriété nommée kind avec la valeur audioinput, audiooutput ou videoinput, indiquant de quel type de périphérique multimédia il s'agit.

Utiliser des promesses

function getConnectedDevices(type, callback) {
    navigator.mediaDevices.enumerateDevices()
        .then(devices => {
            const filtered = devices.filter(device => device.kind === type);
            callback(filtered);
        });
}

getConnectedDevices('videoinput', cameras => console.log('Cameras found', cameras));

Utiliser async/await

async function getConnectedDevices(type) {
    const devices = await navigator.mediaDevices.enumerateDevices();
    return devices.filter(device => device.kind === type)
}

const videoCameras = getConnectedDevices('videoinput');
console.log('Cameras found:', videoCameras);

Écouter les modifications apportées aux appareils

La plupart des ordinateurs prennent en charge le branchement de différents périphériques pendant l'exécution. Il peut s'agir webcam connectée par USB, un casque Bluetooth ou un ensemble de haut-parleurs externes. Dans une application Web doit écouter les modifications des périphériques multimédias. Pour ce faire, ajoutez un écouteur navigator.mediaDevices pour l'événement devicechange.

// Updates the select element with the provided set of cameras
function updateCameraList(cameras) {
    const listElement = document.querySelector('select#availableCameras');
    listElement.innerHTML = '';
    cameras.map(camera => {
        const cameraOption = document.createElement('option');
        cameraOption.label = camera.label;
        cameraOption.value = camera.deviceId;
    }).forEach(cameraOption => listElement.add(cameraOption));
}

// Fetch an array of devices of a certain type
async function getConnectedDevices(type) {
    const devices = await navigator.mediaDevices.enumerateDevices();
    return devices.filter(device => device.kind === type)
}

// Get the initial set of cameras connected
const videoCameras = getConnectedDevices('videoinput');
updateCameraList(videoCameras);

// Listen for changes to media devices and update the list accordingly
navigator.mediaDevices.addEventListener('devicechange', event => {
    const newCameraList = getConnectedDevices('video');
    updateCameraList(newCameraList);
});

Contraintes multimédias

L'objet de contraintes, qui doit implémenter MediaStreamConstraints que nous transmettons en tant que paramètre à getUserMedia() nous permet d'ouvrir périphérique multimédia qui répond à une certaine exigence. Cette exigence peut être très définie de manière vague (audio et/ou vidéo), ou très spécifique (avec une configuration ou un identifiant exact de l'appareil). Il est recommandé d'utiliser l'API getUserMedia() vérifie d'abord les appareils existants, puis spécifie un qui correspond exactement à l'appareil concerné à l'aide de la contrainte deviceId. Si possible, les appareils seront également configurés en fonction des contraintes. Mer peut activer l'annulation de l'écho sur les micros, ou définir une largeur minimale ou spécifique et la hauteur de la vidéo de la caméra.

async function getConnectedDevices(type) {
    const devices = await navigator.mediaDevices.enumerateDevices();
    return devices.filter(device => device.kind === type)
}

// Open camera with at least minWidth and minHeight capabilities
async function openCamera(cameraId, minWidth, minHeight) {
    const constraints = {
        'audio': {'echoCancellation': true},
        'video': {
            'deviceId': cameraId,
            'width': {'min': minWidth},
            'height': {'min': minHeight}
            }
        }

    return await navigator.mediaDevices.getUserMedia(constraints);
}

const cameras = getConnectedDevices('videoinput');
if (cameras && cameras.length > 0) {
    // Open first available video camera with a resolution of 1280x720 pixels
    const stream = openCamera(cameras[0].deviceId, 1280, 720);
}

La documentation complète de l'interface MediaStreamConstraints est disponible sur le MDN Web d'assistance.

Lecture locale

Une fois qu'un appareil multimédia a été ouvert et qu'un MediaStream est disponible, nous vous pouvez l'attribuer à un élément audio ou vidéo pour le lire en local.

async function playVideoFromCamera() {
    try {
        const constraints = {'video': true, 'audio': true};
        const stream = await navigator.mediaDevices.getUserMedia(constraints);
        const videoElement = document.querySelector('video#localVideo');
        videoElement.srcObject = stream;
    } catch(error) {
        console.error('Error opening video camera.', error);
    }
}

Le code HTML requis pour un élément vidéo standard utilisé avec getUserMedia() comportent généralement les attributs autoplay et playsinline. autoplay lance la lecture automatique des nouveaux flux attribués à l'élément. L'attribut playsinline permet de lire la vidéo intégrée, au lieu d'être uniquement lue dans son intégralité. sur certains navigateurs mobiles. Il est également recommandé d'utiliser controls="false" pour les diffusions en direct, sauf si l'utilisateur doit pouvoir les mettre en pause de l'IA générative.

<html>
<head><title>Local video playback</title></head>
<body>
    <video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>