Best way to send Web Audio API stream to server side Java for processing

5.5k views Asked by At

Currently I have a website that can record audio using Matt Diamond's recorder.js + getUserMedia (Web Audio API). After the client is finished recording, I am uploading the data (in .wav) via ajax post to a filesystem. Then my server side java processes the data.wav into other formats. This works fine.

However, I am concerned about performance/bandwidth issues with the ajax post and want to explore the option of streaming the data directly to the java code or filesystem. Does anybody have any suggestions how to pass this client side audio stream (opened with getUserMedia) to the server side Java? If it makes any difference, we are using spring framework.

Thank you.

EDIT:

Here is the requested code:

I added this to recorder.js

    this.upload = function () {
        var data = new FormData();
        data.append('file', blob);

        $j.ajax({
            url :  "/Your_Path/To_PHP/action/UploadAudio/",
            type: 'POST',
            data: data,
            contentType: false,
            processData: false,
            success: function(data) {
                alert("Success");
            },    
            error: function() {
                alert("uploadFail");
           }
        });
     }

And on the php code:

        if($_GET['action'] == 'UploadAudio') {
            if (!file_exists('/audioArchiveDestination/subDirectory/')) {
                mkdir('/audioArchiveDestination/subDirectory/', 0777, true);
            }
            $filePath = "/audioArchiveDestination/subDirectory/";

            $filename = $_SESSION['member_id'].'_'.time();   //Can be anything
            $fileExtension = "wav";
            $uploadSuccess = move_uploaded_file($_FILES['file']['tmp_name'], $filePath.$filename.".wav");

            if($uploadSuccess) {
                $results = json_encode(array("filename" => $filename));
                echo $results;
            }
        }
1

There are 1 answers

1
padenot On BEST ANSWER

You can try to encode the data on the client, so that the bandwidth is reduced. Additionally, you can send the data as soon as you get it. I think MediaRecorder (the standard API to encode media) is only available in Firefox at the moment, but I'm sure other browsers will implement it. In any case, here is how it goes, you could send the content of evt.data each time it's called to stream to you java app.

<audio controls></audio>
<button></button>
<script>
  var v = document.querySelector("video");
  var b = document.querySelector("button");

  window.navigator.mozGetUserMedia({audio:true}, function(stream) {
    v.mozSrcObject = stream;
    v.play();

    var mediaRecorder = new MediaRecorder(stream);
    var chunks = [];

    b.addEventListener("click", function() {
        mediaRecorder.stop();
    });

    mediaRecorder.ondataavailable = function(evt) {
      chunks.push(evt.data);
      // or send evt.data using an XMLHttpRequest to the server
    };

    mediaRecorder.onerror = function(evt) {
      console.log('onerror fired');
    };

    mediaRecorder.onstop = function(evt) {
      console.log('onstop fired');
      // make a blob out of all the chunks
      var blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
      // allow the user to download the opus file
      window.location.href = URL.createObjectURL(blob);
    };

    mediaRecorder.onwarning = function(evt) {
      console.log('onwarning fired');
    };

    v.addEventListener("loadedmetadata", function() {
      mediaRecorder.start();  
      v.play();
    });

    v.addEventListener("ended", function() {
      mediaRecorder.stop();
      mediaRecorder.requestData();
    });
  }, function() {
    alert("gUM failure")
  });
</script>