Uploading recorded audio to web server (node.js, express)

I have an audio file recorder, created in p5.js, similar to what has been created in the p5 Record Save Audio example page. Using node, I am trying to find a good way to save that audio file to the server as a .wav or .mp3

I realize that one strategy to achieve this would be to us the http “POST” function and to post the blob of the audio file, and then save that blob to the server. How do we get the blob? It looks like there is a method called getBlob on the p5.soundFile reference on line 1693 but every time I attempt to use getBlob it returns that the function is “not found”.

Additionally, I am wondering what the best way might be to use the save or saveSound and get the blob and save it to the server without prompting the browser’s dialogue box to save the file.

Thanks in advance,
Candice

2 Likes

Getting the same. If you’re using p5-sound.js from CDN or npm, then, I would say git clone the recent one from github in use that one.

Update
Ok, so to solve:

    1. git clone git@github.com:processing/p5.js-sound.git
    1. npm install
    1. grunt
    1. copy lib library to your project OR replace node_module (don’t forget to fix) or add as a static.
    1. also, for my case, I need to move p5.sound* files to addons dir (cd ~/lib && mv *.p5.sound.* ./addons)

That’s it.

1 Like

you’ll need a few thing to make this happen – of course node.js and express.js, but also you’ll need to require the filesystem via node ‘fs’ and get the multer npm package to handle the blob.

You’ll need p5.sound @ v0.3.9 or greater for the getBlob() function on the client side & p5.dom for this example.

good luck!

server side code:

const express = require('express'); //make express available
const app = express(); //invoke express
const multer  = require('multer') //use multer to upload blob data
const upload = multer(); // set multer to be the upload variable (just like express, see above ( include it, then use it/set it up))
const fs = require('fs'); //use the file system so we can save files

app.post('/upload', upload.single('soundBlob'), function (req, res, next) {
  // console.log(req.file); // see what got uploaded

  let uploadLocation = __dirname + '/public/uploads/' + req.file.originalname // where to save the file to. make sure the incoming name has a .wav extension

  fs.writeFileSync(uploadLocation, Buffer.from(new Uint8Array(req.file.buffer))); // write the blob to the server as a file
  res.sendStatus(200); //send back that everything went ok

})

//serve out any static files in our public HTML folder
app.use(express.static('public'))

//makes the app listen for requests on port 3000
app.listen(3000, function(){
  console.log("app listening on port 3000!")
})

client side code:

let button;
let mic;
let soundRec;
let soundFile;


function setup() {
  mic = new p5.AudioIn();
  mic.start();
  soundRec = new p5.SoundRecorder();
  soundRec.setInput(mic)
  soundFile = new p5.SoundFile();

  button = createDiv("");
  button.position(100,100);
  button.size(100,100);
  button.style('background-color', 'grey');


  button.mouseClicked((mouseEvent)=>{
    console.log("recording....");
    soundRec.record(soundFile); // set up the soundfile to record and start recording

    let recordingTimer = setTimeout(()=>{ // setup a timeout for the recording, after the time below expires, do the tings inside the {}

      soundRec.stop(); // stop recording
      let soundBlob = soundFile.getBlob(); //get the recorded soundFile's blob & store it in a variable

      let formdata = new FormData() ; //create a from to of data to upload to the server
      formdata.append('soundBlob', soundBlob,  'myfiletosave.wav') ; // append the sound blob and the name of the file. third argument will show up on the server as req.file.originalname

          // Now we can send the blob to a server...
      var serverUrl = '/upload'; //we've made a POST endpoint on the server at /upload
      //build a HTTP POST request
      var httpRequestOptions = {
        method: 'POST',
        body: formdata , // with our form data packaged above
        headers: new Headers({
          'enctype': 'multipart/form-data' // the enctype is important to work with multer on the server
        })
      };
      // console.log(httpRequestOptions);
      // use p5 to make the POST request at our URL and with our options
      httpDo(
        serverUrl,
        httpRequestOptions,
        (successStatusCode)=>{ //if we were successful...
          console.log("uploaded recording successfully: " + successStatusCode)
        },
        (error)=>{console.error(error);}
      )
      console.log('recording stopped');

    },1000) //record for one second

  }) // close mouseClicked handler


} //close setup()

3 Likes