MediaStream Recording API - 捕获媒体生成的数据,以进行分析、处理或保存

MediaStream Recording API,有时也称为 Media Recording APIMediaRecorder API,与 Media Capture and Streams APIWebRTC API 密切相关。MediaStream Recording API 可以捕获由 MediaStreamHTMLMediaElement 对象生成的数据,以进行分析、处理或保存到磁盘。它也非常容易使用。

基本概念

MediaStream Recording API 由一个主要接口 MediaRecorder 组成,它完成从 MediaStream 获取数据并将其交付给您进行处理的所有工作。数据由一系列 dataavailable 事件提供,这些事件已经采用您在创建 MediaRecorder 时指定的格式。然后,您可以进一步处理数据或根据需要将其写入文件。

记录过程概述

记录流的过程很简单:

  1. 设置 MediaStreamHTMLMediaElement(以 <audio><video> 的元素的形式)作为媒体数据的来源。
  2. 创建一个 MediaRecorder 对象,指定源流和任何所需的选项(例如容器的 MIME 类型或其轨道的所需比特率)。
  3. MediaRecorder.ondataavailable 设置为 dataavailable 事件的事件处理程序;只要有数据可用,就会调用此方法。
  4. 一旦源媒体正在播放并且您已经准备好录制视频,请调用 MediaRecorder.start() 开始录制。
  5. 您的 dataavailable 事件处理程序在每次准备好数据时都会被调用;该事件有一个 data 属性,其值为包含媒体数据的 Blob。您可以强制触发 dataavailable 事件,从而向您提供最新的声音,以便您可以对其进行过滤、保存或其他任何操作。
  6. 当源媒体停止播放时,录制会自动停止。
  7. 您可以随时通过调用 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 工作草案 初始定义

桌面浏览器兼容性

特性ChromeEdgeFirefoxInternet ExplorerOperaSafari
基础支持4779251 不支持36 不支持
MediaRecorder() 构造函数477925 不支持36 不支持
audioBitsPerSecond497971 不支持36 不支持
error 事件497925 不支持36 不支持
ignoreMutedMedia49 — 57 不支持 未知 不支持36 — 44 不支持
isTypeSupported477925 不支持36 不支持
mimeType

49

47 — 492

79253 不支持36 不支持
ondataavailable497925 不支持36 不支持
onerror497925 不支持36 不支持
onpause497965 不支持36 不支持
onresume497965 不支持36 不支持
onstart497925 不支持36 不支持
onstop497925 不支持36 不支持
onwarning497925 — 71 不支持36 不支持
pause497925 不支持36 不支持
requestData497925 不支持36 不支持
resume497925 不支持36 不支持
start477925 不支持36 不支持
state

49

47 — 492

7925 不支持36 不支持
stop497925 不支持36 不支持
stream

49

47 — 492

7925 不支持36 不支持
videoBitsPerSecond497971 不支持36 不支持
warning 事件497925 — 71 不支持36 不支持

移动浏览器兼容性

特性AndroidChrome for AndroidEdge mobileFirefox for AndroidIE mobileOpera AndroidiOS Safari
基础支持4747 未知251 未知36 不支持
MediaRecorder() 构造函数4747 未知25 未知36 不支持
audioBitsPerSecond4949 未知 未知 未知36 不支持
error 事件4949 未知25 未知36 不支持
ignoreMutedMedia49 — 5749 — 57 未知 未知 未知36 — 44 不支持
isTypeSupported4747 未知25 未知36 不支持
mimeType

49

47 — 492

49

47 — 492

未知25 未知36 不支持
ondataavailable4949 未知25 未知36 不支持
onerror4949 未知25 未知36 不支持
onpause4949 未知65 未知36 不支持
onresume4949 未知65 未知36 不支持
onstart4949 未知25 未知36 不支持
onstop4949 未知25 未知36 不支持
onwarning4949 未知25 未知36 不支持
pause4949 未知25 未知36 不支持
requestData4949 未知25 未知36 不支持
resume4949 未知25 未知36 不支持
start4747 未知25 未知36 不支持
state

49

47 — 492

49

47 — 492

未知25 未知36 不支持
stop4949 未知25 未知36 不支持
stream49

49

47 — 492

未知25 未知36 不支持
videoBitsPerSecond4949 未知 未知 未知36 不支持
warning 事件4949 未知25 未知36 不支持

1. 在 Firefox 58 之前,在使用 getUserMedia() 获取的流上使用 code>MediaStream.addTrack(),然后尝试记录结果流将导致仅记录没有添加轨道的原始流(严重错误)。

2. 在 Chrome 49 之前,只支持视频,不支持音频。

3. 从 Firefox 71 开始, mimeType 的行为更加一致。例如,它现在即使在录制停止后也会返回媒体类型。