Google is committed to advancing racial equity for Black communities. See how.
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Introduzione ai dispositivi multimediali

Durante lo sviluppo per il Web, lo standard WebRTC fornisce API per l'accesso a telecamere e microfoni collegati al computer o allo smartphone. Questi dispositivi vengono comunemente definiti dispositivi multimediali e sono accessibili con JavaScript tramite l'oggetto navigator.mediaDevices , che implementa l'interfaccia MediaDevices . Da questo oggetto possiamo enumerare tutti i dispositivi collegati, ascoltare le modifiche del dispositivo (quando un dispositivo è connesso o disconnesso) e aprire un dispositivo per recuperare un flusso multimediale (vedere di seguito).

Il modo più comune in cui viene utilizzato è tramite la funzione getUserMedia() , che restituisce una promessa che si risolverà in un MediaStream per i dispositivi multimediali corrispondenti. Questa funzione accetta un singolo oggetto MediaStreamConstraints che specifica i requisiti che abbiamo. Ad esempio, per aprire semplicemente il microfono e la videocamera predefiniti, faremo quanto segue.

Usando le promesse

 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);
    });
 

Utilizzando 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);
}
 

La chiamata a getUserMedia() attiverà una richiesta di autorizzazioni. Se l'utente accetta l'autorizzazione, la promessa viene risolta con un MediaStream contenente una traccia video e una traccia audio. Se l'autorizzazione viene negata, viene PermissionDeniedError un PermissionDeniedError . Nel caso in cui non vi siano dispositivi corrispondenti collegati, verrà NotFoundError un NotFoundError .

Il riferimento API completo per l'interfaccia MediaDevices è disponibile nei documenti Web MDN .

Interrogazione di dispositivi multimediali

In un'applicazione più complessa, molto probabilmente vorremmo controllare tutte le telecamere e i microfoni collegati e fornire il feedback appropriato all'utente. Questo può essere fatto chiamando la funzione enumerateDevices() . Ciò restituirà una promessa che si risolve in una matrice di MediaDevicesInfo che descrive ogni dispositivo multimediale noto. Possiamo usarlo per presentare all'utente un'interfaccia utente che gli permetta di scegliere quello che preferisce. Ogni MediaDevicesInfo contiene una proprietà denominata kind con il valore audioinput , audiooutput o videoinput , che indica che tipo di dispositivo multimediale è.

Usando le promesse

 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));
 

Utilizzando 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);
 

Ascolto di modifiche ai dispositivi

La maggior parte dei computer supporta il collegamento di vari dispositivi durante il runtime. Potrebbe essere una webcam collegata tramite USB, un auricolare Bluetooth o un set di altoparlanti esterni. Per supportare correttamente ciò, un'applicazione Web dovrebbe ascoltare i cambiamenti dei dispositivi multimediali. Questo può essere fatto aggiungendo un listener a navigator.mediaDevices per l'evento 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);
});
 

Vincoli multimediali

L'oggetto vincoli, che deve implementare l'interfaccia MediaStreamConstraints , che passiamo come parametro a getUserMedia() ci consente di aprire un dispositivo multimediale che soddisfa un determinato requisito. Questo requisito può essere definito in modo molto approssimativo (audio e / o video) o molto specifico (risoluzione minima della telecamera o un ID dispositivo esatto). Si consiglia alle applicazioni che utilizzano l'API getUserMedia() verificare prima i dispositivi esistenti e quindi di specificare un vincolo che corrisponda al dispositivo esatto utilizzando il vincolo deviceId . Inoltre, se possibile, i dispositivi saranno configurati in base ai vincoli. Possiamo abilitare la cancellazione dell'eco sui microfoni o impostare una larghezza e un'altezza specifiche o minime del video dalla videocamera.

 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 documentazione completa per l'interfaccia MediaStreamConstraints è disponibile nei documenti Web MDN .

Riproduzione locale

Una volta che un dispositivo multimediale è stato aperto e abbiamo disponibile un MediaStream , possiamo assegnarlo a un elemento video o audio per riprodurre lo stream localmente.

 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);
    }
}
 

L'HTML necessario per un tipico elemento video utilizzato con getUserMedia() solito avrà gli attributi autoplay e playsinline . L'attributo autoplay farà riprodurre automaticamente i nuovi stream assegnati all'elemento. L'attributo playsinline consente di riprodurre i video in linea, anziché solo a schermo intero, su alcuni browser mobili. Si consiglia inoltre di utilizzare controls="false" per i flussi live, a meno che l'utente non sia in grado di metterli in pausa.

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