2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

画面キャプチャ API と MediaStream 収録 API を使ってみた

Last updated at Posted at 2023-02-02

画面をキャプチャしたり、それを収録できる面白そうな API を見つけたので使ってみました。

作ったもの

恐竜ゲームをキャプチャしている様子です。🦖
GitHub Pages で公開しています。

Screen Capture API でキャプチャする

キャプチャを開始する

MediaDevices.getDisplayMedia() を使って画面をキャプチャできます。
このメソッドを実行すると、キャプチャしたいタブやウィンドウを選択するポップアップが表示されます。

キャプチャできないときは、ブラウザに画面収録を許可しているか確認してみてください。
https://support.apple.com/ja-jp/guide/mac-help/mchld6aa7d23/mac

オプションの引数では、キャプチャする動画や音声などの詳細な設定ができます。
https://www.w3.org/TR/screen-capture/#constrainable-properties

const stream = await navigator.mediaDevices.getDisplayMedia({
  video: {
    // 解像度
    width: 1920,
    height: 1080,

    // フレームレート
    frameRate: 60
  },

  // 音声なし
  audio: false
});

戻り値として MediaStream で解決する Promise を返します。
MediaStream は、キャプチャされた動画や音声のトラック (MediaStreamTrack) を含んだオブジェクトです。

この MediaStream は、そのまま HTMLMediaElement.srcObject に設定して <video> で再生したり、後述の MediaStream Recording API を使って収録したり、などなどできます。

キャプチャを終了する

ストリームのすべてのトラックを停止します。

  1. MediaStream.getTracks() でストリームのすべてのトラックを取得します。
  2. MediaStreamTrack.stop() でトラックを停止します。
const tracks = stream.getTracks();

tracks.forEach((track) => {
  track.stop();
});

MediaStreamTrackended イベントを使用すると、ブラウザの「共有を停止」を押したり、タブやウィンドウを閉じたりして画面共有が停止されたことを検知できます。
MediaStreamTrack.stop() でトラックを停止した場合は ended イベントは発生しません。

stop-sharing.png

const [ track ] = stream.getTracks();

track.addEventListener('ended', () => {
  console.log('キャプチャが停止されました。');
});

MediaStream Recording API で収録する

レコーダーを作成する

まず MediaStream を収録するための MediaRecorder を作成します。

MediaRecorder() の第 1 引数には、収録したい MediaStream を渡します。
オプションの第 2 引数では、MIME タイプやビットレートの設定ができます。

const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });

収録を開始する

MediaRecorder.start() で収録を開始します。
オプションの引数には、一度に収録する長さをミリ秒で指定できます。
例えば start(1000) と指定した場合は 1 秒ごとに分割して収録できます。

このメソッドを実行すると start イベントが発生します。
また、オプションの引数を渡した場合は、指定したミリ秒ごとに dataavailable イベントが発生します。

// 1000 ミリ秒ごとに Blob に収録する
recorder.start(1000);

収録を停止する

MediaRecorder.stop() で収録を停止します。
このメソッドを実行すると stop イベントが発生します。

recorder.stop();

また、収録中にキャプチャ(ストリーム)が終了した場合は、自動的に収録が停止されます。

収録を一時停止する

MediaRecorder.pause() で収録を一時停止します。
このメソッドを実行すると pause イベントが発生します。

recorder.pause();

収録を再開する

MediaRecorder.resume() で収録を再開します。
このメソッドを実行すると pause イベントが発生します。

recorder.pause();

収録したデータを使用する

dataavailable のイベントハンドラーの引数には BlobEvent が渡されます。
この BlobEvent.data に収録されたデータを含む Blob が入っています。

recorder.addEventListener('dataavailable', (event) => {
  const blob = event.data;
});
  • MediaRecorder.start() に引数を指定しない場合は、dataavailable イベントは収録停止時に 1 度だけ発生します。
  • MediaRecorder.start() に引数を指定した場合は、dataavailable イベントは指定したミリ数ごとに発生します。

MediaRecorder.requestData() を実行すると、収録中または一時停止中の任意のタイミングで dataavailable イベントを発生させることができます。
このメソッドを実行しても収録は停止されませんが、これ以降に収録したデータは新しい Blob に格納されます。

recorder.requestData();

(async () => {
  // 収録された細切れのデータをあつめる
  let chunks = [];

  // 動画と音声をキャプチャする
  const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });

  // キャプチャした動画と音声を WebM 形式で収録する
  const recorder = new MediaRecorder(stream, { mimeType: 'video/webm' });

  // 収録を開始する
  recorder.start(1000);

  // 10 秒後に収録を停止する
  setTimeout(() => recorder.stop(), 10000);

  // start() に指定した 1 秒ごとに dataavailable イベントが発生する
  recorder.addEventListener('dataavailable', (event) => {
    // 収録された細切れのデータをあつめる
    chunks.push(event.data);
  });

  // 収録停止時に stop イベントが発生する
  recorder.addEventListener('stop', () => {
    // Blob の配列から 1 つの File を作る
    // これをダウンロードしたり、サーバーに送信したりして使えます
    const file = new File(chunks, 'screen-recording.webm', { type: 'video/webm' });
    console.log(file);
  });
})();

関連している API / 組み合わせて使うと面白そうな API

MediaDevices.getUserMedia()

こちらはカメラやマイクからの入力を MediaStream として取得できます。
MediaDevices.getDisplayMedia() と使い方も似ています。

HTMLCanvasElement.captureStream()

<canvas> の描画内容を MediaStream として取得できます。
WebSocket などと組み合わせておえかきの森みたいなアプリも作れそうです。

WebRTC API

動画や音声、テキストなどのデータを P2P で送受信できます。
MediaStream を使って相手に画面を共有したり、ビデオ通話したりできます。

IndexedDB API

クライアントサイドの Key-Value データベースです。
大容量でさまざまな型のデータを保存することができます。

収録した動画をブラウザに保存しておきたいときなどに使えます。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?