web-dev-qa-db-fra.com

Accéder au microphone à partir d'un navigateur - Javascript

Est-il possible d'accéder au microphone (intégré ou auxiliaire) à partir d'un navigateur en utilisant JavaScript côté client?

Idéalement, il stockerait l'audio enregistré dans le navigateur. Merci!

32
poisonlocc

Ici, nous capturons l'audio du microphone en tant que tampon de boucle d'événements de l'API Web Audio à l'aide de getUserMedia () - des extraits de domaine temporel et de domaine de fréquence de chaque tampon de boucle d'événements audio sont imprimés (visible dans la console du navigateur, appuyez simplement sur la touche F12 ou ctrl + shift + i)

<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>capture microphone audio into buffer</title>

<script type="text/javascript">


  var webaudio_tooling_obj = function () {

    var audioContext = new AudioContext();

    console.log("audio is starting up ...");

    var BUFF_SIZE = 16384;

    var audioInput = null,
        microphone_stream = null,
        gain_node = null,
        script_processor_node = null,
        script_processor_fft_node = null,
        analyserNode = null;

    if (!navigator.getUserMedia)
            navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia ||
                          navigator.mozGetUserMedia || navigator.msGetUserMedia;

    if (navigator.getUserMedia){

        navigator.getUserMedia({audio:true}, 
          function(stream) {
              start_microphone(stream);
          },
          function(e) {
            alert('Error capturing audio.');
          }
        );

    } else { alert('getUserMedia not supported in this browser.'); }

    // ---

    function show_some_data(given_typed_array, num_row_to_display, label) {

        var size_buffer = given_typed_array.length;
        var index = 0;
        var max_index = num_row_to_display;

        console.log("__________ " + label);

        for (; index < max_index && index < size_buffer; index += 1) {

            console.log(given_typed_array[index]);
        }
    }

    function process_microphone_buffer(event) { // invoked by event loop

        var i, N, inp, microphone_output_buffer;

        microphone_output_buffer = event.inputBuffer.getChannelData(0); // just mono - 1 channel for now

        // microphone_output_buffer  <-- this buffer contains current gulp of data size BUFF_SIZE

        show_some_data(microphone_output_buffer, 5, "from getChannelData");
    }

    function start_microphone(stream){

      gain_node = audioContext.createGain();
      gain_node.connect( audioContext.destination );

      microphone_stream = audioContext.createMediaStreamSource(stream);
      microphone_stream.connect(gain_node); 

      script_processor_node = audioContext.createScriptProcessor(BUFF_SIZE, 1, 1);
      script_processor_node.onaudioprocess = process_microphone_buffer;

      microphone_stream.connect(script_processor_node);

      // --- enable volume control for output speakers

      document.getElementById('volume').addEventListener('change', function() {

          var curr_volume = this.value;
          gain_node.gain.value = curr_volume;

          console.log("curr_volume ", curr_volume);
      });

      // --- setup FFT

      script_processor_fft_node = audioContext.createScriptProcessor(2048, 1, 1);
      script_processor_fft_node.connect(gain_node);

      analyserNode = audioContext.createAnalyser();
      analyserNode.smoothingTimeConstant = 0;
      analyserNode.fftSize = 2048;

      microphone_stream.connect(analyserNode);

      analyserNode.connect(script_processor_fft_node);

      script_processor_fft_node.onaudioprocess = function() {

        // get the average for the first channel
        var array = new Uint8Array(analyserNode.frequencyBinCount);
        analyserNode.getByteFrequencyData(array);

        // draw the spectrogram
        if (microphone_stream.playbackState == microphone_stream.PLAYING_STATE) {

            show_some_data(array, 5, "from fft");
        }
      };
    }

  }(); //  webaudio_tooling_obj = function()



</script>

</head>
<body>

    <p>Volume</p>
    <input id="volume" type="range" min="0" max="1" step="0.1" value="0.5"/>

</body>
</html>

Étant donné que ce code expose les données du microphone comme un tampon, vous pouvez ajouter la possibilité de diffuser à l'aide de websockets ou simplement agréger chaque tampon de boucle d'événements dans un tampon de monstre, puis télécharger le monstre dans un fichier

Notez l'appel à

    var audioContext = new AudioContext();

ce qui indique qu'il utilise Web Audio API qui est intégré dans tous les navigateurs modernes (y compris les navigateurs mobiles) pour fournir une plate-forme audio extrêmement puissante dont le fait de puiser dans le micro n'est qu'un minuscule fragment ... [~ # ~] note [~ # ~] l'utilisation du CPU augmente en raison de cette démo écrivant chaque tampon de boucle d'événement dans le journal de la console du navigateur, destiné uniquement aux tests, de sorte que l'utilisation réelle est beaucoup moins gourmande en ressources, même lorsque vous modifiez cela pour diffuser de l'audio ailleurs

Liens vers une documentation de l'API Web Audio

44
Scott Stensland

Oui, vous pouvez.

À l'aide de l'API getUserMedia(), vous pouvez capturer l'entrée audio brute de votre microphone.

https://nusofthq.com/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/

6
user2879041