概述
Media Recorder, 顾名思义是控制媒体录制的 API, 在原生 App 开发中, 是一个应用广泛的 API, 用于在 App 内录制音频和视频.
事实上, 随着 web 侧的应用越来越富媒体化, w3c 也制定了相应的 Web 标准, 称为 MediaRecorder API(旧称 MediaStream Recording API), 它给我们的 Web 页面赋予了录制音视频的能力, 使得 Web 可以脱离服务器, 客户端的辅助, 独立进行媒体流的录制.
该 API 从 2013 年指定, 2016 年后开始频繁修订, 对于大多数开发者而言是较为陌生的. 本文将结合官方文档和实际案例, 对它进行一些说明解释.
什么可以录?
任何媒体形式的标签, 包括 <audio>, <video>,<canvas>, 其中 <audio>, <video > 可以来自网络媒体文件, 也可以来自本机设备采集. 而 < canvas > 的内容则更加自由, 任何绘制在画布上的用户操作, 2d 或 3d 图像, 都可以进行录制. 它为 Web 提供了更多可能性, 我们甚至可以把一个 h5 游戏流程录成视频, 保存落地或进行实况传输.
录出来的是什么?
是经过标准编码后的媒体流数据, 可以注入 video 标签, 也可以打包生成文件, 还可以进一步流级别的数据处理, 比如画面识别, 动态插入内容, 播放跳转控制等等.
视频编码格式?
编码过程由浏览器实现, 依赖浏览器的能力, 因为该标准由 w3c 推进, 目前主要的试验田在 Chrome 和 Firefox, 移动端兼容安卓内置的 Chrome 内核浏览器. iOS 和 IE 暂时无解.
该标准本身也为我们提供了检测浏览器编码能力的 API
MediaRecorder.isTypeSupported(format)
可以把下面这段代码贴进 console, 来测试当前浏览器的支持状况.
- var types = ["video/webm",
- "audio/webm",
- "video/webm\;codecs=vp8",
- "video/webm\;codecs=daala",
- "video/webm\;codecs=h264",
- "audio/webm\;codecs=opus",
- "video/mpeg"];
- for (var i in types) {
- console.log( "Is" + types[i] + "supported?" + (MediaRecorder.isTypeSupported(types[i]) ? "Maybe!" : "Nope :("));
- }
上述代码来自官方开发文档.
为什么对于支持的格式, 官方给出的答案是 Maybe 呢?
因为就算编码格式支持, 也有可能因为计算资源不足而导致编码失败. 所以该 API 仅作为筛选判断, 实际应用中, 还需要做好错误处理.
MediaRecorder 工作流程
MediaRecorder 在支持的浏览器中表现为是一个全局对象, 下面是一个完整可用的例子, 请用 Chrome 或者 FF 打开.
MediaRecorder 使用示例
该例子中, 把 video 标签的内容放进了 canvas 里, 与用户点击时在 canvas 上绘制图案的过程一起, 通过 MediaRecorder 对象提供的 captureStream 方法录制下来, 合并成一个视频文件并保存.
除了固定的标签之外, 我们还可以调取摄像头作为视频的内容.
MediaRecorder 使用示例 - 摄像头版
具体过程和上面类似, 只是多了一步从摄像头中获取视频, 放入 canvas 中渲染的过程.
使用 API 录制 Canvas 核心代码如下
- let allChunks = [];
- let format='video/webm;codecs=vp9'
- const stream = canvas.captureStream(60); // 录制帧率 60fps
- const recorder = new MediaRecorder(stream, {
- mimeType: format
- });
- recorder.ondataavailable = e => {
- allChunks.push(
- e.data
- );
- }
之后把 allChunks 放进一个 blob 对象, 即可实现下载
- const fullBlob = new Blob(allChunks);
- const downloadUrl = Windows.URL.createObjectURL(fullBlob);
- link.href = downloadUrl;
- link.download = 'media.mp4';
完整代码请看参见案例工程目录
录制出的流是完整有效的吗?
我们知道一个完整的媒体文件中, 流数据的组成是很复杂的, 包括头文件, 预测帧等等, 当我们开始录制后, 不一定马上就能获得可播放的文件.
所以, 该 API 提供了一个事件, ondataavailable, 当浏览器的录制编码进程积攒出可以使用的媒体数据后, 就会抛出该事件, 告诉我们 "录制的数据已经可用了", 把数据移交给用户做进一步处理.
我们可以打开样例中的开关, 来观察 console 中这个 data 被抛出的过程.
有没有替代方案?
由于媒体编码依赖浏览器底层的实现, 所以很难在代码层面进行 polyfill. 在采集设备音频的场景下, 可以使用使用 AudioNodes 替代, 视频和 canvas 暂时无解.
和 WebRTC 的关系?
其实两者不是同一个层面的概念, Web Real-Time Communication(Web 实时通信, WebRTC) 由一组标准, 由一系列 Web API 组成, 从采集, 编码到通信层面都有涉及. 而 Media Recorder 只是对 WebRTC 方案做了一个补充, 为录制后的视频提供了一个落地方案.
二者都是由 w3c 制定并致力推进, 但 iOS 和微软反应冷淡, 所以目前的兼容性都不理想, 还停留在实验阶段. 期待 Web 标准化进程持续推进, 进一步解放开发者的生产力, 使 Web 应用更加天马行空.
来源: https://www.qcloud.com/developer/article/1366886