web-dev-qa-db-fra.com

Enregistrement audio HTML5 dans un fichier

Ce que je veux finalement, c’est enregistrer à partir du microphone de l’utilisateur et télécharger le fichier sur le serveur une fois l’opération terminée. Jusqu'à présent, j'ai réussi à créer un flux vers un élément avec le code suivant:

var audio = document.getElementById("audio_preview");

navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.getUserMedia({video: false, audio: true}, function(stream) {
   audio.src = window.URL.createObjectURL(stream);
}, onRecordFail);

var onRecordFail = function (e) {
   console.log(e);
}

Comment puis-je passer de cela à l'enregistrement dans un fichier?

115
Fibericon

Une démo d'enregistrement assez complète est disponible à l'adresse suivante: http://webaudiodemos.appspot.com/AudioRecorder/index.html

Il vous permet d'enregistrer de l'audio dans le navigateur, puis vous offre la possibilité d'exporter et de télécharger ce que vous avez enregistré.

Vous pouvez afficher la source de cette page pour rechercher des liens vers le javascript, mais pour résumer, il existe un objet Recorder contenant une méthode exportWAV et une méthode forceDownload.

97
Brad Montgomery

Le code ci-dessous est la propriété de Matt Diamond et est utilisable sous la licence MIT. Les fichiers originaux sont ici:

Enregistrez ces fichiers et utilisez

(function(window){

      var WORKER_PATH = 'recorderWorker.js';
      var Recorder = function(source, cfg){
        var config = cfg || {};
        var bufferLen = config.bufferLen || 4096;
        this.context = source.context;
        this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
        var worker = new Worker(config.workerPath || WORKER_PATH);
        worker.postMessage({
          command: 'init',
          config: {
            sampleRate: this.context.sampleRate
          }
        });
        var recording = false,
          currCallback;

        this.node.onaudioprocess = function(e){
          if (!recording) return;
          worker.postMessage({
            command: 'record',
            buffer: [
              e.inputBuffer.getChannelData(0),
              e.inputBuffer.getChannelData(1)
            ]
          });
        }

        this.configure = function(cfg){
          for (var prop in cfg){
            if (cfg.hasOwnProperty(prop)){
              config[prop] = cfg[prop];
            }
          }
        }

        this.record = function(){
       
          recording = true;
        }

        this.stop = function(){
        
          recording = false;
        }

        this.clear = function(){
          worker.postMessage({ command: 'clear' });
        }

        this.getBuffer = function(cb) {
          currCallback = cb || config.callback;
          worker.postMessage({ command: 'getBuffer' })
        }

        this.exportWAV = function(cb, type){
          currCallback = cb || config.callback;
          type = type || config.type || 'audio/wav';
          if (!currCallback) throw new Error('Callback not set');
          worker.postMessage({
            command: 'exportWAV',
            type: type
          });
        }

        worker.onmessage = function(e){
          var blob = e.data;
          currCallback(blob);
        }

        source.connect(this.node);
        this.node.connect(this.context.destination);    //this should not be necessary
      };

      Recorder.forceDownload = function(blob, filename){
        var url = (window.URL || window.webkitURL).createObjectURL(blob);
        var link = window.document.createElement('a');
        link.href = url;
        link.download = filename || 'output.wav';
        var click = document.createEvent("Event");
        click.initEvent("click", true, true);
        link.dispatchEvent(click);
      }

      window.Recorder = Recorder;

    })(window);

    //ADDITIONAL JS recorderWorker.js
    var recLength = 0,
      recBuffersL = [],
      recBuffersR = [],
      sampleRate;
    this.onmessage = function(e){
      switch(e.data.command){
        case 'init':
          init(e.data.config);
          break;
        case 'record':
          record(e.data.buffer);
          break;
        case 'exportWAV':
          exportWAV(e.data.type);
          break;
        case 'getBuffer':
          getBuffer();
          break;
        case 'clear':
          clear();
          break;
      }
    };

    function init(config){
      sampleRate = config.sampleRate;
    }

    function record(inputBuffer){

      recBuffersL.Push(inputBuffer[0]);
      recBuffersR.Push(inputBuffer[1]);
      recLength += inputBuffer[0].length;
    }

    function exportWAV(type){
      var bufferL = mergeBuffers(recBuffersL, recLength);
      var bufferR = mergeBuffers(recBuffersR, recLength);
      var interleaved = interleave(bufferL, bufferR);
      var dataview = encodeWAV(interleaved);
      var audioBlob = new Blob([dataview], { type: type });

      this.postMessage(audioBlob);
    }

    function getBuffer() {
      var buffers = [];
      buffers.Push( mergeBuffers(recBuffersL, recLength) );
      buffers.Push( mergeBuffers(recBuffersR, recLength) );
      this.postMessage(buffers);
    }

    function clear(){
      recLength = 0;
      recBuffersL = [];
      recBuffersR = [];
    }

    function mergeBuffers(recBuffers, recLength){
      var result = new Float32Array(recLength);
      var offset = 0;
      for (var i = 0; i < recBuffers.length; i++){
        result.set(recBuffers[i], offset);
        offset += recBuffers[i].length;
      }
      return result;
    }

    function interleave(inputL, inputR){
      var length = inputL.length + inputR.length;
      var result = new Float32Array(length);

      var index = 0,
        inputIndex = 0;

      while (index < length){
        result[index++] = inputL[inputIndex];
        result[index++] = inputR[inputIndex];
        inputIndex++;
      }
      return result;
    }

    function floatTo16BitPCM(output, offset, input){
      for (var i = 0; i < input.length; i++, offset+=2){
        var s = Math.max(-1, Math.min(1, input[i]));
        output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
      }
    }

    function writeString(view, offset, string){
      for (var i = 0; i < string.length; i++){
        view.setUint8(offset + i, string.charCodeAt(i));
      }
    }

    function encodeWAV(samples){
      var buffer = new ArrayBuffer(44 + samples.length * 2);
      var view = new DataView(buffer);

      /* RIFF identifier */
      writeString(view, 0, 'RIFF');
      /* file length */
      view.setUint32(4, 32 + samples.length * 2, true);
      /* RIFF type */
      writeString(view, 8, 'WAVE');
      /* format chunk identifier */
      writeString(view, 12, 'fmt ');
      /* format chunk length */
      view.setUint32(16, 16, true);
      /* sample format (raw) */
      view.setUint16(20, 1, true);
      /* channel count */
      view.setUint16(22, 2, true);
      /* sample rate */
      view.setUint32(24, sampleRate, true);
      /* byte rate (sample rate * block align) */
      view.setUint32(28, sampleRate * 4, true);
      /* block align (channel count * bytes per sample) */
      view.setUint16(32, 4, true);
      /* bits per sample */
      view.setUint16(34, 16, true);
      /* data chunk identifier */
      writeString(view, 36, 'data');
      /* data chunk length */
      view.setUint32(40, samples.length * 2, true);

      floatTo16BitPCM(view, 44, samples);

      return view;
    }
