record audio from user and save to server

前端 未结 3 1174
心在旅途
心在旅途 2020-12-13 22:36

I\'m trying to record audio from a website user and save the audio to my server. Many of the posts I have studied so far have referenced Matt Diamond\'s recorderjs. I atte

相关标签:
3条回答
  • 2020-12-13 22:53

    Using XMLHttpRequest to post wav or mp3 blobs to server is simple.

    Just run this code wherever you have access to the blob element:

    var xhr=new XMLHttpRequest();
    xhr.onload=function(e) {
      if(this.readyState === 4) {
          console.log("Server returned: ",e.target.responseText);
      }
    };
    var fd=new FormData();
    fd.append("audio_data",blob, "filename");
    xhr.open("POST","upload.php",true);
    xhr.send(fd);
    

    I prefer XMLHttpRequest to $.ajax() because it does not require jQuery.

    Server-side, upload.php is as simple as:

    $input = $_FILES['audio_data']['tmp_name']; //temporary name that PHP gave to the uploaded file
    $output = $_FILES['audio_data']['name'].".wav"; //letting the client control the filename is a rather bad idea
    
    //move the file from temp name to local folder using $output name
    move_uploaded_file($input, $output)
    

    Source: https://addpipe.com/blog/using-recorder-js-to-capture-wav-audio-in-your-html5-web-site/ Live demo: https://addpipe.com/simple-recorderjs-demo/

    0 讨论(0)
  • 2020-12-13 23:01

    I figured out one solution, but would still welcome others related to recorderjs. I used MP3RecorderJS at https://github.com/icatcher-at/MP3RecorderJS. The demo html works if you change the top of the html from src="js/jquery.min.js" and src="js/mp3recorder.js" to wherever they're located in your server. For me, it is src="jquery.min.js" and src="mp3recorder.js" I also had to do the same thing to the "mp3recorder.js" file: var RECORDER_WORKER_PATH = 'js/recorderWorker.js'; var ENCODER_WORKER_PATH = 'js/mp3Worker.js'; changed to var RECORDER_WORKER_PATH = 'recorderWorker.js'; var ENCODER_WORKER_PATH = 'mp3Worker.js';

    The program is set up to record both mp3 and wav. I wanted wav, so I made a few more adjustments to the html file. At line 55 you'll find:

    recorderObject.exportMP3(function(base64_mp3_data) {
          var url = 'data:audio/mp3;base64,' + base64_mp3_data;
          var au  = document.createElement('audio'); 
    

    I changed that to:

    recorderObject.exportWAV(function(base64_wav_data) {
          var url = 'data:audio/wav;base64,' + base64_wav_data;
          var au  = document.createElement('audio');   
    

    The demo appends a new player each time you record. To prevent this, I deleted (commented out) the $recorder.append(au); part, made a new div to store the audio player, and then I clear that div each time, before the audio player is created. To upload to my server, I used a technique I learned from uploading images to a server save canvas image to server Basically, the "url" variable in line 56 was what I needed, but couldn't figure out how to put it in a universal variable to use by another function. So, I made a hidden div and made the contents of it equal to "url". I then referenced that div in a new function called "upload". I then used a php file called "uploadWav.php". I still have to figure out a way to activate and deactivate the upload button to prevent the user from uploading a blank file before recording, but that's another issue. Here's the final html and php that worked for me:

    <!DOCTYPE html>
    <html>
      <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">
        <title>MP3 Recorder test</title>
      </head>
      <body id="index" onload="">
    
        <script type="text/javascript" src="jquery.min.js"></script>
        <script type="text/javascript" src="mp3recorder.js"></script>
        <script type="text/javascript">
        var audio_context;
    
        function __log(e, data) {
          log.innerHTML += "\n" + e + " " + (data || '');
        }
    
        $(function() {
    
          try {
        // webkit shim
        window.AudioContext = window.AudioContext || window.webkitAudioContext;
        navigator.getUserMedia = ( navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia ||
                         navigator.msGetUserMedia);
        window.URL = window.URL || window.webkitURL;
    
        var audio_context = new AudioContext;
        __log('Audio context set up.');
        __log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not  present!'));
      } catch (e) {
        alert('No web audio support in this browser!');
      }
    
      $('.recorder .start').on('click', function() {
        $this = $(this);
        $recorder = $this.parent();
    
        navigator.getUserMedia({audio: true}, function(stream) {
          var recorderObject = new MP3Recorder(audio_context, stream, { statusContainer:  $recorder.find('.status'), statusMethod: 'replace' });
          $recorder.data('recorderObject', recorderObject);
    
          recorderObject.start();
        }, function(e) { });
      });
    
      $('.recorder .stop').on('click', function() {
        $this = $(this);
        $recorder = $this.parent();
    
        recorderObject = $recorder.data('recorderObject');
        recorderObject.stop();
    
        recorderObject.exportWAV(function(base64_wav_data) {
          var url = 'data:audio/wav;base64,' + base64_wav_data;
          var au  = document.createElement('audio');
    
          document.getElementById("playerContainer").innerHTML = "";
          //console.log(url)
    
          var duc = document.getElementById("dataUrlcontainer");
          duc.innerHTML = url;
    
          au.controls = true;
          au.src = url;
          //$recorder.append(au);
          $('#playerContainer').append(au);
    
          recorderObject.logStatus('');
        });
    
      });
    
      });
      </script>
    
    
     <script>
        function upload(){
    
        var dataURL = document.getElementById("dataUrlcontainer").innerHTML;
    
          $.ajax({
          type: "POST",
          url: "uploadWav.php",
          data: { 
              wavBase64: dataURL
           }
        }).done(function(o) {
          console.log('saved'); 
    
          });
    
        }    
      </script>
    
    
     <div class="recorder">
      Recorder 1
      <input type="button" class="start"  value="Record" />
      <input type="button" class="stop" value="Stop" />
      <pre class="status"></pre>
     </div>
    
     <div><button onclick="upload()">Upload</button></div>
    
     <div id="playerContainer"></div>
    
     <div id="dataUrlcontainer" hidden></div>
    
     <pre id="log"></pre>
    
     </body>
     </html>
    

    and the "uploadWav.php" file:

    <?php
    // requires php5
    define('UPLOAD_DIR', 'uploads/');
    $img = $_POST['wavBase64'];
    $img = str_replace('data:audio/wav;base64,', '', $img);
    $img = str_replace(' ', '+', $img);
    $data = base64_decode($img);
    $file = UPLOAD_DIR . uniqid() . '.wav';
    $success = file_put_contents($file, $data);
    print $success ? $file : 'Unable to save the file.';
    ?> 
    
    0 讨论(0)
  • 2020-12-13 23:04
    //**Server Side Code**
    package myPack;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.codec.binary.Base64;
    
    @WebServlet("/MyServlet")
    @MultipartConfig
    public class MyServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;
    
        public MyServlet() {
            super();
        }
    
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
        }
    
        protected void doPost(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
            try {
                String name = request.getParameter("fname");
                String url = request.getParameter("myUrl");
                url = url.replace("data:audio/wav;base64,", "");
                url = url.replace(" ", "+");
                byte[] bytes = url.getBytes();
                byte[] valueDecoded = Base64.decodeBase64(bytes);
                FileOutputStream os = new FileOutputStream(new File("D://" + name
                        + ".wav"));
                os.write(valueDecoded);
                os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    }
    
    **Client Side Code**
    
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>MP3 Recorder test</title>
    </head>
    <body id="index" onload="">
    
        <script type="text/javascript" src="js/jquery.min.js"></script>
        <script type="text/javascript" src="js/recorder.js"></script>
        <script type="text/javascript">
        var audio_context;
    
        function __log(e, data) {
          log.innerHTML += "\n" + e + " " + (data || '');
        }
    
        $(function() {
    
          try {
            // webkit shim
            window.AudioContext = window.AudioContext || window.webkitAudioContext;
            navigator.getUserMedia = ( navigator.getUserMedia ||
                             navigator.webkitGetUserMedia ||
                             navigator.mozGetUserMedia ||
                             navigator.msGetUserMedia);
            window.URL = window.URL || window.webkitURL;
    
            var audio_context = new AudioContext;
            __log('Audio context set up.');
            __log('navigator.getUserMedia ' + (navigator.getUserMedia ? 'available.' : 'not present!'));
          } catch (e) {
            alert('No web audio support in this browser!');
          }
    
          $('.recorder .start').on('click', function() {
            $this = $(this);
            $recorder = $this.parent();
    
            navigator.getUserMedia({audio: true}, function(stream) {
              var recorderObject = new MP3Recorder(audio_context, stream, { statusContainer: $recorder.find('.status'), statusMethod: 'replace' });
              $recorder.data('recorderObject', recorderObject);
    
              recorderObject.start();
            }, function(e) { });
          });
    
          $('.recorder .stop').on('click', function() {
            $this = $(this);
            $recorder = $this.parent();
    
            recorderObject = $recorder.data('recorderObject');
            recorderObject.stop();
    
            recorderObject.exportWAV(function(base64_wav_data) {
                var url = 'data:audio/wav;base64,' + base64_wav_data;
                var au  = document.createElement('audio'); 
                document.getElementById("playerContainer").innerHTML = "";
                //console.log(url)
    
                var duc = document.getElementById("dataUrlcontainer");
                duc.innerHTML = url;
    
                au.controls = true;
                au.src = url;
                //$recorder.append(au);
                $('#playerContainer').append(au);
    
                var fd = new FormData();
                fd.append('fname', 'test.wav');
                fd.append('myUrl', duc.innerHTML);
             $.ajax({
                  type: "POST",
                  url: "/audioPart2/MyServlet",
                  data: fd,
                  processData: false,
                  contentType: false
                });
              recorderObject.logStatus('');
            });
    
          });
    
        });
        </script>
    
        <div class="recorder">
            Recorder 1 <input type="button" class="start" value="Record" /> <input
                type="button" class="stop" value="Stop" />
            <div id="playerContainer"></div>
            <div id="dataUrlcontainer" hidden></div>
            <pre class="status"></pre>
        </div>
    
    <!--    <div class="recorder"> -->
    <!--        Recorder 2 <input type="button" class="start" value="Record" /> <input -->
    <!--            type="button" class="stop" value="Stop" /> -->
    <!--        <pre class="status"></pre> -->
    <!--    </div> -->
    
        <pre id="log"></pre>
    </body>
    </html>
    
    **// Required JS 
    1)jquery.min.js
    2) recorder.js**
    
    
    **recorder.js is below**
    (function(window){
    
      var RECORDER_WORKER_PATH  = 'js/recorderWorker.js';
      var ENCODER_WORKER_PATH   = 'js/mp3Worker.js';
    
    
      var MP3Recorder = function(context, stream, cfg) {
        var config      = cfg || { statusContainer: null, statusMethod: 'append' }
    
        var bufferLen   = 4096;
        var recording   = false;
    
        this.source     = context.createMediaStreamSource(stream);
        this.node       = (context.createScriptProcessor || context.createJavaScriptNode).call(context, bufferLen, 1, 1);
    
        var recorderWorker  = new Worker(RECORDER_WORKER_PATH);
        var encoderWorker   = new Worker(ENCODER_WORKER_PATH);
        var exportCallback;
    
    
        // initialize the Recorder Worker
        recorderWorker.postMessage({ cmd: 'init', sampleRate: context.sampleRate });
    
        // the recording loop
        this.node.onaudioprocess = function(e) {
          if(!recording) return;
          recorderWorker.postMessage({ cmd: 'record', buffer: e.inputBuffer.getChannelData(0) });
        }
    
    
        this.start = function() {
          recording = true;
          this.logStatus('recording...');
        }
        this.stop = function() {
          recording = false;
          this.logStatus('stopping...');
        }
        this.destroy  = function() { recorderWorker.postMessage({ cmd: 'destroy' }); }
    
        this.logStatus = function(status) {
          if(config.statusContainer) {
            if(config.statusMethod == 'append') {
              config.statusContainer.text(config.statusContainer.text + "\n" + status);
            } else {
              config.statusContainer.text(status);
            }
          }
        }
    
        this.exportBlob = function(cb) {
          exportCallback = cb;
          if (!exportCallback) throw new Error('Callback not set');
          recorderWorker.postMessage({ cmd: 'exportBlob' });
        }
    
        this.exportWAV = function(cb) {
          // export the blob from the worker
          this.exportBlob(function(blob) {
            var fileReader = new FileReader();
    
            // read the blob as array buffer and convert it
            // to a base64 encoded WAV buffer
            fileReader.addEventListener("loadend", function() {
              var resultBuffer = new Uint8Array(this.result);
              cb(encode64(resultBuffer));
            });
            fileReader.readAsArrayBuffer(blob);
          });
        }
    
        this.exportMP3 = function(cb) {
          this.logStatus('converting...');
    
          // export the blob from the worker
          this.exportBlob(function(blob) {
            var fileReader = new FileReader();
    
            fileReader.addEventListener("loadend", function() {
              var wavBuffer = new Uint8Array(this.result);
              var wavData = parseWav(wavBuffer);
    
              encoderWorker.addEventListener('message', function(e) {
                if (e.data.cmd == 'data') {
                  cb(encode64(e.data.buffer));
                }
              });
    
              encoderWorker.postMessage({ cmd: 'init', config: { mode: 3, channels: 1, samplerate: wavData.sampleRate, bitrate: wavData.bitsPerSample } });
              encoderWorker.postMessage({ cmd: 'encode', buf: Uint8ArrayToFloat32Array(wavData.samples) });
              encoderWorker.postMessage({ cmd: 'finish' });
            });
    
            fileReader.readAsArrayBuffer(blob);
          });
        }
    
    
    
    
        // event listener for return values of the recorderWorker
        recorderWorker.addEventListener('message', function(e) {
          switch(e.data.from) {
            case 'exportBlob':
              exportCallback(e.data.blob);
              break;
          };
        });
    
    
        // HELPER FUNCTIONS
    
        function encode64(buffer) {
            var binary  = '';
          var bytes   = new Uint8Array(buffer);
            var len     = bytes.byteLength;
    
            for(var i = 0; i < len; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            return window.btoa(binary);
        }
    
        function parseWav(wav) {
            function readInt(i, bytes) {
                var ret = 0, shft = 0;
    
                while(bytes) {
                    ret += wav[i] << shft; shft += 8;
                    i++; bytes--;
                }
                return ret;
            }
            if(readInt(20, 2) != 1) throw 'Invalid compression code, not PCM';
            if(readInt(22, 2) != 1) throw 'Invalid number of channels, not 1';
    
            return { sampleRate: readInt(24, 4), bitsPerSample: readInt(34, 2), samples: wav.subarray(44) };
        }
    
        function Uint8ArrayToFloat32Array(u8a){
            var f32Buffer = new Float32Array(u8a.length);
            for (var i = 0; i < u8a.length; i++) {
                var value = u8a[i<<1] + (u8a[(i<<1)+1]<<8);
                if (value >= 0x8000) value |= ~0x7FFF;
                f32Buffer[i] = value / 0x8000;
            }
            return f32Buffer;
        }
    
    
        this.source.connect(this.node);
        this.node.connect(context.destination);    // this should not be necessary
      }
    
      window.MP3Recorder = MP3Recorder;
    
    })(window);
    
    0 讨论(0)
提交回复
热议问题