MediaStream Recording API

MediaStream Recording API 有时简称为 Media Recording API 或者 MediaRecorder API,与媒体捕捉与媒体流 APIWebRTC API 密切相关。MediaStream Recording API 使得捕获通过 MediaStream 或者HTMLMediaElement 对象产生的用于分析、加工或者保存到硬盘的数据成为可能。它也非常容易让人们使用。

基本概念

MediaStream Recording API 由一个主接口MediaRecorder组成,这个接口负责的所有工作是从MediaStream获取数据并将其传递给你进行处理。数据通过一系列 dataavailable 事件传递,这些数据已经成为你创建 MediaRecorder 时所声明的格式。然后,你可以进一步处理数据,或者根据需要将其写入文件。

录制过程概述

记录一个流的过程是非常容易的:

  1. 建立一个 MediaStream或者HTMLMediaElement (以 <audio><video> 元素的形式) 来充当媒体数据的源。
  2. 创建一个 MediaRecorder 对象,指定源以及任何有需求的选项 (比如容器的 MIME 类型或它轨道所需的比特率).
  3. dataavailable 事件设置MediaRecorder.ondataavailable 事件处理函数; 会在数据可利用时候调用。
  4. 一旦媒体源播放,你已经准备好录制,使用 MediaRecorder.start() 开始录制。
  5. dataavailable 事件处理函数正如你所愿的在每次数据准备好时调用; 这个事件有一个值为包含媒体数据的Blob 类型的 data 属性。你可以强制 dataavailable 事件发生,因此会给你传递最新的声音以至于可以让你过滤、保存或者做一些其他的事情。
  6. 当源媒体停止播放时候,录制自动结束。
  7. 你可以随时结束录制通过使用 MediaRecorder.stop().

备注: 单单使用包含已经录制好媒体切片的Blobs 将大可不能单独播放。媒体在重放之前需要重新组装。

如果在录制过程中出错,error 事件将会传给MediaRecorder. 你可以设置onerror去监听 error 事件。

例子中,我们使用 Canvas 作为MediaStream的源,在 9 秒后停止录音。

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

// Optional frames per second argument.
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);
}

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

检查 and 控制记录器的状态

你也可以使用 MediaRecorder 对象的属性去决定录制过程的状态,用 pause()resume() 方法暂停或者继续媒体源的录制。

如果你需要检查一个特殊的 MIME 类型是否被支持,使用MediaRecorder.isTypeSupported().

检查潜在的输入源

如果你的目标是记录摄像头或麦克风输入,你可能希望在构建 MediaRecorder 之前检查可用的输入设备。这时,你需要调用 navigator.mediaDevices.enumerateDevices() 来得到可使用的媒体设备。你可以检查此列表,发现潜在的设备,甚至在有需要的时候过滤掉设备。

在这块代码中,enumerateDevices() 被用来检查可利用的设备,找到那些音频输入设备,创建<option> 元素,之后添加到<select>元素,代表输入源选择器 .

js
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.innerHTML = device.label;
      item.value = device.deviceId;
      menu.appendChild(item);
    }
  });
});

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

更多信息

更多关于 MediaStream Recording API 的使用,查看 Using the MediaStream Recording API, 这个显示了如何使用 API 来记录音频剪辑。另一篇文章,Recording a media element, 介绍了如何从 <audio><video> 元素 接收信息流和如何使用接收到的信息流(这个案例中,接收、存到硬盘)。

参考

BlobEvent

Each time a chunk of media data is finished being recorded, it's delivered to consumers in Blob form using a BlobEvent of type dataavailable.

MediaRecorder

The primary interface that implements the MediaStream Recording API.

MediaRecorderErrorEvent

The interface that represents errors thrown by the MediaStream Recording API. Its error property is a DOMException that specifies that error occurred.

规范

Specification
MediaStream Recording

浏览器兼容性

Report problems with this compatibility data on GitHub
desktopmobile
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
MediaRecorder
MediaRecorder() constructor
options parameter
audioBitrateMode
Experimental
audioBitsPerSecond
dataavailable event
error event
isTypeSupported() static method
mimeType
pause
pause event
requestData
resume
resume event
start
start event
state
stop
stop event
stream
videoBitsPerSecond

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support
Partial support
Partial support
No support
No support
Experimental. Expect behavior to change in the future.
See implementation notes.
Has more compatibility info.

参阅