【问题标题】:How to save WAV Blob to MongoDB, retrieve and serve correctly with Node?如何将 WAV Blob 保存到 MongoDB,使用 Node 正确检索和服务?
【发布时间】:2016-02-13 01:37:35
【问题描述】:

我发现了很多关于使用 Mongoose Buffer SchemaType 保存二进制文件的帖子。但是,它们中的大多数都处理图像文件,我无法让它们处理 WAV 音频文件。

我正在使用 Recorder.js 保存来自内置麦克风的录音。我使用 Recorder.js 的 exportWAV 函数从完成的录制中获取一个 BLOB,然后使用 FileReader 读取该 blob 并将其发送到 Node/Express 后端,然后将其保存到数据库中。我已经使用 Mongo CLI 进行了检查,并且有数据保存到相关字段(从 BinData(0,"UklGR.lotsofdatahere..=") 开始。当我尝试通过句子 id 获取记录时,服务器会响应无法播放的适当 MIME 类型的 .wav 文件。

似乎我在文件被编码和解码以存储在 MongoDB 中的方式上遗漏了一些东西。当读取 Recorder.js 吐出的 blob 时,它看起来已经是 base64 编码的。所以这就是为什么我尝试在保存到 Mongo 之前将其加载为 base64 缓冲区,然后在输出时从 base64 缓冲区解码。我在这里想念什么?如何解决这些编码问题?谢谢!

注意:我不一定需要 GridFS,因为这些文件远低于 16MB。虽然,如果从 GridFS 流式传输文件要快得多,也许我应该切换到该解决方案。但是,我想先弄清楚这种方法有什么问题。

以下是 Angular 前端的相关代码:

$scope.start = function() {
  $scope.rec.record();
}

$scope.export = function() {
  $scope.rec.stop();

  $scope.rec.exportWAV(function blobCallback(blob) {
    $scope.rec.clear();

    var reader = new FileReader();
    reader.onload = function(event) {
      $.ajax({
        type: 'POST',
        url: '/saveRecording',
        data: {
          audio: event.target.result,
          text: $scope.text,
          timestamp: new Date()
        }
      }).done(function(data) {
        console.log(data);
      });
    }
    reader.readAsDataURL(blob);
  });
}

特快路线:

router.post('/saveRecording', function(request, response, next) {
  var sentence = new Sentence();
  sentence.audio = new Buffer(request.body.audio, 'base64');
  sentence.timestamp = request.body.timestamp;
  sentence.text = request.body.text;


  // Save sentence to DB with Mongoose
  sentence.save(function(error, sentence) {
    if (error) {
      return next(error);
    }

    // If no error, send added sentence back to the client.
    response.json(sentence);
  });
});

router.get('/getRecording/:sentenceId', function(request, response, next) {
  Sentence.findById(request.params.sentenceId,
    function dbCallback (error, sentence) {
      if (error) {
        return next(error);
      }
      if (!sentence) {
        return next(new Error('Can\'t find sentence'));
      }

      var base64Audio = new Buffer(sentence.audio, 'base64');
      response.writeHead(200, {
        'Content-Type': 'audio/x-wav',
        'Content-Length': base64Audio.length
      });

      response.write(base64Audio);
      response.end();
    });
});

句子的猫鼬模式:

var SentenceSchema = new mongoose.Schema({
  text: String,
  audio: Buffer,
  timestamp: Date
});

【问题讨论】:

    标签: angularjs node.js mongodb mongoose recorder.js


    【解决方案1】:

    您可以尝试使用 GridFs 来存储您的音频文件 检查link

    【讨论】:

    • 我考虑过 GridFS,但我认为对于我正在使用的小文件大小来说,这并不是真正必要的。对于上述代码示例中我的编码/解码出了什么问题,我将不胜感激。
    • 您是否尝试将 blob 读取为 BufferArray ? reader.readAsArrayBuffer(blob)
    • 我尝试了 BufferArray 的东西,但不能完全让它工作。在这种情况下,无论如何我都必须从 BufferArray 转换为 Node Buffer,从我所读到的内容来看,这可能会很慢。我遵循了您最初的建议并最终使用了 GridFS,它现在就像一个魅力一样工作......我会说将来我不会费心尝试手动操作,即使文件大小很小。对于我正在做的事情,性能差异可能可以忽略不计。谢谢!
    • 很高兴它现在正在与您合作!我发现 GridFs 是一种更好的方法来处理所有大小的文件,即使是小文件。
    猜你喜欢
    • 2012-05-14
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2017-04-27
    • 1970-01-01
    • 2015-06-15
    • 1970-01-01
    相关资源
    最近更新 更多