Molti browser ora hanno la possibilità di accedere all'input video e audio dell'utente. Tuttavia, a seconda del browser, potrebbe trattarsi di un'esperienza dinamica e in linea completa o potrebbe essere delegata a un'altra app sul dispositivo dell'utente.
Inizia in modo semplice e graduale
Il modo più semplice è chiedere all'utente un file preregistrato. A tale scopo, crea un semplice elemento di input file e aggiungi un filtro accept
che indichi che puoi accettare solo file audio e un attributo capture
che indichi che vuoi acquisire l'audio direttamente dal microfono.
<input type="file" accept="audio/*" capture />
Questo metodo funziona su tutte le piattaforme. Sul computer, verrà chiesto all'utente di caricare un file dal file system (ignorando l'attributo capture
). In Safari su iOS, si aprirà l'app del microfono, che ti consente di registrare l'audio e poi di inviarlo di nuovo alla pagina web. Su Android, l'utente potrà scegliere l'app in cui registrare l'audio prima di inviarlo di nuovo alla pagina web.
Una volta che l'utente ha completato la registrazione ed è tornato sul sito web, devi recuperare in qualche modo i dati del file. Puoi accedere rapidamente collegando un evento onchange
all'elemento di input e leggendo la proprietà files
dell'oggetto evento.
<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>
Una volta ottenuto l'accesso al file, puoi utilizzarlo come preferisci. Ad esempio, puoi:
- Collegalo direttamente a un elemento
<audio>
per poterlo riprodurre - Scaricalo sul dispositivo dell'utente
- Caricalo su un server collegandolo a un
XMLHttpRequest
- Trasmetterlo all'API Web Audio e applicare filtri
Sebbene l'utilizzo del metodo dell'elemento input per accedere ai dati audio sia molto diffuso, è l'opzione meno interessante. Vogliamo davvero accedere al microfono e offrire un'esperienza piacevole direttamente nella pagina.
Accedere al microfono in modo interattivo
I browser moderni possono avere un canale diretto con il microfono, il che ci consente di creare esperienze completamente integrate con la pagina web e l'utente non dovrà mai uscire dal browser.
Acquisire l'accesso al microfono
Possiamo accedere direttamente al microfono utilizzando un'API nella specifica WebRTC chiamata getUserMedia()
. getUserMedia()
chiederà all'utente di accedere ai microfoni e alle videocamere collegati.
In caso di esito positivo, l'API restituirà un Stream
contenente i dati della videocamera o del microfono, che potremo poi collegare a un elemento <audio>
, a uno stream WebRTC, a un AudioContext
Web Audio o salvarlo utilizzando l'API MediaRecorder
.
Per ottenere i dati dal microfono, basta impostare audio: true
nell'oggetto vincoli passato all'API getUserMedia()
.
<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>
Se vuoi scegliere un microfono specifico, puoi prima elencare i microfoni disponibili.
navigator.mediaDevices.enumerateDevices().then((devices) => {
devices = devices.filter((d) => d.kind === 'audioinput');
});
Puoi quindi passare il deviceId
che vuoi utilizzare quando chiami getUserMedia
.
navigator.mediaDevices.getUserMedia({
audio: {
deviceId: devices[0].deviceId,
},
});
Da solo, non è molto utile. Tutto ciò che possiamo fare è prendere i dati audio e riprodurli.
Accedere ai dati non elaborati del microfono
Per accedere ai dati non elaborati del microfono, dobbiamo prendere lo stream creato da
getUserMedia()
e poi utilizzare l'API Web Audio per elaborare i dati. L'API Web Audio è un'API semplice che prende le sorgenti di input e le collega a nodi che possono elaborare i dati audio (regolare il guadagno e così via) e infine a uno speaker in modo che l'utente possa sentirli.
Uno dei nodi che puoi collegare è un AudioWorkletNode
. Questo nodo offre la funzionalità di basso livello per l'elaborazione audio personalizzata. L'elaborazione effettiva dell'audio avviene nel metodo di callback process()
in AudioWorkletProcessor
.
Chiama questa funzione per fornire input e parametri e recuperare le uscite.
Per saperne di più, consulta Enter Audio Worklet.
<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);
I dati memorizzati nei buffer sono i dati non elaborati del microfono e hai a disposizione diverse opzioni per utilizzarli:
- Carica direttamente sul server
- Memorizzarli localmente
- Convertilo in un formato file dedicato, ad esempio WAV, e salvalo sui tuoi server o localmente
Salvare i dati dal microfono
Il modo più semplice per salvare i dati dal microfono è utilizzare l'API MediaRecorder
.
L'API MediaRecorder
acquisirà lo stream creato da getUserMedia
e poi salverà progressivamente i dati dello stream nella destinazione che preferisci.
<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>
Nel nostro caso, salviamo i dati direttamente in un array che in un secondo momento possiamo trasformare in un Blob
, che può essere utilizzato per salvare i dati sul nostro server web o direttamente nello spazio di archiviazione sul dispositivo dell'utente.
Chiedere l'autorizzazione per utilizzare il microfono in modo responsabile
Se l'utente non ha mai concesso al tuo sito l'accesso al microfono, nel momento in cui chiami getUserMedia
, il browser chiederà all'utente di
concedere al tuo sito l'autorizzazione per il microfono.
Gli utenti detestano che venga chiesto loro di accedere a dispositivi potenti sulla propria macchina e spesso bloccano la richiesta o la ignorano se non comprendono il contesto in cui è stata creata. È buona prassi chiedere di accedere al microfono solo la prima volta che è necessario. Una volta che l'utente ha concesso l'accesso, non gli verrà chiesto di nuovo, ma se rifiuta l'accesso, non potrai chiedergli di nuovo l'autorizzazione.
Utilizza l'API Permissions per verificare se disponi già dell'accesso
L'API getUserMedia
non ti informa se hai già accesso al microfono. Questo presenta un problema: per fornire un'interfaccia utente piacevole e convincere l'utente a concederti l'accesso al microfono, devi chiedere di poter accedere al microfono.
Questo problema può essere risolto in alcuni browser utilizzando l'API Permission. L'API
navigator.permission
consente di eseguire query sullo stato della possibilità di
accedere ad API specifiche senza dover richiedere nuovamente l'autorizzazione.
Per verificare se hai accesso al microfono dell'utente, puoi passare
{name: 'microphone'}
al metodo di query, che restituirà:
granted
: l'utente ti ha già concesso l'accesso al microfono.prompt
: l'utente non ti ha concesso l'accesso e gli verrà chiesto di farlo quando chiameraigetUserMedia
.denied
: il sistema o l'utente ha bloccato esplicitamente l'accesso al microfono e non potrai accedervi.
Ora puoi verificare rapidamente se devi modificare l'interfaccia utente per adattarla alle azioni che l'utente deve intraprendere.
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 () {};
});