草庐IT

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

coder 2023-08-02 原文

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

我的服务器(Flask)的主路由'/'正在等待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")

这是我的 JS 代码:

Jsfiddle

这里主要有两个问题:

1) 当我在录制后下载 mp3 文件时,无法用媒体播放器打开它。好像我只是在录制音频时做错了什么。

2) 当我在收到 POST 请求后在我的服务器中 print request.form 时,我只得到这个:

ImmutableMultiDict([('file', u'')])

print request.form['file'] 返回一个空行。

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

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

注意:所有这些都不必保持不变。任务是录制音频,然后将其发布到服务器。如果有更有效的方法来做到这一点,欢迎任何提示。另外,我不关心文件是 wav 还是 mp3。

最佳答案

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


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

此外,在您的 MediaRecorder 代码中,您似乎在每个 dataavailable 事件中完成文件。这通常不是您想要的。


目前,没有浏览器支持本地录制为 mp3。

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

因此,如果您想采用 MediaRecorder 方式,则必须使用 opus 编解码器,封装在用于 chrome 的 webmogg 中 对于 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>

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

关于javascript - 将 HTML5 音频数据发布到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43903963/

有关javascript - 将 HTML5 音频数据发布到服务器的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  4. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  5. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  6. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  7. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  8. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  9. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  10. ruby-on-rails - Ruby url 到 html 链接转换 - 2

    我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.

随机推荐