MediaStream Recording API

Baseline Widely available *

This feature is well established and works across many devices and browser versions. It’s been available across browsers since April 2021.

* Some parts of this feature may have varying levels of support.

MediaStream Recording API, đôi khi được gọi là Media Recording API hoặc MediaRecorder API, có liên kết chặt chẽ với Media Capture and Streams APIWebRTC API. MediaStream Recording API giúp có thể thu thập dữ liệu được tạo bởi đối tượng MediaStream hoặc HTMLMediaElement để phân tích, xử lý hoặc lưu vào đĩa. Nó cũng khá dễ làm việc.

Khái niệm và cách sử dụng

MediaStream Recording API được tạo thành từ một giao diện chính, MediaRecorder, thực hiện tất cả công việc lấy dữ liệu từ MediaStream và cung cấp cho bạn để xử lý. Dữ liệu được gửi qua một loạt các sự kiện dataavailable, đã ở định dạng bạn chỉ định khi tạo MediaRecorder. Sau đó bạn có thể xử lý thêm dữ liệu hoặc ghi vào tệp theo ý muốn.

Tổng quan về quá trình ghi

Quá trình ghi một luồng rất đơn giản:

  1. Thiết lập MediaStream hoặc HTMLMediaElement (dưới dạng phần tử <audio> hoặc <video>) để phục vụ làm nguồn dữ liệu phương tiện.
  2. Tạo đối tượng MediaRecorder, chỉ định luồng nguồn và bất kỳ tùy chọn nào (chẳng hạn loại MIME của container hoặc tốc độ bit mong muốn của các track của nó).
  3. Đặt ondataavailable thành trình xử lý sự kiện cho sự kiện dataavailable; điều này sẽ được gọi bất cứ khi nào có dữ liệu sẵn sàng cho bạn.
  4. Sau khi phương tiện nguồn đang phát và bạn đã đến thời điểm sẵn sàng ghi video, hãy gọi MediaRecorder.start() để bắt đầu ghi.
  5. Trình xử lý sự kiện dataavailable của bạn được gọi mỗi khi có dữ liệu sẵn sàng; sự kiện có thuộc tính data có giá trị là Blob chứa dữ liệu phương tiện. Bạn có thể buộc sự kiện dataavailable xảy ra, qua đó gửi âm thanh mới nhất cho bạn để bạn có thể lọc, lưu hoặc làm bất cứ điều gì.
  6. Ghi dừng tự động khi phương tiện nguồn ngừng phát.
  7. Bạn có thể dừng ghi bất cứ lúc nào bằng cách gọi MediaRecorder.stop().

Note: Các Blob riêng lẻ chứa các phần của phương tiện được ghi không nhất thiết phải phát được riêng lẻ. Phương tiện cần được lắp ráp lại trước khi phát.

Nếu có gì đó xảy ra sai trong khi ghi, sự kiện error được gửi đến MediaRecorder. Bạn có thể lắng nghe các sự kiện error bằng cách thiết lập trình xử lý sự kiện onerror.

Ví dụ ở đây, chúng ta sử dụng HTML Canvas làm nguồn của MediaStream, và dừng ghi sau 9 giây.

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);

Kiểm tra và kiểm soát trạng thái trình ghi

Bạn cũng có thể sử dụng các thuộc tính của đối tượng MediaRecorder để xác định trạng thái của quá trình ghi, cùng với các phương thức pause()resume() để tạm dừng và tiếp tục ghi phương tiện nguồn.

Nếu bạn cần kiểm tra xem loại MIME cụ thể có được hỗ trợ không, điều đó cũng có thể. Chỉ cần gọi MediaRecorder.isTypeSupported().

Kiểm tra các nguồn đầu vào tiềm năng

Nếu mục tiêu của bạn là ghi đầu vào camera và/hoặc micrô, bạn có thể muốn kiểm tra các thiết bị đầu vào có sẵn trước khi bắt đầu quá trình xây dựng MediaRecorder. Để làm vậy, bạn cần gọi navigator.mediaDevices.enumerateDevices() để lấy danh sách các thiết bị phương tiện có sẵn. Sau đó bạn có thể kiểm tra danh sách đó và xác định các nguồn đầu vào tiềm năng, thậm chí lọc danh sách dựa trên tiêu chí mong muốn.

Trong đoạn mã này, enumerateDevices() được sử dụng để kiểm tra các thiết bị đầu vào có sẵn, xác định những thiết bị là thiết bị đầu vào âm thanh và tạo các phần tử <option> sau đó được thêm vào phần tử <select> đại diện cho bộ chọn nguồn đầu vào.

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);
    }
  });
});

Mã tương tự có thể được sử dụng để cho phép người dùng giới hạn tập hợp thiết bị họ muốn sử dụng.

Để biết thêm thông tin

Để tìm hiểu thêm về việc sử dụng MediaStream Recording API, xem Using the MediaStream Recording API, cho thấy cách sử dụng API để ghi các clip âm thanh. Bài viết thứ hai, Recording a media element, mô tả cách nhận luồng từ phần tử <audio> hoặc <video> và sử dụng luồng đã thu (trong trường hợp này là ghi và lưu vào đĩa cục bộ).

Giao diện

BlobEvent

Mỗi khi một đoạn dữ liệu phương tiện hoàn thành việc ghi, nó được gửi đến người dùng ở dạng Blob bằng cách sử dụng BlobEvent loại dataavailable.

MediaRecorder

Giao diện chính triển khai MediaStream Recording API.

MediaRecorderErrorEvent Deprecated Non-standard

Giao diện đại diện cho các lỗi do MediaStream Recording API ném ra. Thuộc tính error của nó là DOMException chỉ định lỗi đã xảy ra.

Ví dụ

Ghi video cơ bản

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");
  }
});

Thông số kỹ thuật

Specification
MediaStream Recording

Tương thích trình duyệt

Xem thêm