我认为这应该相当简单,但我认为我研究得太多了,这没有意义。
我目前在做什么
我正在使用 Node + React 创建一个 Web 应用程序,以便在浏览器中录制音频。我在客户端使用RecordRTC来录制来自用户麦克风的音频。 一切都很好,但有时在用户唱完歌后上传音频文件需要很长时间。 我想在下一步中将其发送回用户之前处理此文件,因此速度在这里至关重要,因为他们正在等待这种情况发生。
为了使我的用户体验更流畅,我想在开始从 RecordRTC 接收音频 blob 后立即启动音频上传过程。 我可以访问这些 blob,因为 RecordRTC 允许我传递一个时间片值(以毫秒为单位)和一个"ondatavailable"函数,该函数将每隔毫秒的时间片量传递一个 blob。
我试过什么
目前,我可以轻松地使用 FormData(),因为我只在用户唱完歌后发送文件。
- 我的第一个想法是找到一个像 Fetch API 这样的例子,以类似于我所追求的方式使用。 有很多例子,但它们都认为源文件已经可用,但是由于我想在它们出现时不断添加 blob(无法预先确定这些 blob 何时可能停止出现,因为用户可能会决定提前停止唱歌过程)这看起来没有希望。
- 然后,我考虑了一个"编写我自己的"过程,即提出许多请求,而不是尝试一个长时间的连续样式。 这将涉及为每个请求附加一个唯一标识符,并让服务器将每个 id 匹配的块连接在一起。 但是,我不确定这在未来的多服务器环境中会有多灵活,更不用说处理掉线等了,也没有真正的方法告诉服务器在用户中止事件的情况下报废所有内容,例如关闭选项卡/网页等。
- 最后,我研究了通过NPM等可用的内容,但没有成功,然后承认也许我的Google Fu让我失望了。
我想要什么
理想情况下,我想在记录开始后创建一个 SINGLE 新请求,然后在每次我在"ondataavailable"中收到 blob 时获取它,将其发送到我的请求(一旦收到某些内容,就会将其泵送到我的服务器)无限期。 一旦音频停止(我也从 RecordRTC 获得此事件,因此可以控制它),我想完成/关闭我的请求,以便服务器知道它现在可以开始处理文件。 作为上传过程的一部分,我还需要在正文中传入一两个文本数据字段,因此也需要处理。 在服务器端,一旦服务器收到每个块,它应该可以立即访问,这样我就可以开始在服务器端创建音频文件/附加到音频文件,并在用户完成唱歌后几乎立即准备好进行处理。
注意:服务器目前设置为通过 npm 上的 multer 库查找和处理多部分上传,但我非常乐意更改它以获得我想要的功能。
谢谢!
为任何可能在自己的搜索中偶然发现此问题的人提供更新。
我们最终"滚动我们自己的"自定义上传器,在客户端,将音频 blob 以最多 5 个 1 秒 blob 的块的形式发送到服务器。 每个请求都包含一个"请求编号",该编号只是前一个请求编号的 +1,从 1 开始。 发送 5 个 1 秒 blob 的原因是 RecordRTC,至少在当时,不会捕获最后的 X 秒数。 联发局如果改用 5 秒的 blob,则 38 秒的歌曲将丢失最后 3 秒。 到达录制结束时,它会发送一个最终请求(标有额外的标头,让服务器知道这是最终请求)。 上传器以链表样式工作,以确保在发送下一个请求之前已处理每个先前的请求。
在服务器端,这 5 个 blob 通过 FFMPEG 追加到单个 5 秒音频 blob 中。 这确实引入了外部依赖关系,但我们已经在大部分应用程序中使用了FFMPEG,因此这是一个容易的决定。 生成的文件在其文件名后附加了请求编号。 收到最终请求后,我们再次使用 FFMPEG 对所有收到的文件进行最终串联,以获得最终文件。
在非常慢的连接上,我们看到时间节省了60 +秒以上,因此它显着提高了应用程序在较慢的互联网连接下的可用性。
如果有人想自己使用代码,请通过这里进行 PM。(它相当未经修饰,但我会在发送前清理它)