MediaStream Recording API

Baseline 广泛可用 *

此特性已得到良好支持,可在多种设备和浏览器版本上使用。自 2021 年 4 月起,所有浏览器均已支持此特性。

* 此特性的某些部分可能存在不同级别的支持。

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. ondataavailable 设置为 dataavailable 事件的处理程序;每当有可用数据时,都会调用此处理程序。
  4. 一旦源媒体开始播放,并且您已准备好录制视频,请调用 MediaRecorder.start() 开始录制。
  5. 您的 dataavailable 事件处理程序会在每次有数据准备好供您使用时被调用;该事件有一个 data 属性,其值是一个包含媒体数据的 Blob。您可以强制触发一个 dataavailable 事件,从而将最新的声音传递给您,以便您可以对其进行过滤、保存或其他操作。
  6. 源媒体停止播放时,录制会自动停止。
  7. 您可以通过调用 MediaRecorder.stop() 随时停止录制。

注意:包含录制媒体切片的单个 Blob 不一定能单独播放。需要先将媒体重新组合才能播放。

如果在录制过程中发生任何错误,将向 MediaRecorder 发送一个 error 事件。您可以通过设置 onerror 事件处理程序来监听 error 事件。

在此示例中,我们使用 HTML Canvas 作为 MediaStream 的源,并在 9 秒后停止录制。

js
const canvas = document.querySelector("canvas");

// Optional frames per second argument.
const stream = canvas.captureStream(25);
const recordedChunks = [];

console.log(stream);
const options = { mimeType: "video/webm; codecs=vp9" };
const 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() {
  const blob = new Blob(recordedChunks, {
    type: "video/webm",
  });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  document.body.appendChild(a);
  a.style = "display: none";
  a.href = url;
  a.download = "test.webm";
  a.click();
  URL.revokeObjectURL(url);
}

// demo: to download after 9sec
setTimeout((event) => {
  console.log("stopping");
  mediaRecorder.stop();
}, 9000);

检查和控制录制器状态

您还可以使用 MediaRecorder 对象的属性来确定录制过程的状态,并使用其 pause()resume() 方法来暂停和恢复源媒体的录制。

如果您需要或想检查特定 MIME 类型是否受支持,这也是可能的。只需调用 MediaRecorder.isTypeSupported() 即可。

检查潜在的输入源

如果您的目标是录制摄像头和/或麦克风输入,您可能希望在开始构造 MediaRecorder 之前检查可用的输入设备。为此,您需要调用 navigator.mediaDevices.enumerateDevices() 来获取可用媒体设备列表。然后,您可以检查该列表并识别潜在的输入源,甚至可以根据所需的条件过滤列表。

在此代码片段中,enumerateDevices() 用于检查可用的输入设备,找到音频输入设备,并创建 <option> 元素,然后将这些元素添加到代表输入源选择器的 <select> 元素中。

js
navigator.mediaDevices.enumerateDevices().then((devices) => {
  devices.forEach((device) => {
    const menu = document.getElementById("input-devices");
    if (device.kind === "audioinput") {
      const item = document.createElement("option");
      item.textContent = device.label;
      item.value = device.deviceId;
      menu.appendChild(item);
    }
  });
});

可以使用类似的代码让用户限制他们希望使用的设备集。

了解更多信息

要了解更多关于使用 MediaStream Recording API 的信息,请参阅 使用 MediaStream Recording API,其中介绍了如何使用该 API 录制音频片段。第二篇文章 录制媒体元素 描述了如何从 <audio><video> 元素接收流,并使用捕获的流(在此案例中,将其录制并保存到本地磁盘)。

接口

BlobEvent

每次录制完一块媒体数据后,它都会通过类型为 dataavailableBlobEventBlob 形式传递给消费者。

MediaRecorder

实现 MediaStream Recording API 的主要接口。

MediaRecorderErrorEvent 已弃用 非标准

表示 MediaStream Recording API 抛出错误的接口。其 error 属性是一个 DOMException,指定了发生的错误。

示例

基本视频录制

html
<button id="record-btn">Start</button>
<video id="player" src="" autoplay controls></video>
js
const recordBtn = document.getElementById("record-btn");
const video = document.getElementById("player");

let chunks = [];
let isRecording = false;
let mediaRecorder = null;

const constraints = { video: true };

recordBtn.addEventListener("click", async () => {
  if (!isRecording) {
    // Acquire a recorder on load
    if (!mediaRecorder) {
      const stream = await navigator.mediaDevices.getUserMedia(constraints);
      mediaRecorder = new MediaRecorder(stream);
      mediaRecorder.addEventListener("dataavailable", (e) => {
        console.log("data available");
        chunks.push(e.data);
      });
      mediaRecorder.addEventListener("stop", (e) => {
        console.log("onstop fired");
        const blob = new Blob(chunks, { type: "video/ogv; codecs=opus" });
        video.src = window.URL.createObjectURL(blob);
      });
      mediaRecorder.addEventListener("error", (e) => {
        console.error("An error occurred:", e);
      });
    }
    isRecording = true;
    recordBtn.textContent = "Stop";
    chunks = [];
    mediaRecorder.start();
    console.log("recorder started");
  } else {
    isRecording = false;
    recordBtn.textContent = "Start";
    mediaRecorder.stop();
    console.log("recorder stopped");
  }
});

规范

规范
MediaStream Recording

浏览器兼容性

另见