웹용으로 개발할 때 WebRTC 표준은 컴퓨터 또는 스마트 폰에 연결된 카메라 및 마이크에 액세스하기위한 API를 제공합니다. 이러한 장치는 일반적으로 미디어 장치라고하며 MediaDevices
인터페이스를 구현하는 navigator.mediaDevices
객체를 통해 JavaScript로 액세스 할 수 있습니다. 이 개체에서 연결된 모든 장치를 열거하고, 장치 변경 사항을 수신하고 (장치가 연결되거나 연결 해제 된 경우) 장치를 열어 미디어 스트림을 검색 할 수 있습니다 (아래 참조).
이것이 사용되는 가장 일반적인 방법은 getUserMedia()
함수를 사용하는 것입니다.이 함수는 일치하는 미디어 장치에 대해 MediaStream
되는 promise를 반환합니다. 이 함수는 요구 사항을 지정하는 단일 MediaStreamConstraints
개체를 사용합니다. 예를 들어 기본 마이크와 카메라를 간단히 열려면 다음을 수행합니다.
약속 사용
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);
});
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);
}
getUserMedia()
를 호출하면 권한 요청이 트리거됩니다. 사용자가 권한을 수락하면 비디오 1 개와 오디오 트랙 1 개가 포함 된 MediaStream
약속이 해결됩니다. 권한이 거부되면 PermissionDeniedError
가 발생합니다. 연결된 장치가없는 경우 NotFoundError
가 발생합니다.
MediaDevices
인터페이스에 대한 전체 API 참조는 MDN 웹 문서 에서 확인할 수 있습니다.
미디어 장치 쿼리
더 복잡한 애플리케이션에서는 연결된 모든 카메라와 마이크를 확인하고 사용자에게 적절한 피드백을 제공하기를 원할 것입니다. enumerateDevices()
함수를 호출하면됩니다. 이렇게하면 알려진 각 미디어 장치를 설명하는 MediaDevicesInfo
배열로 확인되는 promise가 반환됩니다. 이것을 사용하여 사용자가 선호하는 UI를 선택할 수있는 UI를 제공 할 수 있습니다. 각 MediaDevicesInfo
에는 어떤 유형의 미디어 장치인지를 나타내는 값이 audioinput
, audiooutput
또는 videoinput
인 kind
라는 속성이 포함되어 있습니다.
약속 사용
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));
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);
장치 변경 수신
대부분의 컴퓨터는 런타임 동안 다양한 장치 연결을 지원합니다. USB로 연결된 웹캠, Bluetooth 헤드셋 또는 외부 스피커 세트 일 수 있습니다. 이를 제대로 지원하려면 웹 애플리케이션이 미디어 장치의 변경 사항을 수신해야합니다. 이것은 devicechange
이벤트에 대한 navigator.mediaDevices
에 리스너를 추가하여 수행 할 수 있습니다.
// 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);
});
미디어 제약
MediaStreamConstraints
인터페이스를 구현해야하는 제약 조건 객체는 getUserMedia()
매개 변수로 전달하여 특정 요구 사항과 일치하는 미디어 장치를 열 수 있습니다. 이 요구 사항은 매우 느슨하게 정의되거나 (오디오 및 / 또는 비디오) 매우 구체적 일 수 있습니다 (최소 카메라 해상도 또는 정확한 장치 ID). getUserMedia()
API를 사용하는 애플리케이션은 먼저 기존 장치를 확인한 다음 deviceId
제약 조건을 사용하여 정확한 장치와 일치하는 제약 조건을 지정하는 것이 deviceId
. 가능한 경우 장치도 제약 조건에 따라 구성됩니다. 마이크에서 에코 제거를 활성화하거나 카메라에서 비디오의 특정 또는 최소 너비 및 높이를 설정할 수 있습니다.
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);
}
MediaStreamConstraints
인터페이스에 대한 전체 문서는 MDN 웹 문서 에서 찾을 수 있습니다.
로컬 재생
미디어 장치가 열리고 사용 가능한 MediaStream
있으면이를 비디오 또는 오디오 요소에 할당하여 스트림을 로컬로 재생할 수 있습니다.
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);
}
}
getUserMedia()
와 함께 사용되는 일반적인 동영상 요소에 필요한 HTML에는 일반적으로 autoplay
및 playsinline
속성이 있습니다. autoplay
속성은 요소에 할당 된 새 스트림이 autoplay
되도록합니다. playsinline
속성을 사용하면 특정 모바일 브라우저에서 동영상을 전체 화면으로 만 재생하는 대신 인라인으로 재생할 수 있습니다. 사용자가 일시 중지 할 수 있어야하는 경우가 아니면 실시간 스트림에 controls="false"
를 사용하는 것이 좋습니다.
<html>
<head><title>Local video playback</video></head>
<body>
<video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>