Kini banyak browser yang dapat mengakses input video dan audio dari pengguna. Namun, bergantung pada browser, mungkin pengalaman inline dan dinamis penuh, atau dapat didelegasikan ke aplikasi lain di perangkat pengguna.
Memulai dengan mudah dan bertahap
Hal termudah untuk dilakukan adalah cukup meminta file yang sudah direkam sebelumnya 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
). Pada Safari di iOS, aplikasi mikrofon akan terbuka, sehingga Anda dapat merekam audio, lalu mengirimkannya kembali ke halaman web. Pada Android, hal ini akan memberi pengguna pilihan aplikasi mana yang akan digunakan untuk merekam audio sebelum mengirimnya kembali ke halaman web.
Setelah pengguna selesai merekam dan kembali ke situs, Anda
harus memiliki data file. Anda bisa mendapatkan akses cepat dengan menambahkan 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 memiliki akses ke file tersebut, Anda dapat melakukan apa pun yang Anda inginkan pada file tersebut. Misalnya, Anda dapat:
- Melampirkannya langsung ke elemen
<audio>
sehingga Anda dapat memutarnya - Download aplikasi ke perangkat pengguna
- Upload ke server dengan melampirkannya ke
XMLHttpRequest
- Meneruskannya melalui Web Audio API dan menerapkan filter ke dalamnya
Meskipun penggunaan metode elemen input untuk mendapatkan akses ke data audio ada di mana-mana, metode ini adalah opsi yang paling tidak menarik. Kita benar-benar ingin mendapatkan akses ke mikrofon dan memberikan pengalaman yang baik langsung di laman.
Mengakses mikrofon secara interaktif
Browser modern dapat terhubung langsung ke mikrofon, sehingga kita dapat menciptakan pengalaman yang terintegrasi sepenuhnya dengan halaman web dan pengguna tidak akan pernah meninggalkan browser.
Mendapatkan akses ke mikrofon
Kita dapat langsung mengakses Mikrofon dengan menggunakan API di spesifikasi WebRTC
yang disebut getUserMedia()
. getUserMedia()
akan meminta 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 aliran WebRTC,
melampirkan ke Audio Web AudioContext
, 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, ini tidak berguna. Kita hanya bisa mengambil data audio dan memutarnya kembali.
Mengakses data mentah dari mikrofon
Untuk mengakses data mentah dari mikrofon, kita harus mengambil streaming yang dibuat oleh
getUserMedia()
, lalu menggunakan Web Audio API untuk memproses data tersebut. Web Audio API adalah API sederhana yang mengambil sumber input dan menghubungkan sumber tersebut ke node yang dapat memproses data audio (menyesuaikan Keuntungan, dll.) dan pada 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 Masukkan Worklet Audio 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 di buffer adalah data mentah dari mikrofon dan Anda memiliki sejumlah opsi yang dapat dilakukan 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 dengan menggunakan
MediaRecorder
API.
MediaRecorder
API akan mengambil aliran data yang dibuat oleh getUserMedia
, lalu secara progresif menyimpan data yang ada di aliran data ke tujuan yang Anda inginkan.
<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 langsung ke dalam array yang nantinya dapat diubah menjadi Blob
, yang kemudian dapat digunakan untuk menyimpan data ke Server Web atau langsung ke penyimpanan di perangkat pengguna.
Minta izin untuk menggunakan mikrofon secara bertanggung jawab
Jika pengguna belum pernah mengizinkan situs Anda mengakses mikrofon, begitu Anda memanggil getUserMedia
, browser akan meminta pengguna
untuk memberikan izin ke mikrofon kepada situs Anda.
Pengguna tidak suka dimintai akses ke perangkat canggih di komputer mereka dan sering kali mereka memblokir permintaan tersebut, atau akan mengabaikannya jika tidak memahami konteks pembuatan perintah. Sebaiknya hanya minta akses ke mikrofon saat pertama kali diperlukan. Setelah pengguna diberikan akses, mereka tidak akan diminta lagi untuk melakukannya. Namun, jika pengguna menolak akses, Anda tidak dapat meminta izin lagi kepada pengguna tersebut.
Gunakan API izin untuk memeriksa apakah Anda sudah memiliki akses
getUserMedia
API tidak memberi tahu apakah Anda sudah
memiliki akses ke mikrofon. Hal ini menimbulkan masalah. Untuk memberikan UI yang bagus
agar pengguna memberi Anda akses ke mikrofon, Anda harus meminta
akses ke mikrofon.
Hal ini dapat diatasi di beberapa browser dengan menggunakan Permission API. API
navigator.permission
memungkinkan Anda membuat kueri status kemampuan untuk
mengakses API tertentu tanpa harus meminta izin lagi.
Untuk mengkueri apakah Anda memiliki akses ke mikrofon pengguna, Anda dapat meneruskan
{name: 'microphone'}
ke dalam metode kueri dan metode ini akan menampilkan:
granted
— pengguna sebelumnya telah memberi Anda akses ke mikrofon;prompt
— pengguna belum memberi Anda akses dan akan diminta saat Anda memanggilgetUserMedia
;denied
— sistem atau pengguna telah secara eksplisit memblokir akses ke mikrofon dan Anda tidak akan bisa mendapatkan akses ke mikrofon tersebut.
Sekarang Anda dapat dengan cepat memeriksa apakah perlu mengubah antarmuka pengguna untuk mengakomodasi tindakan yang perlu dilakukan 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 () {};
});