Home > OS >  iOS can't play uploaded audio: JS MediaRecorder -> Blob -> Django Server -> AWS s3 -&g
iOS can't play uploaded audio: JS MediaRecorder -> Blob -> Django Server -> AWS s3 -&g

Time:02-08

Answer: shouldn't set content/mime type browser side with JS, should use native browser mimeType then convert server side (I used PyDub).

Question: I am using Javascript MediaRecorder, Django, AWS s3 and Javascript Web Audio API to record audio files for users to share voice notes with one another. I've seen disbursed answers online about how to record and upload audio data and the issues with Safari/iOS but thought this could be a thread to bring it together and confront some of these issues.

Javascript:

mediaRecorder = new MediaRecorder(stream);

mediaRecorder.onstop = function (e) {
    var blob = new Blob(
        chunks,
        {
            type:"audio/mp3",
        }
    );
    var formdata = new FormData();
    formdata.append('recording', blob)
    var resp = await fetch(url, { // Your POST endpoint
        method: 'POST',
        mode: 'same-origin',
        headers: {
        'Accept': 'application/json',
        'X-Requested-With': 'XMLHttpRequest',
        'X-CSRFToken': csrf_token,
        },
        body: formdata,
    })
}

Django:

for k,file in request.FILES.items():
    sub_path = "recordings/audio.mp3"
    meta_data = {"ContentType":"audio/mp3"}
    s3.upload_fileobj(file, S3_BUCKET_NAME, sub_path,ExtraArgs=meta_data)
    ###then some code to save the s3 URL to my database for future retrieval

Javascript:

var audio_context = new AudioContext();

document.addEventListener("#play-audio","click", function(e) {
    var url = "https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/audio.mp3"
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';
    request.onload = function () {
        audio_context.decodeAudioData(request.response, function (buffer) {
            playSound(buffer)
        });
    }
    request.send();
})

Results in: "EncodingError: Decoding Failed"

Note however that using the w3 schools demo mp3 url does play the recording: https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/t-rex-roar.mp3

Specs: PC (used to upload recoding): Windows 11, Chrome Version 98.0.4758.81 (Official Build) (64-bit) Django: Version: 3.1.7 Mobile (used to play recording): iPhone X, iOS (Version 14.7.1) Problematic url: https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/audio.mp3 Working url: https://docplat-bucket.s3.eu-west-3.amazonaws.com/recordings/t-rex-roar.mp3

(This is my first post so please forgive me if I haven't asked this question in the ideal way :) )

CodePudding user response:

When you upload the recorded Blob you set the type to 'audio/mp3'. But unless you use a custom library which patches the MediaRecorder the mimeType of the recording will be whatever the browser likes best.

As of now it's 'audio/opus' in Firefox and 'audio/webm' in Chrome.

If you define your Blob like this it should work.

var blob = new Blob(
    chunks,
    {
        type: mediaRecorder.mimeType
    }
);

You would also have to change your server side code to not use 'audio/mp3' anymore.

  •  Tags:  
  • Related