MediaStream Recording API - 捕获媒体生成的数据,以进行分析、处理或保存
MediaStream Recording API,有时也称为 Media Recording API 或 MediaRecorder API,与 Media Capture and Streams API 和 WebRTC API 密切相关。MediaStream Recording API 可以捕获由 MediaStream 或 HTMLMediaElement 对象生成的数据,以进行分析、处理或保存到磁盘。它也非常容易使用。
基本概念
MediaStream Recording API 由一个主要接口 MediaRecorder 组成,它完成从 MediaStream 获取数据并将其交付给您进行处理的所有工作。数据由一系列 dataavailable 事件提供,这些事件已经采用您在创建 MediaRecorder 时指定的格式。然后,您可以进一步处理数据或根据需要将其写入文件。
记录过程概述
记录流的过程很简单:
- 设置 
MediaStream或HTMLMediaElement(以<audio>或<video>的元素的形式)作为媒体数据的来源。 - 创建一个 
MediaRecorder对象,指定源流和任何所需的选项(例如容器的 MIME 类型或其轨道的所需比特率)。 - 将 
MediaRecorder.ondataavailable设置为dataavailable事件的事件处理程序;只要有数据可用,就会调用此方法。 - 一旦源媒体正在播放并且您已经准备好录制视频,请调用 
MediaRecorder.start()开始录制。 - 您的 
dataavailable事件处理程序在每次准备好数据时都会被调用;该事件有一个data属性,其值为包含媒体数据的Blob。您可以强制触发dataavailable事件,从而向您提供最新的声音,以便您可以对其进行过滤、保存或其他任何操作。 - 当源媒体停止播放时,录制会自动停止。
 - 您可以随时通过调用 
MediaRecorder.stop()来停止录制。 
注意: 包含录制媒体片段的单个
Blob不一定可以单独播放。媒体需要在播放前重新组装。
如果在录制过程中出现任何问题,error 事件将发送到 MediaRecorder 。您可以通过设置 onerror 事件处理程序来监听 error 事件。
例如,我们使用 HTML Canvas 作为 MediaStream 的源,并在 9 秒后停止录制。
var canvas = document.querySelector("canvas");
// 可选的每秒帧数参数。
var stream = canvas.captureStream(25);
var recordedChunks = [];
console.log(stream);
var options = { mimeType: "video/webm; codecs=vp9" };
mediaRecorder = new MediaRecorder(stream, options);
mediaRecorder.ondataavailable = handleDataAvailable;
mediaRecorder.start();
function handleDataAvailable(event) {
  console.log("data-available");
  if (event.data.size > 0) {
    recordedChunks.push(event.data);
    console.log(recordedChunks);
    download();
  } else {
    // ...
  }
}
function download() {
  var blob = new Blob(recordedChunks, {
    type: "video/webm"
  });
  var url = URL.createObjectURL(blob);
  var a = document.createElement("a");
  document.body.appendChild(a);
  a.style = "display: none";
  a.href = url;
  a.download = "test.webm";
  a.click();
  window.URL.revokeObjectURL(url);
}
// 演示:9 秒后下载
setTimeout(event => {
  console.log("stopping");
  mediaRecorder.stop();
}, 9000);
检查和控制记录器状态
您还可以使用 MediaRecorder 对象的属性来确定录制过程的状态,及其 pause() 和 resume() 方法来暂停和恢复源媒体的录制。
如果您需要或想要查看是否支持特定的 MIME 类型,这也是可能的。只需调用 MediaRecorder.isTypeSupported()。
检查潜在的输入源
如果您的目标是记录相机和 / 或麦克风输入,您可能希望在开始构建 MediaRecorder 的过程之前检查可用的输入设备。为此,您需要调用 navigator.mediaDevices.enumerateDevices() 以获取可用媒体设备的列表。然后,您可以检查该列表并确定潜在的输入源,甚至可以根据所需条件过滤该列表。
在此代码片段中,enumerateDevices() 用于检查可用的输入设备,定位音频输入设备,并创建 <option> 元素,然后将这些元素添加到 <select> 元素表示输入源选择器。
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
  devices.forEach(function(device) {
    let menu = document.getElementById("inputdevices");
    if (device.kind == "audioinput") {
      let item = document.createElement("option");
      item.innerText = device.label;
      item.value = device.deviceId;
      menu.appendChild(item);
    }
  });
});
与此类似的代码可用于让用户限制他们希望使用的设备集。
想要查询更多的信息
要了解有关使用 MediaStream Recording API 的更多信息,请参阅 使用 MediaStream Recording API,其中显示了如何使用 API 录制音频剪辑。第二篇文章 录制媒体元素 描述了如何从 <audio> 或 <video> 元素接收流并使用捕获的流(在本例中,记录它并将其保存到本地磁盘)。
参考
 BlobEvent
