Saving recorded audio blob [JS]

Viewed 974

I am recording user voice through microphone and saving it as a file on Google Drive (using GDrive API). I was having no issues doing this and listening to the audio that is uploaded to drive when I listen to it in the browser. However, when I download the file from GDrive, it gets downloaded without an extension (kind of like a textedit document).

I tried to modify the extension of the downloaded file and play it but it doesn't play on QuickTime, VLC or even Audacity etc.

Here's how I am recording the audio

function recordVisitorMsg() {
    navigator.mediaDevices.getUserMedia({
            audio: true
        })
        .then(stream => {
            const mediaRecorder = new MediaRecorder(stream);
            mediaRecorder = new MediaRecorder(stream);
            mediaRecorder.start();
            const audioChunks = [];
            mediaRecorder.addEventListener("dataavailable", event => {
                audioChunks.push(event.data);
            });

            mediaRecorder.addEventListener("stop", () => {
                audioBlob = new Blob(audioChunks, {
                    'type': 'audio/mp3'
                });
                const audioUrl = URL.createObjectURL(audioBlob);

                const audio = new Audio(audioUrl);
                audio = new Audio(audioUrl);
                audio.play();
            });

            setTimeout(() => {
                mediaRecorder.stop();
            }, 3000);
        });
}

Here's how I am uploading to Drive.

form = new FormData();
form.append('metadata', new Blob([JSON.stringify(metadata)], {
        type: 'application/json'
    }));


    form.append('audio-file', audioBlob);

let refresh_request = {
            body: post_body,
            method: "POST",
            headers: new Headers({
                'Content-Type': 'application/x-www-form-urlencoded'
            })
        }

        // trimmed the secret keys code for length, not necessary here 
        fetch(refresh_url, refresh_request).then(response => {
            return (response.json());
        }).then(response_json => {
            console.log(response_json);
            var xhr = new XMLHttpRequest();
            xhr.open('post', 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id');
            xhr.setRequestHeader('Authorization', 'Bearer ' + response_json.access_token);
            xhr.responseType = 'json';
            xhr.onload = () => {
                console.log(xhr.response.id); // Retrieve uploaded file ID.
            };
            xhr.send(form);
        });

I am new to this so please excuse if there's some minor issue wrong in this process. Again, it plays fine when I play it from within GDrive in the browser. The problem is when I download -- it comes out without the extension. Manual extension/modification doesn't help either to play the file in any player. Please help, thank you!

1 Answers

I'm not sure if this solves the problem entirely but I think it would be a good start to set the correct mimeType when creating the Blob. Unfortunately there is no browser which allows to record MP3s with the MediaRecorder. The default mimeType in Chrome is for example 'audio/webm'. You can read the mimeType from the MediaRecorder to set it when creating the Blob.

audioBlob = new Blob(
    audioChunks,
    { type: mediaRecorder.mimeType }
);

It may also help to create a File instead of a Blob. It allows you to set the filename and thus the extension. A quick and dirty way is to parse the mimeType like this.

audioBlob = new File(
    audioChunks,
    `my-file.${mediaRecorder.mimeType.match(/\/([\w\d]+);?/)[1]}`,
    { type: mediaRecorder.mimeType }
);

In Chrome this should be equal to the following hardcoded version.

audioBlob = new File(
    audioChunks,
    'my-file.webm',
    { type: 'audio/webm' }
);
Related