<html>
        <body>
                <audio controls autoplay></audio>
                <script type="text/javascript" src="recorder.js"> </script>
                    <fieldset><legend>RECORD AUDIO</legend>
                <input onclick="startRecording()" type="button" value="start recording" />
                <input onclick="stopRecording()" type="button" value="stop recording and play" />
                    </fieldset>
                <script>
                        var onFail = function(e) {
                                console.log('Rejected!', e);
                        };

                        var onSuccess = function(s) {
                                var context = new webkitAudioContext();
                                var mediaStreamSource = context.createMediaStreamSource(s);
                                recorder = new Recorder(mediaStreamSource);
                                recorder.record();

                                // audio loopback
                                // mediaStreamSource.connect(context.destination);
                        }

                        window.URL = window.URL || window.webkitURL;
                        navigator.getUserMedia  = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

                        var recorder;
                        var audio = document.querySelector('audio');

                        function startRecording() {
                                if (navigator.getUserMedia) {
                                        navigator.getUserMedia({audio: true}, onSuccess, onFail);
                                } else {
                                        console.log('navigator.getUserMedia not present');
                                }
                        }

                        function stopRecording() {
                                recorder.stop();
                                recorder.exportWAV(function(s) {
                                
                                        audio.src = window.URL.createObjectURL(s);
                                });
                        }
                </script>
        </body>
    </html>
38
Ankit Aranya

Ceci est un simple enregistreur et éditeur de son JavaScript. Tu peux l'essayer.

https://www.danieldemmel.me/JSSoundRecorder/

Peut télécharger à partir d'ici

https://github.com/daaain/JSSoundRecorder

11
user2801382

Mettre à jour maintenant Chrome prend également en charge MediaRecorder API de v47. La même chose à faire serait de l’utiliser (deviner que la méthode d’enregistrement natif est forcément plus rapide que les contournements), l’API est vraiment facile à utiliser, et vous obtiendrez des tonnes de réponses sur la façon de télécharger un blob pour le serveur. .

Démo - fonctionnerait dans Chrome et Firefox, omis intentionnellement de pousser le blob sur le serveur ...

Code Source


Actuellement, il y a trois façons de le faire:

  1. comme wav [tout code codé côté enregistrement, non compressé], vous pouvez extraire -> Recorderjs . Problème: la taille du fichier est assez grande, plus de bande passante de téléchargement est nécessaire.
  2. comme mp3 [tout code codé côté enregistrement, compressé], vous pouvez vérifier -> mp3Recorder . Problème: personnellement, je trouve la qualité mauvaise, il y a aussi ce problème de licence.
  3. comme ogg [code client + serveur (node.js), enregistrement compressé, heures infinies d’enregistrement sans panne du navigateur], vous pouvez vérifier -> recordOpus , soit uniquement client- Côté enregistrement, ou groupement client-serveur, à vous de choisir.

    exemple d'enregistrement ogg (seulement firefox):

    var mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.start();  // to start recording.    
    ...
    mediaRecorder.stop();   // to stop recording.
    mediaRecorder.ondataavailable = function(e) {
        // do something with the data.
    }
    

    Fiddle Demo pour l'enregistrement d'un fichier ogg.

10
mido

Vous pouvez utiliser Recordmp3js à partir de GitHub pour répondre à vos besoins. Vous pouvez enregistrer à partir du microphone de l'utilisateur, puis obtenir le fichier au format MP3. Enfin, téléchargez-le sur votre serveur.

Je l'ai utilisé dans ma démo. Il existe déjà un échantillon disponible avec le code source de l'auteur à cet emplacement: https://github.com/Audior/Recordmp3js

La démo est ici: http://audior.ec/recordmp3js/

Mais ne fonctionne actuellement que sur Chrome et Firefox.

Semble travailler bien et assez simple. J'espère que cela t'aides.

5

Voici un projet gitHub qui fait exactement cela.

Il enregistre l'audio au format mp3 à partir du navigateur et l'enregistre automatiquement sur le serveur Web. https://github.com/Audior/Recordmp3js

Vous pouvez également voir une explication détaillée de la mise en œuvre: http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/

5
Remus Negrota

Diffusion audio en temps réel sans attendre la fin de l’enregistrement: https://github.com/noamtcohen/AudioStreamer

Cela permet de diffuser des données PCM en continu, mais vous pouvez modifier le code pour diffuser des fichiers mp3 ou Speex

3
noamtcohen