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 audio, dan atribut capture
yang menunjukkan bahwa kita ingin mendapatkannya langsung dari mikrofon.
<input type="file" accept="audio/*" capture />
Metode ini berfungsi di semua platform. Di desktop, pengguna akan diminta untuk
mengupload file dari sistem file (mengabaikan atribut capture
). Di Safari
pada iOS, aplikasi ini akan membuka aplikasi mikrofon, yang memungkinkan Anda merekam audio, lalu
mengirimnya kembali ke halaman web. Di Android, aplikasi ini akan memberi pengguna
pilihan aplikasi yang akan digunakan untuk merekam audio sebelum mengirimnya kembali ke halaman
web.
Setelah pengguna menyelesaikan perekaman dan kembali ke situs, Anda
perlu mendapatkan data file. Anda bisa mendapatkan akses cepat dengan
melampirkan peristiwa onchange
ke elemen input, lalu membaca
properti files
objek peristiwa.
<input type="file" accept="audio/*" capture id="recorder" />
<audio id="player" controls></audio>
<script>
const recorder = document.getElementById('recorder');
const player = document.getElementById('player');
recorder.addEventListener('change', function (e) {
const file = e.target.files[0];
const url = URL.createObjectURL(file);
// Do something with the audio file.
player.src = url;
});
</script>
</audio>
Setelah Anda memiliki akses ke file tersebut, Anda dapat melakukan apa saja yang diinginkan padanya. Misalnya, Anda dapat:
- Melampirkannya langsung ke elemen
<audio>
sehingga Anda dapat memainkannya - Mendownloadnya ke perangkat pengguna
- Upload ke server dengan melampirkan ke
XMLHttpRequest
- Meneruskannya melalui Web Audio API dan menerapkan filter padanya
Meskipun metode elemen input untuk mendapatkan akses ke data audio ada di mana-mana, metode ini adalah opsi yang paling tidak menarik. Kami benar-benar ingin mendapatkan akses ke mikrofon dan memberikan pengalaman yang baik secara langsung di halaman.
Mengakses mikrofon secara interaktif
Browser modern dapat memiliki jalur langsung ke mikrofon yang memungkinkan kita untuk membangun pengalaman yang sepenuhnya terintegrasi dengan halaman web dan pengguna tidak akan pernah meninggalkan browser.
Memperoleh akses ke mikrofon
Kita dapat mengakses Mikrofon secara langsung dengan 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 <audio>
, melampirkannya ke streaming
WebRTC, melampirkannya ke AudioContext
Web Audio, atau menyimpannya menggunakan MediaRecorder
API.
Untuk mendapatkan data dari mikrofon, kita cukup menetapkan audio: true
dalam objek
batasan yang diteruskan ke getUserMedia()
API.
<audio id="player" controls></audio>
<script>
const player = document.getElementById('player');
const handleSuccess = function (stream) {
if (window.URL) {
player.srcObject = stream;
} else {
player.src = stream;
}
};
navigator.mediaDevices
.getUserMedia({audio: true, video: false})
.then(handleSuccess);
</script>
Jika ingin memilih mikrofon tertentu, Anda dapat menghitung mikrofon yang tersedia terlebih dahulu.
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices = devices.filter((d) => d.kind === 'audioinput');
});
Kemudian, Anda dapat meneruskan deviceId
yang ingin digunakan saat memanggil getUserMedia
.
navigator.mediaDevices.getUserMedia({
audio: {
deviceId: devices[0].deviceId,
},
});
Dengan sendirinya, hal ini tidak berguna. Yang bisa kita lakukan cuma mengambil data audio dan memutarnya.
Mengakses data mentah dari mikrofon
Untuk mengakses data mentah dari mikrofon, kita harus mengambil aliran yang dibuat oleh
getUserMedia()
, lalu menggunakan Web Audio API untuk memproses data. Web Audio API adalah API sederhana yang mengambil sumber input dan menghubungkan sumber tersebut ke node yang dapat memproses data audio (menyesuaikan Gain, dll.) dan akhirnya ke speaker sehingga pengguna dapat mendengarnya.
Salah satu node yang dapat Anda hubungkan adalah AudioWorkletNode
. Node ini memberi
Anda kemampuan tingkat rendah untuk pemrosesan audio kustom. Pemrosesan
audio yang sebenarnya terjadi di metode callback process()
di AudioWorkletProcessor
.
Panggil fungsi ini untuk memasukkan input dan parameter serta mengambil output.
Lihat Enter Audio Worklet untuk mempelajari lebih lanjut.
<script>
const handleSuccess = async function(stream) {
const context = new AudioContext();
const source = context.createMediaStreamSource(stream);
await context.audioWorklet.addModule("processor.js");
const worklet = new AudioWorkletNode(context, "worklet-processor");
source.connect(worklet);
worklet.connect(context.destination);
};
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
.then(handleSuccess);
</script>
// processor.js
class WorkletProcessor extends AudioWorkletProcessor {
process(inputs, outputs, parameters) {
// Do something with the data, e.g. convert it to WAV
console.log(inputs);
return true;
}
}
registerProcessor("worklet-processor", WorkletProcessor);
Data yang disimpan dalam buffering adalah data mentah dari mikrofon dan Anda memiliki sejumlah opsi yang dapat Anda lakukan dengan data tersebut:
- Menguploadnya langsung ke server
- Menyimpannya secara lokal
- Konversikan ke format file khusus, seperti WAV, lalu simpan ke server atau secara lokal
Menyimpan data dari mikrofon
Cara termudah untuk menyimpan data dari mikrofon adalah menggunakan
MediaRecorder
API.
MediaRecorder
API akan mengambil streaming yang dibuat oleh getUserMedia
, lalu
secara progresif menyimpan data yang ada di streaming ke tujuan
yang Anda pilih.
<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
const downloadLink = document.getElementById('download');
const stopButton = document.getElementById('stop');
const handleSuccess = function(stream) {
const options = {mimeType: 'audio/webm'};
const recordedChunks = [];
const mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.addEventListener('dataavailable', function(e) {
if (e.data.size > 0) recordedChunks.push(e.data);
});
mediaRecorder.addEventListener('stop', function() {
downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
downloadLink.download = 'acetest.wav';
});
stopButton.addEventListener('click', function() {
mediaRecorder.stop();
});
mediaRecorder.start();
};
navigator.mediaDevices.getUserMedia({ audio: true, video: false })
.then(handleSuccess);
</script>
Dalam kasus ini, kita menyimpan data secara langsung ke dalam array yang nantinya dapat kita ubah
menjadi Blob
, yang kemudian dapat digunakan untuk menyimpan data ke Server Web atau langsung
ke penyimpanan di perangkat pengguna.
Meminta izin untuk menggunakan mikrofon secara bertanggung jawab
Jika pengguna belum memberi situs Anda akses ke mikrofon, begitu Anda memanggil getUserMedia
, browser akan meminta pengguna untuk memberikan izin situs Anda ke mikrofon.
Pengguna tidak suka dimintai akses ke alat pribadi di komputer atau perangkat mereka dan sering kali mereka memblokir permintaan itu, atau mengabaikannya jika tidak memahami konteks permintaan tersebut. Praktik terbaiknya adalah hanya meminta akses mikrofon saat pertama kali diperlukan. Setelah pengguna memberikan akses, mereka tidak akan diminta lagi, tetapi jika mereka menolak akses, Anda tidak dapat meminta izin pengguna lagi.
Gunakan Permission API untuk memeriksa apakah Anda sudah memiliki akses
getUserMedia
API tidak memberi tahu apakah Anda sudah
memiliki akses ke mikrofon. Hal ini menimbulkan masalah pada Anda, untuk memberikan UI yang bagus
agar pengguna memberi Anda akses ke mikrofon, Anda harus meminta
akses ke mikrofon.
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 membuat kueri apakah Anda memiliki akses ke mikrofon pengguna, Anda dapat meneruskan
{name: 'microphone'}
ke dalam metode kueri dan metode ini akan menampilkan:
granted
— sebelumnya pengguna telah memberikan akses ke mikrofon;prompt
— pengguna belum memberi Anda akses dan akan diminta saat Anda memanggilgetUserMedia
;denied
— sistem atau pengguna secara eksplisit telah memblokir akses ke mikrofon 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: 'microphone'}).then(function (result) {
if (result.state == 'granted') {
} else if (result.state == 'prompt') {
} else if (result.state == 'denied') {
}
result.onchange = function () {};
});