Skip to content

Send Wav file from js to flask

I have this code in js witch recod an audio from the browser and I need to send it back from js to flask

start: function () {
    var options = {audio: true, video: false};
    navigator.mediaDevices.getUserMedia(options).then(function (stream) {
    myRecorder.objects.stream = stream;
    myRecorder.objects.recorder = new Recorder(
    myRecorder.objects.context.createMediaStreamSource(stream),
    {numChannels: 1}
     );
     myRecorder.objects.recorder.record();
     }).catch(function (err) {});

How I should do that while making the file in wav format?

Answer

The following example creates a limited time audio recording and uploads it when finished. A form containing a blob is used for this.
It would also be possible to transmit the pure blob to the server, but since there are differences in the audio format used depending on the browser, this is the more general variant.

(function() {
  const uploadURL = "{{ url_for('upload') }}";
  const startButton = document.getElementById("toggle-rec-btn");
  startButton.addEventListener("click", function() {
    if (!navigator.mediaDevices) {
      console.error("getUserMedia not supported.")
      return;
    }

    const constraints = { audio: true };
    navigator.mediaDevices.getUserMedia(constraints)
    .then(function(stream) {
        let chunks = []
        let recorder = new MediaRecorder(stream);
        recorder.ondataavailable = event => {
            // Collect all the chunks of the recording in an array.
            chunks.push(event.data);
        };
        recorder.onstop = event => {
          console.log("Recording stopped.")
          // Create a blob with all the chunks of the recording.
          let blob = new Blob(chunks, { type: recorder.mimeType }); 
          chunks = [];
          startButton.disabled = false;

          // Create form data that contain the recording.
          let formData = new FormData();
          formData.append("audio_file", blob);

          // Send the form data to the server.
          fetch(uploadURL, {
            method: "POST",
            cache: "no-cache",
            body: formData
          }).then(resp => {
            if (resp.status === 200) {
              window.location.reload(true);
            } else {
              console.error("Error:", resp)
            }
          }).catch(err => {
            console.error(err);
          });
        };
        recorder.onstart = event => {
          console.log("Recording started.");
          startButton.disabled = true;
          // Stop recording when the time is up.
          setTimeout(function() { recorder.stop(); }, 10000);
        };
        recorder.start();
    })
    .catch(function(err) {
        console.error(err);
    });
  });
})();

All recordings are saved on the server in a directory with the default name “var/app-instance/uploads”.

import os
from flask import abort, current_app, make_response, request
from mimetypes import guess_extension
from werkzeug.utils import secure_filename

@app.route('/upload', methods=['POST'])
def upload():
    if 'audio_file' in request.files:
        file = request.files['audio_file']
        # Get the file suffix based on the mime type.
        extname = guess_extension(file.mimetype)
        if not extname:
            abort(400)

        # Test here for allowed file extensions.

        # Generate a unique file name with the help of consecutive numbering.
        i = 1
        while True:
            dst = os.path.join(
                current_app.instance_path,
                current_app.config.get('UPLOAD_FOLDER', 'uploads'),
                secure_filename(f'audio_record_{i}{extname}'))
            if not os.path.exists(dst): break
            i += 1

        # Save the file to disk.
        file.save(dst)
        return make_response('', 200)
    
    abort(400)

I wish you every success in implementing your project.