Enregistrement audio de l'utilisateur

De nombreux navigateurs peuvent désormais accéder aux entrées vidéo et audio de l'utilisateur. Toutefois, selon le navigateur, il peut s'agir d'une expérience entièrement dynamique et intégrée, ou d'une délégation à une autre application sur l'appareil de l'utilisateur.

Commencez par des actions simples et progressives

La solution la plus simple consiste à demander à l'utilisateur de fournir un fichier préenregistré. Pour ce faire, créez un élément d'entrée de fichier simple et ajoutez un filtre accept indiquant que nous ne pouvons accepter que des fichiers audio, ainsi qu'un attribut capture indiquant que nous souhaitons l'obtenir directement à partir du micro.

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

Cette méthode fonctionne sur toutes les plates-formes. Sur un ordinateur, l'utilisateur est invité à importer un fichier à partir du système de fichiers (en ignorant l'attribut capture). Dans Safari sur iOS, l'application du micro s'ouvre, ce qui vous permet d'enregistrer du contenu audio, puis de le renvoyer à la page Web. Sur Android, l'utilisateur peut choisir l'application dans laquelle enregistrer le contenu audio avant de le renvoyer à la page Web.

Une fois que l'utilisateur a terminé l'enregistrement et qu'il est de retour sur le site Web, vous devez récupérer les données du fichier. Pour y accéder rapidement, joignez un événement onchange à l'élément de saisie, puis lisez la propriété files de l'objet de l'événement.

<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>

Une fois que vous avez accès au fichier, vous pouvez l'utiliser comme vous le souhaitez. Par exemple, vous pouvez :

  • Associez-le directement à un élément <audio> pour pouvoir le lire.
  • Télécharger l'application sur l'appareil de l'utilisateur
  • Importez-le sur un serveur en l'associant à un XMLHttpRequest.
  • Transmettez-le via l'API Web Audio et appliquez-lui des filtres.

Bien que la méthode d'accès aux données audio à l'aide de l'élément d'entrée soit omniprésente, elle est la moins attrayante. Nous souhaitons vraiment accéder au micro et offrir une expérience agréable directement sur la page.

Accéder au micro de manière interactive

Les navigateurs modernes peuvent avoir une ligne directe vers le micro, ce qui nous permet de créer des expériences entièrement intégrées à la page Web et l'utilisateur ne quittera jamais le navigateur.

Accéder au micro

Nous pouvons accéder directement au micro à l'aide d'une API de la spécification WebRTC appelée getUserMedia(). getUserMedia() demandera à l'utilisateur d'autoriser l'accès à ses micros et caméras connectés.

Si l'opération aboutit, l'API renvoie un Stream contenant les données de la caméra ou du micro. Nous pouvons ensuite l'associer à un élément <audio>, à un flux WebRTC, à un AudioContext Web Audio ou l'enregistrer à l'aide de l'API MediaRecorder.

Pour obtenir des données à partir du micro, il suffit de définir audio: true dans l'objet de contraintes transmis à l'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>

Si vous souhaitez choisir un micro particulier, vous pouvez d'abord énumérer les micros disponibles.

navigator.mediaDevices.enumerateDevices().then((devices) => {
  devices = devices.filter((d) => d.kind === 'audioinput');
});

Vous pouvez ensuite transmettre l'deviceId que vous souhaitez utiliser lorsque vous appelez getUserMedia.

navigator.mediaDevices.getUserMedia({
  audio: {
    deviceId: devices[0].deviceId,
  },
});

Cela n'est pas très utile en soi. Tout ce que nous pouvons faire est de prendre les données audio et de les lire.

Accéder aux données brutes du micro

Pour accéder aux données brutes du micro, nous devons récupérer le flux créé par getUserMedia(), puis utiliser l'API Web Audio pour traiter les données. L'API Web Audio est une API simple qui prend des sources d'entrée et les connecte à des nœuds pouvant traiter les données audio (ajuster le gain, etc.) et, en fin de compte, à un haut-parleur pour que l'utilisateur puisse l'entendre.

L'un des nœuds que vous pouvez connecter est un AudioWorkletNode. Ce nœud vous offre la possibilité de traiter l'audio de manière personnalisée à un niveau bas. Le traitement audio se produit dans la méthode de rappel process() dans AudioWorkletProcessor. Appelez cette fonction pour fournir des entrées et des paramètres, et récupérer des sorties.

Pour en savoir plus, consultez Entrer un 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);

Les données stockées dans les tampons sont les données brutes du micro. Vous pouvez les utiliser de différentes manières:

  • l'importer directement sur le serveur ;
  • Stocker les données localement
  • Convertissez-le en format de fichier dédié, tel que WAV, puis enregistrez-le sur vos serveurs ou localement.

Enregistrer les données du micro

Le moyen le plus simple d'enregistrer les données du micro consiste à utiliser l'API MediaRecorder.

L'API MediaRecorder récupère le flux créé par getUserMedia, puis enregistre progressivement les données du flux dans la destination de votre choix.

<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>

Dans notre cas, nous enregistrons les données directement dans un tableau que nous pouvons ensuite transformer en Blob, qui peut ensuite être utilisé pour enregistrer les données sur notre serveur Web ou directement dans l'espace de stockage de l'appareil de l'utilisateur.

Demander l'autorisation d'utiliser le micro de manière responsable

Si l'utilisateur n'a pas encore autorisé votre site à accéder au micro, le navigateur invite l'utilisateur à autoriser votre site à accéder au micro au moment où vous appelez getUserMedia.

Les utilisateurs détestent être invités à accéder à des appareils puissants sur leur machine. Ils bloquent souvent la requête ou l'ignorent s'ils ne comprennent pas le contexte dans lequel l'invite a été créée. Il est recommandé de ne demander l'accès au micro que lorsque cela est nécessaire. Une fois que l'utilisateur a accordé l'accès, il ne sera plus invité à le faire. Toutefois, s'il refuse l'accès, vous ne pouvez pas lui demander à nouveau l'autorisation.

Utiliser l'API des autorisations pour vérifier si vous disposez déjà d'un accès

L'API getUserMedia ne vous indique pas si vous avez déjà accès au micro. Cela pose un problème. Pour fournir une UI attrayante pour que l'utilisateur vous accorde l'accès au micro, vous devez demander l'accès au micro.

Pour résoudre ce problème dans certains navigateurs, vous pouvez utiliser l'API Permission. L'API navigator.permission vous permet d'interroger l'état de la possibilité d'accéder à des API spécifiques sans avoir à demander à nouveau.

Pour savoir si vous avez accès au micro de l'utilisateur, vous pouvez transmettre {name: 'microphone'} à la méthode de requête. Elle renverra les valeurs suivantes:

  • granted : l'utilisateur vous a déjà accordé l'accès au micro.
  • prompt : l'utilisateur ne vous a pas accordé d'accès et sera invité à le faire lorsque vous appellerez getUserMedia.
  • denied : le système ou l'utilisateur a explicitement bloqué l'accès au micro et vous ne pouvez pas y accéder.

Vous pouvez désormais vérifier rapidement si vous devez modifier votre interface utilisateur pour tenir compte des actions que l'utilisateur doit effectuer.

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

Commentaires