将捕获的视频保存到 Electron 中的文件 [英] Save captured video to file in Electron

查看:23
本文介绍了将捕获的视频保存到 Electron 中的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将从网络摄像头捕获的视频保存到本地文件.到目前为止,我已经能够:

I want to save a video that is captured from webcam to a local file. So far I have been able to:

  1. 使用 getUserMedia 创建一个流
  2. RecordRTC
  3. 封装流
  4. RecordRTC
  5. 获取 blob
  1. Create a stream with getUserMedia
  2. Encapsulate the stream with RecordRTC
  3. Get blob from RecordRTC

我不知道如何将视频保存到文件中.在 RecordRTC 上调用 save() 允许我下载视频文件,但我希望一切都发生在 nodejs 中以进行进一步处理.无论如何,该文件是可播放的.我尝试将 blob 和 dataURL 写入文件,但该文件不可播放.

I cannot figure out how to save the video to a file though. Calling save() on RecordRTC allows me to download the video file, but I want everything to happen in nodejs for further processing. The file is playable, regardless. I tried to write the blob and dataURL to file, but that file is not playable.

推荐答案

MediaRecorder 类在 Chromium 和 Electron 中实现,可以支持您的用例.将媒体保存为文件不仅是可能的,而且可以说是微不足道的:

The MediaRecorder class implemented in Chromium and thus Electron, can support your use case. Saving the media as a file is not only possible but arguably trivial:

const recorder = new MediaRecorder(await navigator.mediaDevices.getUserMedia());
const blob_reader = new FileReader();
const storage_stream = require("fs").createWriteStream(path);
const blobs = [];
blob_reader.addEventListener("load", ev => {
    storage_stream.write(Buffer.from(ev.currentTarget.result));
    if(blobs.length) ev.currentTarget.readAsArrayBuffer(blobs.shift());
});
recorder.addEventListener("dataavailable", ev => {
    if(blob_reader.readyState != 1) blob_reader.readAsArrayBuffer(ev.data);
    else blobs.push(ev.data);
});

我认为将 Blob 对象转换为 ArrayBuffer 等价物的技术消耗和不希望的(但必要的)步骤与 API 实现本身一样有效-- JavaScript 机器本身并不繁重.

Short of what I consider a technically expendable and undesired (but necessary) step of converting Blob objects to ArrayBuffer equivalents, this is as efficient as the API implementation itself is -- the JavaScript machine itself does no heavy lifting here.

对以上片段的备注和解释:

