Registrazione dell'audio dell'utente in corso...

Molti browser ora hanno la possibilità di accedere all'input video e audio dell'utente. Tuttavia, a seconda del browser, potrebbe essere un'esperienza completamente dinamica e in linea oppure potrebbe essere delegata a un'altra app sul dispositivo dell'utente.

Inizia in modo semplice e progressivo

La cosa più semplice da fare è semplicemente chiedere all'utente un file preregistrato. Per farlo, crea un semplice elemento di input del file e aggiungi un filtro accept che indichi che possiamo accettare solo file audio e un attributo capture che indica che possiamo riceverli direttamente dal microfono.

<input type="file" accept="audio/*" capture />

Questo metodo funziona su tutte le piattaforme. Su desktop, all'utente verrà chiesto di caricare un file dal file system (senza l'attributo capture). In Safari su iOS si apre l'app Microfono, che consente di registrare l'audio e di inviarlo alla pagina web; su Android, l'utente può scegliere quale app utilizzare per registrare l'audio prima di inviarlo alla pagina web.

Quando l'utente ha finito di registrare e torna sul sito web, devi recuperare in qualche modo i dati del file. Puoi accedere rapidamente associando un evento onchange all'elemento di input e poi 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 fare tutto ciò che vuoi. Ad esempio, puoi:

  • Collegalo direttamente a un elemento <audio> per riprodurlo
  • Scaricalo sul dispositivo dell'utente
  • Caricalo su un server collegandolo a un XMLHttpRequest
  • Passala tramite l'API Web Audio e applica i filtri.

Sebbene l'uso del metodo degli elementi di input per accedere ai dati audio sia onnipresente, è l'opzione meno accattivante. Vogliamo avere accesso al microfono e offrire un'esperienza positiva direttamente dalla pagina.

Accesso al microfono in modo interattivo

I browser moderni possono avere una linea diretta con il microfono, che ci consente di creare esperienze completamente integrate con la pagina web e l'utente non abbandonerà mai il browser.

Ottenere 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 connessi.

Se l'esito è positivo, l'API restituirà un Stream che conterrà i dati della videocamera o del microfono. In seguito, possiamo associarlo a un elemento <audio>, collegarlo a uno stream WebRTC, collegarlo a un AudioContext audio web o salvarlo utilizzando l'API MediaRecorder.

Per ottenere i dati dal microfono, è sufficiente impostare audio: true nell'oggetto vincoli che viene 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 enumerare 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,
  },
});

Di per sé, questo non è molto utile. Tutto ciò che possiamo fare è recuperare i dati audio.

Accedere ai dati non elaborati dal microfono

Per accedere ai dati non elaborati dal microfono, dobbiamo prendere lo stream creato da getUserMedia() e utilizzare l'API Web Audio per elaborare i dati. L'API Web Audio è una semplice API che prende le sorgenti di input e le connette a nodi in grado di elaborare i dati audio (regolare il guadagno e così via) e infine a un altoparlante in modo che l'utente possa ascoltarli.

Uno dei nodi che puoi connettere è un AudioWorkletNode. Questo nodo offre la funzionalità di basso livello per l'elaborazione audio personalizzata. L'effettiva elaborazione dell'audio avviene nel metodo di callback process() in AudioWorkletProcessor. Richiama questa funzione per fornire feed di input e parametri e recuperare gli output.

Per ulteriori informazioni, consulta Invio di Worklet audio.

<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 contenuti nei buffer sono i dati non elaborati provenienti dal microfono e hai diverse opzioni a disposizione per utilizzarli:

  • Caricalo direttamente sul server
  • Archiviazione locale
  • Convertilo in un formato file dedicato, come WAV, quindi salvalo sui tuoi server o localmente

Salva i dati dal microfono

Il modo più semplice per salvare i dati dal microfono è utilizzare l'API MediaRecorder.

L'API MediaRecorder acquisirà il flusso creato da getUserMedia e salva progressivamente i dati presenti nel flusso nella tua destinazione preferita.

<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, i dati vengono salvati direttamente in un array che possiamo in seguito trasformare in un Blob, che può essere quindi utilizzato per salvare i dati nel nostro server web o direttamente nello spazio di archiviazione sul dispositivo dell'utente.

Chiedere l'autorizzazione a usare il microfono in modo responsabile

Se l'utente non ha precedentemente concesso al tuo sito l'accesso al microfono, nel momento in cui chiami getUserMedia, il browser gli chiederà di concedere al tuo sito l'autorizzazione per l'utilizzo del microfono.

Gli utenti odiano ricevere la richiesta di accesso a dispositivi potenti sul proprio computer e spesso bloccheranno la richiesta o la ignoreranno se non comprendono il contesto in cui è stata creata. È buona norma chiedere l'accesso al microfono solo se necessario. Una volta che l'utente avrà concesso l'accesso, non gli verrà più chiesto di farlo. Tuttavia, se l'utente rifiuta l'accesso, non potrai chiedere di nuovo l'autorizzazione all'utente.

Utilizza l'API Permissions per verificare se hai già l'accesso

L'API getUserMedia indica se hai già accesso al microfono. Ciò presenta un problema: per fornire all'utente una buona interfaccia utente, devi chiedere l'accesso al microfono.

Questo problema può essere risolto in alcuni browser utilizzando l'API Permission. L'API navigator.permission ti consente di eseguire query sullo stato della possibilità di accedere ad API specifiche senza dover ripetere la richiesta.

Per eseguire una query se hai accesso al microfono dell'utente, puoi passare {name: 'microphone'} al metodo di query, che restituirà:

  • granted: l'utente ti ha precedentemente concesso l'accesso al microfono;
  • prompt: l'utente non ti ha concesso l'accesso e verrà visualizzato un messaggio quando chiamerai il numero getUserMedia.
  • denied: il sistema o l'utente ha bloccato esplicitamente l'accesso al microfono e non potrai accedervi.

E ora puoi verificare rapidamente se devi modificare l'interfaccia utente per adattarla alle azioni che deve eseguire.

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 () {};
});

Feedback