Convert Blob URL to Base64 (or directly) and send to server

4.7k views Asked by At

I have found other posts so similar to this but nothing works - and they are fairly old so don't want to add to them.

I am using MP3LameEncorder.js with < audio > to allow the user to record audio from a mic.

Currently I get something like this: <audio id="audio" controls="" type="audio/mpeg" src="blob:https://example.com/6c2730f1-6a77-41e5-b6c7-ec9fdd25d54a"></audio>

This is a part of a multistep process, and no file has been saved yet. What I want to do is convert the blob url in the src to base64 and place it into a hidden form element. Then when they users finishes filling everything out, send the base64 data to my php file where it is then turned into a mp3 or wave file on the server and I can use it for other stuff.

Every time I try to convert the url to base64, I get: Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'

Here is what I am doing:

audioElement.src = URL.createObjectURL(encoder.finish());    
let reader = new window.FileReader(); 
reader.readAsDataURL(audioElement.src); 
reader.addEventListener("loadend", function() {
    var audioBase64 = reader.result.toString();
    let audioTurned = audioBase64.substr(audioBase64.indexOf(',')+1); 
    $("#audiofile").val(audioTurned); 
});

I'm OK with creating and storing the file prior to submitting the form, but the ways I have seen to do that jumps the user to a new processing php page which messes everything up and removes what they have already done in the form.

Update 1 - As Base64 (Works):

OK I think I got it, having looked at the demo @Dhavel mentioned, I modified my code a little and it seems to be working. In my StopRecording function which had my original code, Instead of assigning the finished encorder to my audio element and then trying to use the url it made there, it seems to work if I send the encoder directly as a blob first.

stopBtnRecord = () => {
    isRecording = false;
    startBtn.removeAttribute('disabled');
    stopBtn.setAttribute('disabled', true);
    audioContext.close();
    processor.disconnect();
    tracks.forEach(track => track.stop());
    saveRecording(encoder.finish());
};
function saveRecording(blob) {
    var time = new Date(),
    url = URL.createObjectURL(blob);
    $("#audio").attr('src', url);
    let reader = new window.FileReader(); 
        reader.readAsDataURL(blob); 
        reader.addEventListener("loadend", function() {
        var audioBase64 = reader.result.toString();
        let audioTurned = audioBase64.substr(audioBase64.indexOf(',')+1); 
        $("#audiofile").val(audioTurned); 
    });
}

This creates a large base64 output in my hidden form element which when I send to my php file on submit, saves it as a file.

Update 2 - Blob Directly:

I've tried sending as blob directly, managed to somewhat do this by attaching a new onclick function to my form's submit button. But $_FILES and $_POST still don't show it anywhere.

var submitFormBtn = document.querySelector('#share-submit');
submitFormBtn.onclick = uploadBlob();
function uploadBlob(){
    var url = $("#audio").attr('src');
    var blob = new Blob([url]);
    var fd = new FormData();
    fd.append('fname', 'test.wav');
    fd.append('data', blob);
    $.ajax({
        type: 'POST',
        url: '/app/inc/social_push.php',
        data: fd,
        processData: false,
        contentType: false
    }).done(function(data) {
        console.log(data);
    });
}

This is the console log I get. Looks like it's sitting in storage as a tmp file, but it's not available in the POST/FILES data for me to work with. In my PHP file should I look somewhere else for the pending blob file?

</pre><pre>array(1) {
    ["data"]=>
        array(5) {
            ["name"]=>
            string(4) "blob"
            ["type"]=>
            string(24) "application/octet-stream"
            ["tmp_name"]=>
            string(25) "/home/share/tmp/phpcs49Me"
            ["error"]=>
            int(0)
            ["size"]=>
            int(0)
        }
    }
</pre>
0

There are 0 answers