Enregistrement audio de l'utilisateur

De nombreux navigateurs ont désormais la possibilité d'accéder aux entrées audio et vidéo de l'utilisateur. Toutefois, selon le navigateur, il peut s'agir d'une expérience complète et dynamique, ou d'une délégation à une autre application sur l'appareil de l'utilisateur.

Procédez de manière simple et progressive

Le plus simple est de demander simplement à l'utilisateur un fichier préenregistré. Pour ce faire, créez un élément d'entrée de fichier simple et ajoutez un filtre accept qui indique que nous ne pouvons accepter que des fichiers audio, ainsi qu'un attribut capture qui indique que nous voulons l'obtenir directement depuis le micro.

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

Cette méthode fonctionne sur toutes les plates-formes. Sur ordinateur, l'utilisateur est invité à importer un fichier à partir du système de fichiers (en ignorant l'attribut capture). Dans Safari sur iOS, il ouvre l'application Micro, qui vous permet d'enregistrer du contenu audio, puis de le renvoyer vers la page Web. Sous Android, il permet à l'utilisateur de choisir l'application dans laquelle enregistrer l'audio avant de le renvoyer vers 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. Vous pouvez y accéder rapidement en associant un événement onchange à l'élément d'entrée, puis en lisant la propriété files de l'objet é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 le modifier comme bon vous semble. Par exemple, vous pouvez :

  • l'associer directement à un élément <audio> pour pouvoir le lire ;
  • Le télécharger sur l'appareil de l'utilisateur
  • L'importer sur un serveur en l'associant à un XMLHttpRequest
  • Transmettez-la via l'API Web Audio et appliquez-lui des filtres.

Bien que la méthode d'élément d'entrée permettant d'accéder aux données audio soit omniprésente, c'est l'option la moins attrayante. Nous voulons vraiment avoir accès au microphone et offrir une bonne expérience directement sur la page.

Accéder au micro de manière interactive

Les navigateurs récents peuvent être reliés directement au micro, ce qui nous permet de créer des expériences entièrement intégrées à la page Web, sans que l'utilisateur ne quitte le navigateur.

Accéder au micro

Nous pouvons accéder directement au micro à l'aide d'une API dans la spécification WebRTC, appelée getUserMedia(). getUserMedia() demandera à l'utilisateur d'accéder à ses micros et appareils photo connectés.

Si l'opération réussit, 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>, l'associer à un flux WebRTC, l'associer à 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 en 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 le deviceId que vous souhaitez utiliser lorsque vous appelez getUserMedia.

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

En soi, ce n’est pas très utile. Tout ce que nous pouvons faire, c’est prendre les données audio et les lire.

Accéder aux données brutes à partir du micro

Pour accéder aux données brutes du micro, nous devons prendre 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 reçoit des sources d'entrée et les connecte à des nœuds capables de traiter les données audio (ajuster le gain, etc.) et, à terme, à une enceinte afin que l'utilisateur puisse les entendre.

L'un des nœuds que vous pouvez connecter est un nœud AudioWorkletNode. Ce nœud vous offre des fonctionnalités de bas niveau pour un traitement audio personnalisé. Le traitement audio réel s'effectue dans la méthode de rappel process() dans AudioWorkletProcessor. Appelez cette fonction pour alimenter les entrées et les paramètres, et extraire les sorties.

Pour en savoir plus, consultez la section Enter Audio Worklet (Saisir un workflow 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 conservées dans les tampons sont les données brutes du micro. Vous disposez de plusieurs options pour exploiter ces données:

  • Importez-le directement sur le serveur.
  • Stockez-les localement
  • Convertissez-le dans un 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 prend le flux créé par getUserMedia, puis enregistre progressivement les données du flux à 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 le cas présent, 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 déjà autorisé votre site à accéder au micro, dès que vous appelez getUserMedia, le navigateur l'invite à autoriser votre site à utiliser le micro.

Les utilisateurs détestent être invités à accéder à des appareils puissants sur leur machine et ils bloquent fréquemment la requête, ou l'ignoreront 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 qu'en cas de besoin. Une fois que l'utilisateur a accordé l'accès, il n'est plus invité à le faire. Toutefois, s'il refuse l'accès, vous ne pouvez pas lui redemander l'autorisation.

Utilisez l'API Permissions pour vérifier si vous avez déjà accès

L'API getUserMedia ne vous indique pas si vous avez déjà accès au micro. Cela pose problème. Pour que l'interface utilisateur puisse vous inciter à vous accorder l'accès au micro, vous devez demander l'accès au micro.

Dans certains navigateurs, le problème peut être résolu à l'aide de l'API Permission. L'API navigator.permission vous permet d'interroger l'état de la capacité d'accès à des API spécifiques sans avoir à relancer la requête.

Pour demander si vous avez accès au micro de l'utilisateur, vous pouvez transmettre {name: 'microphone'} à la méthode de requête. Celle-ci renvoie alors l'un des éléments suivants:

  • granted : l'utilisateur vous a précédemment accordé l'accès au micro.
  • prompt : l'utilisateur ne vous a pas accordé l'accès et sera invité à appeler getUserMedia.
  • denied : le système ou l'utilisateur a explicitement bloqué l'accès au micro, et vous ne pourrez pas y accéder.

Vous pouvez maintenant vérifier rapidement si vous devez modifier votre interface utilisateur pour l'adapter aux 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