Kehadiran HTML5 memperkenalkan API dengan akses ke peranti keras perangkat, termasuk API MediaDevices. API ini memberikan akses ke perangkat masukan media seperti audio dan video.
Dengan bantuan API ini, pengembang dapat mengakses perangkat audio dan video untuk mengalirkan dan menampilkan umpan video langsung di peramban. Dalam tutorial ini, Anda akan mengakses umpan video dari perangkat pengguna dan menampilkannya di peramban menggunakan metode getUserMedia
.
API getUserMedia
memanfaatkan perangkat masukan media untuk menghasilkan MediaStream. MediaStream ini berisi jenis media yang diminta, baik audio atau video. Menggunakan aliran yang dikembalikan dari API, umpan video dapat ditampilkan di peramban, yang berguna untuk komunikasi waktu nyata di peramban.
Ketika digunakan bersama API Rekaman MediaStream, Anda dapat merekam dan menyimpan data media yang ditangkap di peramban. API ini hanya bekerja di asal yang aman seperti API lainnya yang baru diperkenalkan, tetapi API ini juga bekerja di localhost
dan URL berkas.
Tutorial ini pertama-tama akan menjelaskan konsep dan mendemonstrasikan contoh dengan Codepen. Di langkah terakhir, Anda akan menciptakan umpan video yang berfungsi untuk peramban.
Pertama-tama, Anda akan melihat cara memeriksa apakah peramban pengguna mendukung API mediaDevices
. API ini ada di dalam antarmuka navigator dan berisi keadaan dan identitas saat ini dari agen pengguna. Pemeriksaan dilakukan dengan kode berikut yang dapat ditempelkan ke Codepen:
if ('mediaDevices' in navigator && 'getUserMedia' in navigator.mediaDevices) {
console.log("Let's get this party started")
}
Pertama-tama, ini memeriksa apakah API mediaDevices
ada di dalam navigator
, lalu memeriksa apakah API getUserMedia
tersedia di dalam mediaDevices
. Jika ini menampilkan true
, Anda dapat memulai.
Setelah mengonfirmasi dukungan peramban untuk getUserMedia
, Anda perlu meminta izin untuk menggunakan perangkat masukan media pada agen pengguna. Biasanya, setelah pengguna memberikan izin, Promise
diberikan yang terselesaikan menjadi aliran media. Promise
ini tidak diberikan ketika izin ditolak oleh pengguna, yang memblokir akses ke perangkat ini.
Tempelkan baris berikut ke Codepen untuk meminta izin:
navigator.mediaDevices.getUserMedia({video: true})
Objek yang diberikan sebagai argumen untuk metode getUserMedia
disebut constraints
. Ini menentukan perangkat masukan media yang Anda minta izinnya untuk diakses. Misalnya, jika objek berisi audio: true
, pengguna akan diminta memberikan akses ke perangkat masukan audio.
Bagian ini akan membahas tentang konsep umum dari constraints
. Objek constraints
adalah suatu objek MediaStreamConstraints
yang menentukan jenis media yang diminta dan persyaratan dari setiap jenis media. Anda dapat menentukan persyaratan untuk aliran yang diminta menggunakan objek constraints
, seperti resolusi dari aliran yang digunakan (front
, back
).
Anda harus menentukan baik audio
atau video
saat membuat permintaan. NotFoundError
akan dihasilkan jika jenis media yang diminta tidak dapat ditemukan di peramban pengguna.
Jika Anda berniat meminta aliran video dari resolusi 1280 x 720
, Anda dapat memperbarui objek constraints
agar terlihat seperti ini:
{
video: {
width: 1280,
height: 720,
}
}
Dengan pembaruan ini, peramban akan mencoba mencocokkan pengaturan kualitas yang ditentukan untuk aliran tersebut. Jika perangkat video tidak dapat memberikan resolusi ini, peramban akan memberikan resolusi lain yang tersedia.
Untuk memastikan peramban memberikan resolusi yang tidak lebih rendah dari yang disediakan sebelumnya, Anda harus memastikan untuk menggunakan properti min
. Berikut ini adalah cara Anda dapat memperbarui objek constraints
untuk menyertakan properti min
:
{
video: {
width: {
min: 1280,
},
height: {
min: 720,
}
}
}
Ini akan memastikan bahwa resolusi aliran tersebut setidaknya akan sebesar 1280 x 720
. Jika persyaratan minimum ini tidak dapat terpenuhi, promise akan ditolak dengan OverconstrainedError
.
Dalam beberapa kasus, Anda mungkin khawatir tentang menyimpan data dan perlu membuat aliran tidak melampaui resolusi yang ditetapkan. Ini dapat menjadi berguna ketika pengguna berada dalam paket yang terbatas. Untuk mengaktifkan fungsionalitas ini, perbarui objek constraints untuk memuat bidang max
:
{
video: {
width: {
min: 1280,
max: 1920,
},
height: {
min: 720,
max: 1080
}
}
}
Dengan pengaturan ini, peramban akan memastikan bahwa aliran yang diberikan tidak lebih kecil dari 1280 x 720
dan tidak melebihi 1920 x 1080
.
Ketentuan lain yang dapat digunakan mencakup exact
dan ideal
. Pengaturan ideal
biasanya digunakan bersama properti min
dan max
untuk menemukan kemungkinan pengaturan terbaik yang paling dekat dengan nilai ideal yang disediakan.
Anda dapat memperbarui constraints untuk menggunakan kata kunci ideal
:
{
video: {
width: {
min: 1280,
ideal: 1920,
max: 2560,
},
height: {
min: 720,
ideal: 1080,
max: 1440
}
}
}
Untuk memberi tahu peramban agar menggunakan kamera depan atau belakang (di perangkat mobil) pada perangkat, Anda dapat menentukan properti facingMode
dalam objek video
:
{
video: {
width: {
min: 1280,
ideal: 1920,
max: 2560,
},
height: {
min: 720,
ideal: 1080,
max: 1440
},
facingMode: 'user'
}
}
Pengaturan ini akan menggunakan kamera yang selalu menghadap depan di semua perangkat. Untuk menggunakan kamera belakang di perangkat mobil, Anda dapat mengubah properti facingMode
menjadi environment
.
{
video: {
...
facingMode: {
exact: 'environment'
}
}
}
enumerateDevices
Ketika metode enumerateDevices
digunakan, metode ini merespons dengan semua perangkat media masukan yang ada dan tersedia di PC pengguna.
Dengan metode ini, Anda dapat memberi pengguna opsi-opsi tentang perangkat media yang digunakan untuk mengalirkan konten audio atau konten video. Metode ini menghasilkan Promise
yang terselesaikan menjadi larik MediaDeviceInfo yang berisi informasi tentang setiap perangkat.
Contoh cara menggunakan metode ini ditampilkan dalam cuplikan kode di bawah ini:
async function getDevices() {
const devices = await navigator.mediaDevices.enumerateDevices();
}
Respons sampel untuk setiap perangkat akan terlihat seperti yang berikut:
{
deviceId: "23e77f76e308d9b56cad920fe36883f30239491b8952ae36603c650fd5d8fbgj",
groupId: "e0be8445bd846722962662d91c9eb04ia624aa42c2ca7c8e876187d1db3a3875",
kind: "audiooutput",
label: "",
}
Catatan: Label tidak akan diberikan kecuali ada aliran yang tersedia, atau jika pengguna telah memberikan izin akses perangkat.
Anda telah melewati proses meminta dan mendapatkan akses ke perangkat media, mengonfigurasi constraints untuk menyertakan resolusi yang diperlukan, dan memilih kamera yang Anda perlukan untuk merekam video.
Setelah melewati semua langkah ini, setidaknya Anda ingin melihat apakah aliran tersebut bekerja sesuai dengan pengaturan yang dikonfigurasi. Untuk memastikan ini, Anda akan menggunakan elemen <video>
untuk menampilkan aliran video di peramban.
Seperti disebutkan sebelumnya, metode getUserMedia
memberikan Promise
yang dapat diselesaikan menjadi aliran. Aliran yang dihasilkan dapat dikonversi menjadi URL objek dengan metode createObjectURL
. URL ini akan diatur sebagai sumber video.
Anda akan menciptakan demo singkat yang membiarkan pengguna memilih dari daftar perangkat video mereka yang tersedia, yang menggunakan metode enumerateDevices
.
Ini adalah metode navigator.mediaDevices
. Ini membuat daftar perangkat media yang tersedia, seperti mikrofon dan kamera. Ini memberikan Promise
yang dapat diselesaikan menjadi larik objek yang memerinci perangkat media yang tersedia.
Ciptakan berkas index.html
dan perbarui konten dengan kode di bawah ini:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="display-cover">
<video autoplay></video>
<canvas class="d-none"></canvas>
<div class="video-options">
<select name="" id="" class="custom-select">
<option value="">Select camera</option>
</select>
</div>
<img class="screenshot-image d-none" alt="">
<div class="controls">
<button class="btn btn-danger play" title="Play"><i data-feather="play-circle"></i></button>
<button class="btn btn-info pause d-none" title="Pause"><i data-feather="pause"></i></button>
<button class="btn btn-outline-success screenshot d-none" title="ScreenShot"><i data-feather="image"></i></button>
</div>
</div>
<script src="https://unpkg.com/feather-icons"></script>
<script src="script.js"></script>
</body>
</html>
Dalam cuplikan kode di atas, Anda telah menyiapkan elemen yang Anda perlukan dan beberapa kontrol untuk video. Yang juga disertakan adalah tombol untuk mengambil tangkapan layar dari umpan video saat ini.
Sekarang, mari kita hias komponen ini sedikit.
Ciptakan berkas style.css
dan salin gaya berikut ke dalamnya. Bootstrap disertakan untuk mengurangi jumlah CSS yang harus ditulis agar komponennya berjalan.
.screenshot-image {
width: 150px;
height: 90px;
border-radius: 4px;
border: 2px solid whitesmoke;
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
position: absolute;
bottom: 5px;
left: 10px;
background: white;
}
.display-cover {
display: flex;
justify-content: center;
align-items: center;
width: 70%;
margin: 5% auto;
position: relative;
}
video {
width: 100%;
background: rgba(0, 0, 0, 0.2);
}
.video-options {
position: absolute;
left: 20px;
top: 30px;
}
.controls {
position: absolute;
right: 20px;
top: 20px;
display: flex;
}
.controls > button {
width: 45px;
height: 45px;
text-align: center;
border-radius: 100%;
margin: 0 6px;
background: transparent;
}
.controls > button:hover svg {
color: white !important;
}
@media (min-width: 300px) and (max-width: 400px) {
.controls {
flex-direction: column;
}
.controls button {
margin: 5px 0 !important;
}
}
.controls > button > svg {
height: 20px;
width: 18px;
text-align: center;
margin: 0 auto;
padding: 0;
}
.controls button:nth-child(1) {
border: 2px solid #D2002E;
}
.controls button:nth-child(1) svg {
color: #D2002E;
}
.controls button:nth-child(2) {
border: 2px solid #008496;
}
.controls button:nth-child(2) svg {
color: #008496;
}
.controls button:nth-child(3) {
border: 2px solid #00B541;
}
.controls button:nth-child(3) svg {
color: #00B541;
}
.controls > button {
width: 45px;
height: 45px;
text-align: center;
border-radius: 100%;
margin: 0 6px;
background: transparent;
}
.controls > button:hover svg {
color: white;
}
Langkah selanjutnya adalah menambahkan fungsionalitas pada demo. Dengan menggunakan metode enumerateDevices
, Anda akan mendapatkan perangkat video yang tersedia dan mengaturnya sebagai opsi di dalam elemen pilihan. Ciptakan berkas bernama script.js
dan perbarui dengan cuplikan kode berikut:
feather.replace();
const controls = document.querySelector('.controls');
const cameraOptions = document.querySelector('.video-options>select');
const video = document.querySelector('video');
const canvas = document.querySelector('canvas');
const screenshotImage = document.querySelector('img');
const buttons = [...controls.querySelectorAll('button')];
let streamStarted = false;
const [play, pause, screenshot] = buttons;
const constraints = {
video: {
width: {
min: 1280,
ideal: 1920,
max: 2560,
},
height: {
min: 720,
ideal: 1080,
max: 1440
},
}
};
const getCameraSelection = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(device => device.kind === 'videoinput');
const options = videoDevices.map(videoDevice => {
return `<option value="${videoDevice.deviceId}">${videoDevice.label}</option>`;
});
cameraOptions.innerHTML = options.join('');
};
play.onclick = () => {
if (streamStarted) {
video.play();
play.classList.add('d-none');
pause.classList.remove('d-none');
return;
}
if ('mediaDevices' in navigator && navigator.mediaDevices.getUserMedia) {
const updatedConstraints = {
...constraints,
deviceId: {
exact: cameraOptions.value
}
};
startStream(updatedConstraints);
}
};
const startStream = async (constraints) => {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
handleStream(stream);
};
const handleStream = (stream) => {
video.srcObject = stream;
play.classList.add('d-none');
pause.classList.remove('d-none');
screenshot.classList.remove('d-none');
streamStarted = true;
};
getCameraSelection();
Dalam cuplikan kode di atas, ada beberapa hal yang terjadi. Mari kita uraikan:
feather.replace()
: metode ini memanggil instans feather, yang merupakan ikon yang diatur untuk pengembangan web.constraints
menyimpan konfigurasi awal untuk aliran. Ini akan diperluas untuk menyertakan perangkat media yang dipilih pengguna.getCameraSelection
: fungsi ini memanggil metode enumerateDevices
. Kemudian, Anda memfilter larik dari Promise
yang terselesaikan dan memilih perangkat masukan video. Dari hasil yang terfilter, Anda membuat <option>
untuk elemen <select>
.getUserMedia
terjadi di dalam pendengar onclick
dari tombol play
. Di sini, Anda akan memeriksa apakah metode ini didukung oleh peramban pengguna sebelum memulai aliran.startStream
yang mengambil argumen constraints
. Ini memanggil metode getUserMedia
dengan constraints
yang disediakan. handleStream
dipanggil menggunakan aliran dari Promise
yang terselesaikan. Metode ini mengatur aliran yang diberikan ke srcObject
dari elemen video.Selanjutnya, Anda akan menambahkan pendengar ke tombol kontrol pada laman untuk melakukan pause
(jeda), stop
(berhenti), dan mengambil screenshots
(tangkapan layar). Juga, Anda akan menambahkan pendengar ke elemen <select>
untuk memperbarui constraints aliran dengan perangkat video yang dipilih.
Perbarui berkas script.js
dengan kode di bawah ini:
...
cameraOptions.onchange = () => {
const updatedConstraints = {
...constraints,
deviceId: {
exact: cameraOptions.value
}
};
startStream(updatedConstraints);
};
const pauseStream = () => {
video.pause();
play.classList.remove('d-none');
pause.classList.add('d-none');
};
const doScreenshot = () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
canvas.getContext('2d').drawImage(video, 0, 0);
screenshotImage.src = canvas.toDataURL('image/webp');
screenshotImage.classList.remove('d-none');
};
pause.onclick = pauseStream;
screenshot.onclick = doScreenshot;
Sekarang, saat Anda membuka berkas index.html
di peramban, mengeklik tombol Play akan memulai aliran.
Berikut adalah demo yang lengkap:
https://codepen.io/chrisbeast/pen/ebYwpX
Tutorial ini memperkenalkan API getUserMedia
. Ini adalah tambahan yang menarik untuk HTML5 yang mempermudah proses penangkapan media di web.
API menggunakan parameter (constraints
) yang dapat digunakan untuk mengonfigurasi akses ke perangkat masukan audio dan video. Ini juga dapat digunakan untuk menentukan resolusi video yang diperlukan untuk aplikasi Anda.
Anda dapat memperpanjang demo lebih lanjut untuk memberi pengguna dengan suatu opsi untuk menyimpan tangkapan layar yang diambil, begitu juga dengan merekam dan menyimpan data video serta audio dengan bantuan dari API Rekaman MediaStream.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!