Web Real-Time Communications 实时通信技术
前阵子,产品经理找到我
- 产品:咱们有视频录制、下载功能吗?
- 我:(擦?又想加需求?)没有,不支持
- 产品:那行吧,你准备准备,要出差了,外厂商有视频录制的接口,咱实现不了,那就过去对接一下
- 我:(???)等下,好像可以有,我回去试试 🐶
视频录制与下载
用过 MediaRecorder 的朋友都知道,这玩意儿录视频贼简单,很少的代码量就能实现录制,MDN - MediaRecorder 传送门
掘金上相关文章一搜一大把,我就不重复说了。这里念叨下大致流程吧:
- new 一个 MediaRecorder,将待录制的 stream 流传给他,并指定录制格式等参数
- 录制结束后,拿到 Blob 数组
blobs - 将数组生成一个新的 Blob
finalBlob - 将
finalBlob转为可播放、下载的 Urlvar videoURL = URL.createObjectURL(finalBlob); - 播放或者下载录制好的视频
- 播放:
video.src = videoURL - 下载: 使用 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…,有需要的大哥自取。