将HTML5音频数据发布到服务器

时间:2017-05-10 23:02:01

标签: javascript python html5 audio flask

我目前正在实施一个Web应用程序,我希望用户录制一些音频,然后我想要一个提交按钮来将记录的mp3文件发送到服务器。

我的服务器(Flask)的主路由serviceWorker正在等待POST请求:

'/'

这是我的JS代码:

Jsfiddle

这里有两个主要问题:

1)录制后下载mp3文件时,媒体播放器无法打开。在录制音频时,我似乎做错了。

2)在收到POST请求后我的服务器中@app.route('/', methods=['GET', 'POST']) def index(): if request.method == "GET": return render_template('index.html', request="GET") else: print request.files print request.form print request.form['file'] if 'file' not in request.files: flash('No file part') return redirect(request.url) file = request.files['file'] if file.filename == '': flash('No selected file') return redirect(request.url) if file and allowed_file(file.filename): handle_file(file) return render_template('index.html', request="POST") 时,我只能得到这个:

print request.form

ImmutableMultiDict([('file', u'')]) 返回一个空行。

为什么会这样? POST请求有问题吗。

最后,我希望能够解码我发布的字符串以转换回mp3。我该怎么做?

注意:这些都不能保持不变。任务是录制音频,然后将其POST到服务器。如果有更有效的方法,欢迎任何提示。另外,我不在乎文件是wav还是mp3。

2 个答案:

答案 0 :(得分:4)

注意:此答案仅处理chrome和Firefox中的当前实现。所有这些都可能很快改变。

我不确定您的服务器端代码是否有任何问题,但不要将二进制数据作为字符串发送。相反,使用FormData将其作为multipart发送(您将获得30%的数据+完整性)。

此外,似乎在您的MediaRecorder代码中,您要在每个dataavailable事件中最终确定该文件。它通常不是你想要的。

目前,没有任何浏览器本身支持以mp3格式录制。



var mimes = ['mpeg', 'mpeg3', 'x-mpeg3', 'mp3', 'x-mpeg']
console.log(mimes.some(m=>MediaRecorder.isTypeSupported('audio/'+m)));




因此,如果你想采用MediaRecorder的方式,你必须使用opus编解码器,用webm封装为chrome,或ogg封装为FF:



var enc = ['ogg', 'webm'];
var mime = "";
enc.forEach(e => {
  if (!mime && MediaRecorder.isTypeSupported(`audio/${e};codecs="opus"`)) {
    mime = `audio/${e};codecs="opus"`;
  }
});
console.log(mime);




现在我们已经获得了正确的mimeType,我们可以简单地告诉浏览器使用它:

fiddle for chrome



var enc = ['ogg', 'webm'];
var extension = "",
  mime = '';
enc.forEach(e => !extension &&
  (mime = `audio/${e};codecs="opus"`) &&
  MediaRecorder.isTypeSupported(mime) &&
  (extension = e));
navigator.mediaDevices.getUserMedia({
    audio: true
  })
  .then(stream => {
    const chunks = [];
    const rec = new MediaRecorder(stream, {
      mimeType: mime // use the mimeType we've found
    });
    // this is not where we build the file, but where we store the chunks
    rec.ondataavailable = e => chunks.push(e.data);
    rec.onstop = e => {
      // stop our gUM stream
      stream.getTracks().forEach(t => t.stop());
      // NOW create the file
      let blob = new Blob(chunks, {
        type: mime
      });
      // we could now send this blob : 
      //   let form = new FormData();
      //   form.append('file', blob, 'filename.'+extension;
      //   ... declare xhr
      //   xhr.send(form);
      // but we'll just fetch it for the demo :
      let url = URL.createObjectURL(blob);
      let au = new Audio(url);
      au.controls = true;
      document.body.appendChild(au);
      au.play();
      // and create an downloadable link from it : 
      let a = document.createElement('a');
      a.href = url;
      a.download = 'filename.' + extension;
      a.innerHTML = 'download';
      document.body.appendChild(a);
    };
    rec.start();
    setTimeout(() => rec.stop(), 3000);
  });




或者我们也可以让浏览器默认执行所有操作。这只是文件扩展名的问题......

现在,如果你更喜欢wav而不是opus,你可以让MediaRecorder离开,只需使用WebAudioAPI,将你的gUM流传递给它,然后从那里记录数据。在这里,为了简单起见,我将使用recorder.js库。

fiddle for chrome



navigator.mediaDevices.getUserMedia({
  audio: true
})
.then(stream => {
  const aCtx = new AudioContext();
  const streamSource = aCtx.createMediaStreamSource(stream);
  var rec = new Recorder(streamSource);
  rec.record();
  setTimeout(() => {
    stream.getTracks().forEach(t => t.stop());
    rec.stop()
    rec.exportWAV((blob) => {
      // now we could send this blob with an FormData too
      const url = URL.createObjectURL(blob);
      let au = new Audio(url);
      au.controls = true;
      document.body.appendChild(au);
      au.play();
      let a = document.createElement('a');
      a.href = url;
      a.innerHTML = 'download';
      a.download = 'filename.wav';
      document.body.appendChild(a);
    });
  }, 3000);
})

<script src="https://rawgit.com/mattdiamond/Recorderjs/master/dist/recorder.js"></script>
&#13;
&#13;
&#13;

如果你真的想要一个mp3,我想你可以使用网上提供的一个javascript lame库。

答案 1 :(得分:0)

尝试将音频blob转换为Base64并将base64字符串发布到服务器。

function submit(blob) {
  var reader = new window.FileReader();
  reader.readAsDataURL(blob);
  reader.onloadend = function() {

    var fd = new FormData();
    base64data = reader.result;
    fd.append('file', base64data, 'audio.mp3');

    $.ajax({
      type: 'POST',
      url: '/',
      data: fd,
      cache: false,
      processData: false,
      contentType: false,
      enctype: 'multipart/form-data'
    }).done(function(data) {
      console.log(data);
    });
  }

}

现在,将base64字符串转换为服务器中的二进制流。

在python checkout上发布有关如何解码Base64的更多信息。 Python base64 data decode