Saat mengembangkan untuk web, standar WebRTC menyediakan API untuk mengakses
kamera dan mikrofon yang terhubung ke komputer atau smartphone. Perangkat ini
umumnya disebut sebagai Perangkat Media dan dapat diakses dengan JavaScript
melalui objek navigator.mediaDevices
, yang menerapkan antarmuka
MediaDevices
. Dari objek ini, kita dapat menghitung semua perangkat yang terhubung, memproses
perubahan perangkat (saat perangkat terhubung atau terputus), dan membuka perangkat
untuk mengambil Aliran Media (lihat di bawah).
Cara yang paling umum digunakan adalah melalui fungsi getUserMedia()
, yang
menampilkan promise yang akan di-resolve ke MediaStream
untuk perangkat media
yang cocok. Fungsi ini menggunakan satu objek MediaStreamConstraints
yang menentukan persyaratan yang kita miliki. Misalnya, untuk membuka
mikrofon dan kamera default, kita akan melakukan hal berikut.
Menggunakan Promise
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);
});
Menggunakan 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);
}
Panggilan ke getUserMedia()
akan memicu permintaan izin. Jika pengguna
menerima izin, promise akan diselesaikan dengan MediaStream
yang berisi
satu video dan satu trek audio. Jika izin ditolak, PermissionDeniedError
akan ditampilkan. Jika tidak ada perangkat yang cocok
yang terhubung, NotFoundError
akan ditampilkan.
Referensi API lengkap untuk antarmuka MediaDevices
tersedia di dokumen web MMD.
Membuat kueri perangkat media
Pada aplikasi yang lebih kompleks, kemungkinan besar kita ingin memeriksa semua
kamera dan mikrofon yang terhubung dan memberikan masukan yang sesuai kepada
pengguna. Tindakan ini dapat dilakukan dengan memanggil fungsi enumerateDevices()
. Tindakan ini akan menampilkan promise yang di-resolve ke array MediaDevicesInfo
yang mendeskripsikan setiap perangkat media yang diketahui. Kita dapat menggunakannya untuk menampilkan UI kepada pengguna sehingga
mereka dapat memilih UI yang mereka sukai. Setiap MediaDevicesInfo
berisi properti bernama kind
dengan nilai audioinput
, audiooutput
, atau videoinput
, yang menunjukkan jenis perangkat media tersebut.
Menggunakan Promise
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));
Menggunakan 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);
Memproses perubahan perangkat
Sebagian besar komputer mendukung penyambungan berbagai perangkat selama runtime. Hal ini dapat berupa
webcam yang terhubung melalui USB, headset Bluetooth, atau sekumpulan speaker eksternal. Untuk
mendukung hal ini dengan benar, aplikasi web harus memproses perubahan
pada perangkat media. Hal ini dapat dilakukan dengan menambahkan pemroses ke navigator.mediaDevices
untuk peristiwa 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);
});
Batasan media
Objek batasan, yang harus mengimplementasikan antarmuka MediaStreamConstraints
, yang kita teruskan sebagai parameter ke getUserMedia()
memungkinkan kita membuka
perangkat media yang cocok dengan persyaratan tertentu. Persyaratan ini dapat
ditentukan secara longgar (audio dan/atau video), atau sangat spesifik (resolusi kamera
minimum atau ID perangkat yang tepat). Sebaiknya aplikasi yang menggunakan
getUserMedia()
API terlebih dahulu memeriksa perangkat yang ada, lalu menentukan
batasan yang cocok dengan perangkat yang tepat menggunakan batasan deviceId
.
Perangkat juga akan, jika memungkinkan, dikonfigurasi sesuai dengan batasan. Kita
dapat mengaktifkan pengurangan gema pada mikrofon atau menetapkan lebar dan tinggi
tertentu pada video dari kamera.
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);
}
Dokumentasi lengkap untuk antarmuka MediaStreamConstraints
dapat ditemukan
di dokumen web
MDN.
Pemutaran lokal
Setelah perangkat media dibuka dan MediaStream
tersedia, kita
dapat menetapkannya ke elemen video atau audio untuk memutar streaming secara lokal.
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);
}
}
HTML yang diperlukan untuk elemen video standar yang digunakan dengan getUserMedia()
biasanya akan
memiliki atribut autoplay
dan playsinline
. Atribut autoplay
akan menyebabkan streaming baru yang ditetapkan ke elemen diputar secara otomatis.
Atribut playsinline
memungkinkan video diputar inline, bukan hanya di layar
penuh, di browser seluler tertentu. Sebaiknya gunakan juga
controls="false"
untuk live stream, kecuali jika pengguna dapat menjedanya.
<html>
<head><title>Local video playback</title></head>
<body>
<video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>