Przy programowaniu do internetu standard WebRTC zapewnia interfejsy API umożliwiające dostęp
kamer i mikrofonów podłączonych do komputera lub smartfona. Te urządzenia
są potocznie nazywane „urządzeniami multimedialnymi” i można je otworzyć za pomocą języka JavaScript.
za pomocą obiektu navigator.mediaDevices, który implementuje interfejs MediaDevices
za pomocą prostego interfejsu online. Na podstawie tego obiektu możemy wyliczyć wszystkie połączone urządzenia, nasłuchiwać
zmiana urządzenia (gdy urządzenie jest połączone lub odłączone) i otwarcie urządzenia;
aby pobrać strumień multimediów (patrz poniżej).
Najpopularniejszym sposobem jest podanie tej funkcji za pomocą funkcji getUserMedia(), która
zwraca obietnicę, która zostanie rozstrzygnięta na MediaStream w przypadku pasujących multimediów
urządzenia. Ta funkcja przyjmuje pojedynczy obiekt MediaStreamConstraints, który
określa nasze wymagania. Aby na przykład otworzyć
domyślny mikrofon i kamerę, należy wykonać następujące czynności.
Korzystanie z obietnic
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);
});
Używanie asynchronicznego/oczekiwania
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);
}
Wywołanie getUserMedia() spowoduje wysłanie prośby o uprawnienia. Jeśli użytkownik
akceptuje to uprawnienie, obietnica jest zakończona za pomocą elementu MediaStream zawierającego
jeden film i jedną ścieżkę dźwiękową. W przypadku odmowy uprawnień
PermissionDeniedError trafia na piłkę Na wypadek, gdyby nie znaleziono pasujących urządzeń
połączono, zostanie zgłoszony NotFoundError.
Pełna dokumentacja interfejsu API usługi MediaDevices jest dostępna na stronie MDN
dokumenty.
Wysyłanie zapytań dotyczących urządzeń multimedialnych
Przy bardziej złożonej aplikacji będziemy prawdopodobnie sprawdzać
podłączone kamery i mikrofony oraz przekazywać
odpowiednie informacje zwrotne
użytkownika. Można to zrobić, wywołując funkcję enumerateDevices(). Dzięki temu
zwraca obietnicę, która kończy się na tablicy MediaDevicesInfo, która opisuje
każdego znanego urządzenia multimedialnego. Możemy to wykorzystać do zaprezentowania użytkownikowi interfejsu
i wybiorą tę, która im odpowiada. Każdy element MediaDevicesInfo zawiera właściwość o nazwie
kind o wartości audioinput, audiooutput lub videoinput, która wskazuje
typu urządzenia multimedialnego.
Korzystanie z obietnic
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));
Używanie asynchronicznego/oczekiwania
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);
Nasłuchiwanie zmian dotyczących urządzeń
Większość komputerów pozwala podłączyć różne urządzenia podczas działania. Może to być
kamera internetowa podłączona przez USB, zestaw słuchawkowy Bluetooth lub zestaw głośników zewnętrznych. W
Aby to obsługiwać, aplikacja internetowa powinna nasłuchiwać zmian
urządzeń multimedialnych. Można to zrobić, dodając detektor do
navigator.mediaDevices dla wydarzenia 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);
});
Ograniczenia dotyczące multimediów
Obiekt ograniczeń, który musi implementować interfejs MediaStreamConstraints
który przekazujemy jako parametr do getUserMedia(), pozwalamy na otwarcie
urządzenia multimedialnego spełniające określone wymagania. Ten wymóg może być bardzo
luźno zdefiniowane (dźwięk i/lub obraz) lub bardzo szczegółowe (minimalna jakość w przypadku kamery
rozdzielczość lub dokładny identyfikator urządzenia). Zaleca się, aby aplikacje używające języka
interfejs API getUserMedia() najpierw sprawdza istniejące urządzenia, a potem określa
ograniczenie pasujące do konkretnego urządzenia z ograniczeniem deviceId.
Urządzenia będą też w miarę możliwości skonfigurowane zgodnie z obowiązującymi ograniczeniami. Śr
może włączyć redukcję echa w mikrofonach lub ustawić konkretną bądź minimalną szerokość
oraz wysokość
filmu od kamery.
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);
}
Pełną dokumentację interfejsu MediaStreamConstraints znajdziesz
w witrynie MDN
dokumenty.
Odtwarzanie lokalne
Po otwarciu urządzenia multimedialnego i udostępnieniu urządzenia MediaStream
możesz go przypisać do elementu wideo lub audio, aby odtwarzać strumień lokalnie.
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);
}
}
Kod HTML potrzebny w typowym elemencie wideo używanym w kodzie getUserMedia() będzie
zwykle mają atrybuty autoplay i playsinline. autoplay
spowoduje automatyczne odtwarzanie nowych strumieni przypisanych do elementu.
Atrybut playsinline umożliwia odtwarzanie filmu w tekście, a nie tylko w całości
ekranu w niektórych przeglądarkach mobilnych. Zalecane jest też użycie
controls="false" w przypadku transmisji na żywo, chyba że użytkownik powinien mieć możliwość wstrzymania
.
<html>
<head><title>Local video playback</title></head>
<body>
<video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>