WebRTC 视频录制下载 - 我被产品经理套路了

307 阅读2分钟

Web Real-Time Communications 实时通信技术

前阵子,产品经理找到我

  • 产品:咱们有视频录制、下载功能吗?
  • 我:(擦?又想加需求?)没有,不支持
  • 产品:那行吧,你准备准备,要出差了,外厂商有视频录制的接口,咱实现不了,那就过去对接一下
  • 我:(???)等下,好像可以有,我回去试试 🐶

视频录制与下载

用过 MediaRecorder 的朋友都知道,这玩意儿录视频贼简单,很少的代码量就能实现录制,MDN - MediaRecorder 传送门

掘金上相关文章一搜一大把,我就不重复说了。这里念叨下大致流程吧:

  1. new 一个 MediaRecorder,将待录制的 stream 流传给他,并指定录制格式等参数
  2. 录制结束后,拿到 Blob 数组 blobs
  3. 将数组生成一个新的 Blob finalBlob
  4. finalBlob 转为可播放、下载的 Url var videoURL = URL.createObjectURL(finalBlob);
  5. 播放或者下载录制好的视频
    1. 播放: video.src = videoURL
    2. 下载: 使用 a 标签下载 a.href = videoURL

视频时长与进度条问题(一波未平一波又起)

录制下载搞定后,隔天我就屁颠屁颠找产品经理去了。

  • 我:经过我不懈努力,加班加点。不用找外厂商对接了,这个视频录制咱自己就能搞定,自己弄灵活性更高,不会受制与他们。巴拉巴拉一顿吹嘘
  • 产品:可以可以,不愧是我司栋梁,前途无量。走我去你那看看效果
  • one thousand years later
  • 产品:哎?你这个下载的视频,怎么时长时 00:00 呢?
  • 产品:哎?进度条也不好使,这什么情况?
  • 我:这个,,,,这不刚调研结束,demo还不完善,时长啥的我算一下就行,这就是给你看个录视频的效果,后续我把时长加上,都是小意思(求生欲爆棚)

正常来讲,音、视频的相关信息,都会在文件头中体现。而 MediaRecorder 的录制方式,最终得到的 blobs 是不存在音视频时长 Duration,进度条 Seek 等信息的。

还好我在掘金找到了 Electron / Chromium 屏幕录制 - 那些我踩过的坑,其中有一部分恰好解决了这个问题。

使用 Ebml 库

如果我们录制视频的时候,录制格式是 Webm 的,那么 Ebml 库就可以帮我们“优化” finalBlob 的头信息,计算视频的时长,并修复进度条等。

export async function getSeekableBlob(originBlob) {
  const Decoder = new EBML.Decoder();
  const buf = await originBlob.arrayBuffer()
  const ebmlElms = Decoder.decode(buf);

  const reader = new EBML.Reader();
  ebmlElms.forEach(element => {
    reader.read(element)
  });
  reader.stop();

  const refinedMetadataBuf = EBML.tools.makeMetadataSeekable(
    reader.metadatas,
    reader.duration,
    reader.cues
  )

  const body = buf.slice(reader.metadataSize)
  const aimBlob = new Blob([refinedMetadataBuf, body], {
    type: 'video/webm'
  })

  return aimBlob
}

后记

原字节的大兄弟的文章中提到,自己封了个库并上传到了 npm,但是我实际使用的时候发现有异常,可能和 vite 有关?

具体还没深究,最终我没用他的库,自己下载了 EBML.js 库,本地用的

代码已经上传到了 gitee.com/bigflowerfa…,有需要的大哥自取。