Javascript の MediaStream API で PC の画面録画をする方法

Javascript (JS) には MediaStream API という画面録画ができる機能があります。

これを使うことで、画面録画ソフトをダウンロードしなくても画面録画ができます。

ただし PC のみの対応で、モバイル端末には対応していません。

また、安全なコンテキスト (https 環境下、ローカルファイル、localhost) でのみ使えます。

新しい機能のため、OS やブラウザにより対応にバラツキがあり要注意です。

MediaStream API の対応

まず、ブラウザによって録画に対応する動画ファイルの種類が異なります。

ブラウザ動画ファイルの種類
Chromemp4、webm
Safarimp4
FireFoxwebm

さらに、ブラウザや OS によって音声録画の対応が異なります

OSとブラウザ音声録画の対応
Windows 版 Chrome画面全体の音声
Mac 版 Chromeブラウザのタブの音声のみ
Safari非対応
FireFox非対応

Edge は確認していませんが Chrome と同じだと思われます。

MediaStream API で画面録画する方法

以下の JS コードを実行していきます。

1. 対応する動画ファイルの種類を選ぶ

ブラウザにより対応する動画ファイルの種類が異なります。

そこで、MediaRecorder.isTypeSupported() を使います。

引数に動画ファイルの MIME タイプを入れて実行すると、その MIME タイプに対応しているなら true、非対応なら false を返します。

例えば mp4 に対応しているか確認するには MediaRecorder.isTypeSupported('video/mp4') を実行します。

以下のコードを使うと対応しているものを自動選択してくれます。

const mime_type =
  ['video/mp4', 'video/webm'].find((mt) => MediaRecorder.isTypeSupported(mt));

2. navigator.mediaDevices.getDisplayMedia() を実行

画面録画をするにはまずユーザーに画面共有をしてもらう必要があります。

まずは以下のJS コードを実行します。

navigator.mediaDevices.getDisplayMedia({ video: true, audio: true });

すると、画面共有の共有範囲を選ぶ画面が出てきます。

3. MediaStream オブジェクトを取り出す

値は Promise の形式で返ってくるので、Promise の result を取り出します。

navigator.mediaDevices.getDisplayMedia({ video: true, audio: true })
  .then((stream) => { console.log(stream) });

画面共有をオンにすると「MediaStream オブジェクト」が返り、画面共有をキャンセルするとエラーを返します。

画面共有がオンになると、録画マークなどが表示され共有中であることを示す表示になります。

4. MediaRecorder オブジェクトを作成する

返ったMediaStream オブジェクトを使って「MediaRecorder オブジェクト」を作成します。

const recorder = new MediaRecorder(stream, { mimeType: mime_type });

5. 録画の開始、停止

画面録画を開始するには

recorder.start();

停止するには

recorder.stop();

を実行します。

6. 録画停止を検知する

録画停止を検知するには dataavailable イベントの発生を検知します。

recorder.addEventListener('dataavailable', (event) => { console.log(event.data); });

この変数 event に「BlobEvent オブジェクト」が入っています。

event.data に「Blob オブジェクト」の形で録画データが入ります。

7. 録画データを対応するファイル形式に変換

録画データが入った Blob オブジェクト (event.data) を使って、録画データを対応する形式に変換した Blob オブジェクトを新たに作成します。

const blob = new Blob([event.data], { type: mime_type });

8. 画面録画の動画ファイルの Blob URL を生成

URL.createObjectURL() で動画ファイルの Blob URL を生成します。

const url = URL.createObjectURL(blob);

Blob URL は以下の形式となり、アドレスバーにこれを入力して開くと画面録画の動画ファイルが表示されます。

blob:https://example.com/[ランダムな文字列]

Blob URL を作成するとタブを閉じるまでブラウザにデータが残り続けます。

不要になった場合、以下のコードでデータを削除できます。

URL.revokeObjectURL(url);

引数には削除したい Blob URL を入れる必要があります。

画面録画サンプル

上記の手順を一括にまとめたコードがこちらです。

この HTML / Javascript コードを実行すると画面共有が要求されます。

画面共有をした後、「録画開始」→「録画停止」と順にクリックします。

すると画面録画がプレビューされます。

「ダウンロード」をクリックすると録画が保存されます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <h1>画面録画サンプル</h1>
    <button id="start" style="display: none;">録画開始</button>
    <button id="stop" style="display: none;">録画停止</button>
    <div id="preview-outer" style="display: none;">
      <video id="preview" controls style="width: 600px; max-width: 100%;"></video>
      <a id="download" download style="display: block;">ダウンロード</a>
    </div>
    <script>
const start = document.getElementById('start'),
stop = document.getElementById('stop'),
preview_outer = document.getElementById('preview-outer'),
preview = document.getElementById('preview'),
download = document.getElementById('download');
const mime_type =
  ['video/mp4', 'video/webm'].find((mt) => MediaRecorder.isTypeSupported(mt));
navigator.mediaDevices.getDisplayMedia({ video: true, audio: true })
  .then((stream) => {
    const recorder = new MediaRecorder(stream, { mimeType: mime_type });
    start.style.display = '';
    start.addEventListener('click', () => {
      recorder.start();
      start.style.display = 'none';
      stop.style.display = '';
    });
    stop.addEventListener('click', () => {
      recorder.stop();
      stop.style.display = 'none';
    });
    recorder.addEventListener('dataavailable', (event) => {
      const blob = new Blob([event.data], { type: mime_type });
      const url = URL.createObjectURL(blob);
      preview.src = url;
      download.href = url;
      preview_outer.style.display = '';
    });
  });
    </script>
  </body>
</html>

当記事のカテゴリー

コメント (0件)