Remarks and explanations on the snippet above:

  • 在您通过调用 MediaRecorder.start 方法.请注意,如果需要,该片段可与多个生成的 blob 一起使用——使用 1 秒的时间片(start 的第一个参数)可能是一个好主意,具体取决于.这样的时间片允许您进行适当的数据流式传输,而不是在进程内存中存储一​​个潜在的巨大的单个 blob 编码视频流(如果您省略 timeslice 参数到 <代码>开始).
  • 一旦发出对 start 的调用(使用时间片),生成的文件将开始在磁盘上"增长,具体取决于时间片值和中间缓冲区的长度.
  • MediaRecorder 对象,作为编码媒体的一部分,生成 blobs 由于某种原因,它们不是非常可消耗的";通过许多其他 API,因此我们必须将它们转换为可消耗的东西,在这种情况下,对象对我们来说更方便 ArrayBuffer 类.
  • 由于将 blob 转换为数组缓冲区是异步的,因此我们有一个在 先进先出基础.
  • require(fs") 为我们提供了一个 Node.js 模块,fs";不是您的 Web 浏览器中其他可用的模块,至少不是根据我所知道的 Web 标准草案.然而,这个模块允许我们将生成的数组缓冲区转储到文件中.
  • 可能不显眼的表达式 Buffer.from(...) 在这里并不常见——Web API 空间中没有 Buffer 类,它是一个能够将 ArrayBuffer 包装为视图的 Node.js 类(无数据复制).这是必要的,因为您不能将 ArrayBuffer 直接写入文件流.
  • 由媒体记录器对象生成的数据串联是一个有效媒体容器(相对于记录器对象的 MIME 类型),因此只需将这些数据交给流,在完成时当然,正确的顺序足以让我们获得有效的媒体容器文件(例如 .webm.mp4).
  • 不过,生成的文件是所谓的传输流 - 某些视频播放器可能无法可靠或有效地搜索数据.然而,ffmpeg 可以通过索引这些文件并相应地修补它们来轻松地对这些文件进行后处理.我认为这样的步骤是可选的——传输流本身并没有什么问题,就像上面的代码片段生成的那样.
  • 上面传递给 createWriteStreampath 属性/变量表示要将视频保存到的文件的路径.
  • There won't be any action until you actually start the media recorder by issuing a call to the MediaRecorder.start method. Note that the snippet is made to work with multiple generated blobs, if needed -- using a timeslice (first argument to start) of 1 second may be a good idea, depending. Such timeslice allows you to do proper streaming of data, as opposed to getting a potentially gigantic single blob worth of encoded video stream stored in process memory (which is what you get if you omit the timeslice parameter to start).
  • As soon as a call to start is issued (with a timeslice), the resulting file will start growing "on disk", depending on the timeslice value and lengths of intermediate buffers.
  • A MediaRecorder object, as part of encoding media, generates blobs which, for one reason or another, aren't very "consumable" by many other APIs, so we have to convert them to something that is consumable, in this case objects of the more convenient for us ArrayBuffer class.
  • Since conversion of a blob into an array buffer is asynchronous, we have a queue of blobs that is duly converted on a FIFO basis.
  • require("fs") gets us a Node.js module, "fs" is not a module otherwise available in your Web browser, at least not according to a Web standard draft I know of. That's the module, however, that allows us to dump the resulting array buffers into a file.
  • The perhaps inconspicuous expression Buffer.from(...) is more than meets the eye here -- there is no Buffer class in the Web API space, it's a Node.js class that is able to wrap an ArrayBuffer as a view (no data copying). This is necessary because you can't write an ArrayBuffer into a file stream directly.
  • A concatenation of data generated by a media recorder object is a valid media container (with respect to the MIME type of the recorder object), so just handing these data to the stream, when done in proper order of course, is sufficient to get us valid media container file (e.g. a .webm or an .mp4).
  • The resulting file is, however, a so called transport stream -- some video players may or may not be able to reliably or efficiently seek on the data. ffmpeg, however, can trivially postprocess such files by indexing them and patching them accordingly. I consider such step optional -- there is nothing inherently wrong with a transport stream like the ones generated by the snippet above.
  • The path property/variable passed to createWriteStream above denotes the path to the file you want to save the video to.

我已经在 Windows 10 上使用 3.0.4 版本的 Electron 测试了该代码段.

I have tested the snippet with the 3.0.4 version of Electron on Windows 10.

另一种将媒体保存为文件的方法(有趣的是,它也可以与相当现代的 Web 浏览器一起使用)是将记录器提供的 blob 连接到一个 blob 中,并让用户下载整个使用 URL.createObjectURL 方法的产品.然而,我认为这种方法和上面说明的方法在功能或能力上并不​​相同——我对如何在不同的用户代理中实现 blob 不是 100% 有信心——无论是否由物理/虚拟 RAM 支持,例如——媒体文件可能会变得非常大,如果包含在 blob 中并通过 URL 引用,则这些文件需要完整地存储在 RAM 中,这可能是潜在的资源耗尽错误.相比之下,零碎地编写文件自然不应该受到这样的限制.无论如何,我将 createObjectURL 的应用程序留给读者一个练习,它应该相当简单,其他一切都已到位.

An alternative approach to saving the media as a file -- which interestingly works with a Web browser of a fairly modern make, too -- is to concatenate the blobs provided by the recorder into a single blob and let user download the entire product using the URL.createObjectURL method. I'd argue, however, that this approach and the one illustrated above, are not equivalent in their function or capability -- I am not 100% confident about how blobs are implemented in different user agents -- whether backed by physical/virtual RAM, for example -- media files can grow very large and if, contained in blobs and referenced with URLs, these need to be stored in RAM in their entirety, well that's a potentially latent resource exhaustion fault. In comparison, writing a file piecemeal shouldn't naturally suffer from such constraints. Anyway, I leave the application of createObjectURL an exercise to the reader, it should be rather trivial, everything else being in place.

这篇关于将捕获的视频保存到 Electron 中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