Search code examples
javascriptpythonaudiofetch-api

How to POST an audio blob to a python server


Im making a chrome extension which gets an audio, and sends it to a python server (with HttpServer), and the server saves the audio.

The problem is that the server is not saving the audio correctly, and the audio is not playable

the JS:

let gapBlob = new Blob(gapRecord.recording, { type: "video/webm" });
let currGapAudio = document.getElementById("recording" + gapId)
currGapAudio.src = URL.createObjectURL(gapBlob);

var myHeaders = new Headers();
myHeaders.append("Content-Type", "multipart/form-data");


var formdata = new FormData();  
formdata.append("AudioFile",gapBlob, "my_audio.wav");

var requestOptions = {
    method: 'POST',
    headers: myHeaders,
    body: formdata,
    redirect: 'follow'
};

fetch("http://localhost:8080/", requestOptions)
    .then(response => response.text())
    .then(result => console.log(result))
    .catch(error => console.log('error', error));
  • in the first two lines, I display the audio to the client with the <audio /> element, and it works well.

the python server:

def do_POST(self):
    self.send_header('Access-Control-Allow-Origin', '*')

    file_length = int(self.headers['Content-Length'])
    newname = 'server/uploaded' + str(random.randint(100,999)) + '.wav'
    
    with open(newname, 'wb') as output_file:
        content = self.rfile.read(file_length)
        
        content = content.split(b'Content-Type: video/webm')[1]
        content = content[4:]
        content = content.split(b'------')[0]
        
        output_file.write(content)
        
  • the splits are because the body looks like this:

b'------WebKitFormBoundary3joaVYqdXgqiCh0X\r\nContent-Disposition: form-data; name="AudioFile"; filename="my_corrupted.wav"\r\nContent-Type: video/webm\r\n\r\n\x1aE\xdf\xa3\....2\xef\x06}\xa8\xc2\xd7\x9b\xee\xd9\xed2\x16\x0f\xdd\x07U\xef\x9f\xdf\xcb\x16Hk\xfd\x81n2=\xc3\r\n------WebKitFormBoundary3joaVYqdXgqiCh0X--'

I tried to remove the extra text that were appended to the body with splits, but it didn't help.

Anyone has any idea?

Thank you


Solution

  • You can try using a better framework than HttpServer. Here's the same implemented in Flask, note how there's no fussing around with the raw response body.

    from flask import Flask, request
    import uuid
    
    app = Flask(__name__)
    
    @app.route('/', methods=['GET', 'POST'])
    def upload_file():
        if request.method == 'GET':
            return '''
    <form method="post" enctype="multipart/form-data">
      <input type="file" name="file" accept=".wav">
      <input type="submit">
    </form>
    '''
        print(request.files)
        file = request.files['file']
        if not file.filename.endswith('.wav'):
            return 'File extension must be .wav', 415  # Unsupported Media Type
        path = 'server/uploaded' + str(uuid.uuid4()) + '.wav'
        file.save(path)
        return 'saved to '+path
    
    if __name__ == '__main__':
        app.run('127.0.0.1', 8080, debug=True)