Record Audio Using the Users Microphone with HTML5

three3 picture three3 · Aug 3, 2014 · Viewed 15.4k times · Source

I am very close to having a little project of mine done, however, I have run into a slight problem I cannot seem to figure out on my own. What I ultimately want to do is record a user's voice from the users microphone, and then upload the recording to my server when they are done. I am using the code from this project: https://github.com/cwilso/AudioRecorder

It works great, but I am needing to add a feature that it does not include out of the box. I need to be able to upload the file to my server after the recording has finished. With the default code, the file can be downloaded locally to my computer, but not uploaded. So I did some research and I came across another similar project that has the uploading feature. However, the rest of the project is more buggy in my opinion. So I tried adding the "uploading code" from the following project: https://github.com/nusofthq/Recordmp3js

Javascript code:

function uploadAudio(mp3Data){
    var reader = new FileReader();
    reader.onload = function(event){
        var fd = new FormData();
        var mp3Name = encodeURIComponent('audio_recording_' + new Date().getTime() + '.mp3');
        console.log("mp3name = " + mp3Name);
        fd.append('fname', mp3Name);
        fd.append('data', event.target.result);
        $.ajax({
            type: 'POST',
            url: 'upload.php',
            data: fd,
            processData: false,
            contentType: false
        }).done(function(data) {
            //console.log(data);
            log.innerHTML += "\n" + data;
        });
    };      
    reader.readAsDataURL(mp3Data);
}

PHP code:

<?php
if(!is_dir("recordings")){
    $res = mkdir("recordings",0777); 
}

// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
$filename = urldecode($_POST['fname']);

// write the data out to the file
$fp = fopen('recordings/'.$filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>

I have tried combining this code to the project located at https://github.com/cwilso/AudioRecorder, but to no avail. What do I need to change in the Javascript code above and where do I need to place it? Any help is greatly appreciated!

PS: I know this only works in Chrome, FireFox, and Opera.

Answer

tpdietz picture tpdietz · Aug 5, 2014

I have recently implemented a similar task you are trying to achieve using similar resources. You havent indicated that you need the audio uploaded as an mp3, so I am going to just show you how to upload a wav using recorderjs, using the source found here: https://github.com/cwilso/AudioRecorder

First things to note, recorderjs stores the uncompressed wav in a var called blob. This happens on line 101 of recorder js, more specifically in this function:

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

The problem is that blob is locally declared in that function. We need to use it again, so for the sake of this example lets make it really easy to reach and make it global. So declare a variable blob outside of recorder js like so:

var blob = null;

Then modify the above function in recorderjs to store the data inside the globally declared 'blob' variable, the function should look like so:

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

Now we can use 'blob'. Now declare the following function somewhere,

function uploadAudio(){
        var fd = new FormData();
        var wavName = encodeURIComponent('audio_recording_' + new Date().getTime() + '.wav');
        console.log("wavName = " + wavName);
        fd.append('fname', wavName);
        fd.append('data', blob);
        $.ajax({
            type: 'POST',
            url: 'upload.php',
            data: fd,
            processData: false,
            contentType: false
        }).done(function(data) {
            //console.log(data);
            log.innerHTML += "\n" + data;
        });
}

Your server side code should use this:

<?php
if(!is_dir("recordings")){
    $res = mkdir("recordings",0777); 
}
move_uploaded_file($_FILES["file"]["tmp_name"],
  $res . $_FILES["file"]["fname"]);
?>

Note: $_FILES["file"]["tmp_name"] is what it sounds like. A temporary location of the file. This is done for you with the ajax call and form data.

Good luck, let me know if you run into problems.