每次录制完一大块媒体数据时,它都会以 Blob 形式,通过 dataavailable 类型的 BlobEvent 将其交付给消费者。
 MediaRecorder
实现 MediaStream Recording API 的主要接口。
 MediaRecorderErrorEvent
表示 MediaStream Recording API 抛出的错误的接口。它的 error 属性是一个 DOMException 属性,它指定发生了错误。
规范
| 规范 | 状态 | 备注 | 
|---|---|---|
| MediaStream Recording | 工作草案 | 初始定义 | 
桌面浏览器兼容性
| 特性 | Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | 
|---|---|---|---|---|---|---|
| 基础支持 | 47 | 79 | 251 | 不支持 | 36 | 不支持 | 
MediaRecorder() 构造函数 | 47 | 79 | 25 | 不支持 | 36 | 不支持 | 
audioBitsPerSecond | 49 | 79 | 71 | 不支持 | 36 | 不支持 | 
error 事件 | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
ignoreMutedMedia | 49 — 57 | 不支持 | 未知 | 不支持 | 36 — 44 | 不支持 | 
isTypeSupported | 47 | 79 | 25 | 不支持 | 36 | 不支持 | 
mimeType | 49 47 — 492  | 79 | 253 | 不支持 | 36 | 不支持 | 
ondataavailable | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
onerror | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
onpause | 49 | 79 | 65 | 不支持 | 36 | 不支持 | 
onresume | 49 | 79 | 65 | 不支持 | 36 | 不支持 | 
onstart | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
onstop | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
onwarning | 49 | 79 | 25 — 71 | 不支持 | 36 | 不支持 | 
pause | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
requestData | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
resume | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
start | 47 | 79 | 25 | 不支持 | 36 | 不支持 | 
state | 49 47 — 492  | 79 | 25 | 不支持 | 36 | 不支持 | 
stop | 49 | 79 | 25 | 不支持 | 36 | 不支持 | 
stream | 49 47 — 492  | 79 | 25 | 不支持 | 36 | 不支持 | 
videoBitsPerSecond | 49 | 79 | 71 | 不支持 | 36 | 不支持 | 
warning 事件 | 49 | 79 | 25 — 71 | 不支持 | 36 | 不支持 | 
移动浏览器兼容性
| 特性 | Android | Chrome for Android | Edge mobile | Firefox for Android | IE mobile | Opera Android | iOS Safari | 
|---|---|---|---|---|---|---|---|
| 基础支持 | 47 | 47 | 未知 | 251 | 未知 | 36 | 不支持 | 
MediaRecorder() 构造函数 | 47 | 47 | 未知 | 25 | 未知 | 36 | 不支持 | 
audioBitsPerSecond | 49 | 49 | 未知 | 未知 | 未知 | 36 | 不支持 | 
error 事件 | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
ignoreMutedMedia | 49 — 57 | 49 — 57 | 未知 | 未知 | 未知 | 36 — 44 | 不支持 | 
isTypeSupported | 47 | 47 | 未知 | 25 | 未知 | 36 | 不支持 | 
mimeType | 49 47 — 492  | 49 47 — 492  | 未知 | 25 | 未知 | 36 | 不支持 | 
ondataavailable | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
onerror | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
onpause | 49 | 49 | 未知 | 65 | 未知 | 36 | 不支持 | 
onresume | 49 | 49 | 未知 | 65 | 未知 | 36 | 不支持 | 
onstart | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
onstop | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
onwarning | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
pause | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
requestData | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
resume | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
start | 47 | 47 | 未知 | 25 | 未知 | 36 | 不支持 | 
state | 49 47 — 492  | 49 47 — 492  | 未知 | 25 | 未知 | 36 | 不支持 | 
stop | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
stream | 49 | 49 47 — 492  | 未知 | 25 | 未知 | 36 | 不支持 | 
videoBitsPerSecond | 49 | 49 | 未知 | 未知 | 未知 | 36 | 不支持 | 
warning 事件 | 49 | 49 | 未知 | 25 | 未知 | 36 | 不支持 | 
1. 在 Firefox 58 之前,在使用 getUserMedia() 获取的流上使用 code>MediaStream.addTrack(),然后尝试记录结果流将导致仅记录没有添加轨道的原始流(严重错误)。
2. 在 Chrome 49 之前,只支持视频,不支持音频。
3. 从 Firefox 71 开始, mimeType 的行为更加一致。例如,它现在即使在录制停止后也会返回媒体类型。