【JS】getDisplayMediaを使って画面キャプチャ【サンプルはVue3】

皆さん、こんにちは。どんぶラッコです。

今日は、getDisplayMedia を活用して画面画面共有の機能をWebで実装する方法についてまとめていきます。

Google Meet や Zoom で実装されていますよね。

実はあの機能、JavaScriptの標準WebAPIを使って実装することができてしまうんです。

イメージはこんな感じ↓↓

今回は Vue3 で実装したので、コンポーネントの情報を乗っけておきたいと思います。

コンポーネント実装例

App.vue
<script setup type="typescript">
import ScreenCapture from './components/ScreenCapture.vue';
</script>

<template>
  <v-app>
    <v-main>
      <v-container>
        <ScreenCapture />
      </v-container>
    </v-main>
  </v-app>
</template>

App.vueでやっていることは単純です。 ScreenCapture コンポーネントを表示させているだけ

では、ScreenCapture.vue で何をしているかというと、こんな感じ。

ScreenCapture.vue
<template>
  <v-btn
    color="primary"
    class="font-weight-bold"
    elevation="0"
    @click="onClickSelectButton"
  >
    画面1
  </v-btn>
  <video
    :srcObject.prop="videoSrc"
    autoplay
    width="400"
  />
</template>

<script lang="ts">
import {
  ref,
  reactive,
  defineComponent,
} from 'vue';
import useMediaDevice from '../composables/useMediaDevice';

export default defineComponent({
  setup() {
    const videoSrc = ref<MediaStream>(new MediaStream());

    const {getDisplayMedia} = useMediaDevice();

    const onClickSelectButton = async () => {
      const mediaStream = await getDisplayMedia();
      if (!mediaStream.active) {
        return false;
      }
      console.log('mode');
      videoSrc.value = mediaStream;
    };

    return {
      videoSrc,
      onClickSelectButton,
    };
  },
});
</script>

<style lang="scss">

</style>

getDisplayMedia() メソッドを composables ディレクトリに定義して、それを引っ張ってきています。

const {getDisplayMedia} = useMediaDevice();

getDisplayMediaではキャプチャする画面を選択すると MediaStream オブジェクトを返します。

const mediaStream = await getDisplayMedia();

MediaStreamオブジェクトはビデオなどのソース情報をストリーミング形式で流してくれる役割を果たすオブジェクトです。

なので、操作している画面がリアルタイムで共有されるわけですね。

あとはこのMediaStreamオブジェクトを <video> タグの中に流し込んであげればストリーミングされている画面情報がビデオとして画面上で再生される…というわけです。

ちなみに、<video> タグをVueで扱うには2点注意事項があります。

  <video
    :srcObject.prop="videoSrc"
    autoplay
    width="400"
  />

  1. MediaStreamオブジェクトは srcObject.prop に渡すこと
  2. autoplay 属性を付与しておくこと

srcObject.prop と似た挙動を Vanilla JS で記述するとこうなります。

document.querySelector('CSS_SELECTOR').srcObject = MEDIA_STREAM_INSTANCE;

また、 autoplay を付与しておかないと勝手にビデオが再生されません。

さて、あとは 読み込んでいる getDisplayMedia() を確認してみましょう。

useMediaDevice.ts という形で機能をファイルとして切り出しています。

useMediaDevice.ts
const useMediaDevice = () => {
  const cn = {video: true}; // 設定(constraints)

  const getDisplayMedia = async (): Promise<MediaStream> => {
    try {
      const {mediaDevices} = navigator;
      const stream:MediaStream = await mediaDevices.getDisplayMedia(cn); // navigator オブジェクトから取得
      console.log(stream);
      return stream;
    } catch (e) {
      console.error('Error: ' + e);
      return new MediaStream();
    }
  };

  return {
    getDisplayMedia,
  };
};

export default useMediaDevice;

こちらもわかりやすいですね。一番重要なのは下記の部分です。

const stream:MediaStream = await mediaDevices.getDisplayMedia(cn); // navigator オブジェクトから取得

getDisplayMediaを発火すると共有画面の選択画面がユーザに表示されます。ユーザが結果をクリックすると、Promiseの結果として MediaStream インストンスが発動します。

もしユーザが共有をしない(キャンセルボタンを押下)すると、例外処理のフローに遷移します。


ということで画面キャプチャの方法でした!ここからcanvas要素と組み合わせると色々面白いことができる…のですが、今回はここまで!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA