Banyak browser kini mampu mengakses input video dan audio dari pengguna. Namun, bergantung pada browser, hal ini bisa menjadi pengalaman inline dan dinamis penuh, atau bisa didelegasikan ke aplikasi lain pada perangkat pengguna.
Mulailah dengan sederhana dan progresif
Hal termudah untuk dilakukan adalah cukup meminta file yang sudah direkam kepada pengguna. Lakukan hal ini dengan membuat elemen input file sederhana dan menambahkan filter accept
yang menunjukkan bahwa kita hanya dapat menerima file video dan atribut capture
yang menunjukkan bahwa kita ingin mendapatkannya langsung dari kamera.
<input type="file" accept="video/*" capture />
Metode ini berfungsi di semua platform. Di desktop, ini akan meminta pengguna untuk mengupload file dari
sistem file (dengan mengabaikan atribut capture
). Di Safari di iOS, aplikasi kamera akan terbuka, sehingga Anda dapat merekam video, lalu mengirimkannya kembali ke halaman web. Di Android, pengguna dapat memilih aplikasi yang akan digunakan untuk merekam video sebelum mengirimnya kembali ke halaman web.
Banyak perangkat seluler memiliki lebih dari satu kamera. Jika memiliki preferensi, Anda dapat menetapkan atribut capture
ke user
, jika menginginkan kamera yang menghadap pengguna, atau environment
jika menginginkan
kamera yang menghadap ke luar.
<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />
Perhatikan bahwa ini hanyalah petunjuk - jika browser tidak mendukung opsi tersebut, atau jenis kamera yang Anda minta tidak tersedia, browser dapat memilih kamera lain.
Setelah pengguna selesai merekam dan kembali ke situs, Anda
harus memiliki data file. Anda bisa mendapatkan akses cepat dengan
melampirkan peristiwa onchange
ke elemen input, lalu membaca
properti files
objek peristiwa.
<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
var recorder = document.getElementById('recorder');
var player = document.getElementById('player');
recorder.addEventListener('change', function (e) {
var file = e.target.files[0];
// Do something with the video file.
player.src = URL.createObjectURL(file);
});
</script>
Setelah Anda memiliki akses ke file, Anda dapat melakukan apa pun yang Anda inginkan dengan file tersebut. Misalnya, Anda dapat:
- Melampirkannya langsung ke elemen
<video>
sehingga Anda dapat memainkannya - Mendownloadnya ke perangkat pengguna
- Menguploadnya ke server dengan melampirkan ke
XMLHttpRequest
- Menggambar bingkai ke kanvas dan menerapkan filter ke bingkai tersebut
Meskipun metode elemen input untuk mendapatkan akses ke data video ada di mana-mana, metode ini adalah opsi yang paling tidak menarik. Kami benar-benar ingin mendapatkan akses ke kamera dan memberikan pengalaman yang baik secara langsung di halaman.
Mengakses kamera secara interaktif
Browser modern dapat terhubung langsung ke kamera sehingga kita dapat membuat pengalaman yang terintegrasi sepenuhnya dengan halaman web dan pengguna tidak akan pernah meninggalkan browser.
Mendapatkan akses ke kamera
Kita dapat mengakses kamera secara langsung menggunakan API dalam spesifikasi WebRTC
yang disebut getUserMedia()
. getUserMedia()
akan meminta izin pengguna untuk
mengakses mikrofon dan kamera yang terhubung.
Jika berhasil, API akan menampilkan Stream
yang akan berisi data dari kamera atau
mikrofon, lalu kita dapat melampirkannya ke elemen <video>
, melampirkannya ke streaming
WebRTC, atau menyimpannya menggunakan MediaRecorder
API.
Untuk mendapatkan data dari kamera, kita cukup menetapkan video: true
di objek batasan yang diteruskan ke getUserMedia()
API
<video id="player" controls></video>
<script>
var player = document.getElementById('player');
var handleSuccess = function (stream) {
player.srcObject = stream;
};
navigator.mediaDevices
.getUserMedia({audio: true, video: true})
.then(handleSuccess);
</script>
Jika ingin memilih kamera tertentu, Anda dapat menghitung kamera yang tersedia terlebih dahulu.
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices = devices.filter((d) => d.kind === 'videoinput');
});
Kemudian, Anda dapat meneruskan deviceId yang ingin digunakan saat memanggil getUserMedia
.
navigator.mediaDevices.getUserMedia({
audio: true,
video: {
deviceId: devices[0].deviceId,
},
});
Dengan sendirinya, ini menjadi tidak berguna. Kita hanya bisa mengambil data video dan memutarnya.
Mengakses data mentah dari kamera
Untuk mengakses data video mentah dari kamera, Anda dapat menggambar setiap frame ke dalam <canvas>
dan
memanipulasi piksel secara langsung.
Untuk kanvas 2D, Anda dapat menggunakan metode drawImage
konteks untuk menggambar bingkai saat ini dari
elemen <video>
ke dalam kanvas.
context.drawImage(myVideoElement, 0, 0);
Dengan kanvas WebGL, Anda dapat menggunakan elemen <video>
sebagai sumber untuk tekstur.
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA,
gl.RGBA,
gl.UNSIGNED_BYTE,
myVideoElement,
);
Perhatikan bahwa dalam kedua kasus ini, frame saat ini dari video yang diputar akan digunakan. Untuk memproses beberapa frame, Anda perlu menggambar ulang video ke kanvas setiap kali diperlukan.
Anda dapat mempelajari hal ini lebih lanjut di artikel kami tentang cara menerapkan efek real-time ke gambar dan video.
Menyimpan data dari kamera
Cara termudah untuk menyimpan data dari kamera adalah menggunakan
MediaRecorder
API.
MediaRecorder
API akan mengambil streaming yang dibuat oleh getUserMedia
, lalu
secara progresif menyimpan data dari streaming ke tujuan yang Anda pilih.
<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
let shouldStop = false;
let stopped = false;
const downloadLink = document.getElementById('download');
const stopButton = document.getElementById('stop');
stopButton.addEventListener('click', function() {
shouldStop = true;
})
var handleSuccess = function(stream) {
const options = {mimeType: 'video/webm'};
const recordedChunks = [];
const mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.addEventListener('dataavailable', function(e) {
if (e.data.size > 0) {
recordedChunks.push(e.data);
}
if(shouldStop === true && stopped === false) {
mediaRecorder.stop();
stopped = true;
}
});
mediaRecorder.addEventListener('stop', function() {
downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
downloadLink.download = 'acetest.webm';
});
mediaRecorder.start();
};
navigator.mediaDevices.getUserMedia({ audio: true, video: true })
.then(handleSuccess);
</script>
Dalam kasus kita, kita menyimpan data secara langsung ke dalam array yang nantinya dapat kita ubah
menjadi Blob
yang kemudian dapat digunakan untuk disimpan ke Server Web atau langsung di
penyimpanan di perangkat pengguna.
Meminta izin untuk menggunakan kamera secara bertanggung jawab
Jika pengguna belum memberikan akses ke kamera untuk situs Anda, browser akan meminta pengguna untuk memberikan izin ke kamera untuk situs Anda begitu Anda memanggil getUserMedia
.
Pengguna tidak suka dimintai akses ke perangkat yang andal di mesin mereka dan sering kali mereka memblokir permintaan tersebut, atau akan mengabaikannya jika tidak memahami konteks dibuatnya konfirmasi tersebut. Praktik terbaiknya adalah hanya meminta akses ke kamera saat pertama kali diperlukan. Setelah pengguna memberi akses, mereka tidak akan diminta lagi. Namun, jika mereka menolak akses, Anda tidak dapat mendapatkan akses lagi untuk meminta izin pengguna.
Gunakan Permission API untuk memeriksa apakah Anda sudah memiliki akses
getUserMedia
API tidak memberi tahu apakah Anda sudah
memiliki akses ke kamera. Hal ini menimbulkan masalah. Untuk menyediakan UI yang bagus
agar pengguna memberi Anda akses ke kamera, Anda harus meminta
akses ke kamera.
Hal ini dapat diatasi di sebagian browser dengan menggunakan Permission API. navigator.permission
API memungkinkan Anda mengkueri status kemampuan untuk mengakses API tertentu tanpa harus meminta konfirmasi lagi.
Untuk mengetahui apakah Anda memiliki akses ke kamera pengguna, Anda dapat meneruskan
{name: 'camera'}
ke dalam metode kueri dan ini akan menampilkan:
granted
— pengguna sebelumnya telah memberi Anda akses ke kamera;prompt
— pengguna belum memberi Anda akses dan akan diminta saat Anda memanggilgetUserMedia
;denied
— sistem atau pengguna secara eksplisit telah memblokir akses ke kamera dan Anda tidak akan dapat mengaksesnya.
Dan Anda kini dapat memeriksa dengan cepat untuk mengetahui apakah perlu mengubah antarmuka pengguna untuk mengakomodasi tindakan yang perlu diambil pengguna.
navigator.permissions.query({name: 'camera'}).then(function (result) {
if (result.state == 'granted') {
} else if (result.state == 'prompt') {
} else if (result.state == 'denied') {
}
result.onchange = function () {};
});