Search code examples
mongodbmeteorblobrecorder

How to insert a blob into mongodb in meteor


I am using Recorder.js, which allows you to display an audio recording like so

recorder.exportWAV(function(blob) {
  var url = URL.createObjectURL(blob);
  var au = document.createElement('audio');
  au.controls = true;
  au.src = url;
}

But how can I save the blob to the database? Assuming I have a Recordings collection:

recorder.exportWAV(function(blob) {
  Recordings.insert({data: blob});
}

will only store this

{data: { "type" : "audio/wav", "size" : 704556 }}

which does not have the actual content.


Solution

  • After watching the file upload episode from eventedmind.com, it turns out the way to do it is to use the FileReader to read a blob as ArrayBuffer, which is then converted to Uint8Array to be stored in mongo:

    var BinaryFileReader = {
      read: function(file, callback){
        var reader = new FileReader;
    
        var fileInfo = {
          name: file.name,
          type: file.type,
          size: file.size,
          file: null
        }
    
        reader.onload = function(){
          fileInfo.file = new Uint8Array(reader.result);
          callback(null, fileInfo);
        }
        reader.onerror = function(){
          callback(reader.error);
        }
    
        reader.readAsArrayBuffer(file);
      }
    }
    

    The exportWAV callback is then

    recorder.exportWAV(function(blob) {
      BinaryFileReader.read(blob, function(err, fileInfo){
        Recordings.insert(fileInfo)
      });
    });
    

    Then I can display one of my recordings by:

    Deps.autorun(function(){
      var rec = Recordings.findOne();
      if (rec){
        var au = document.createElement('audio');    
        au.controls = true;
        var blob = new Blob([rec.file],{type: rec.type});
        au.src = URL.createObjectURL(blob);
        document.getElementById("recordingslist").appendChild(au);
      }
    })
    

    I don't know if the previous snippet works in other browsers, but this may:

    var base64Data = btoa(String.fromCharCode.apply(null, rec.file))
    var au = document.createElement('audio');
    au.controls = true;
    au.src = "data:"+rec.type+";base64,"+base64Data