Vue.js v3とWebRTCでWebカメラを利用するコピペで使えるサンプル


過去にWebRTCの利用をするべく、カメラを使ったサンプルをチュートリアル的に記事にしました。

> 参考: [SkyWayのサンプルをVue.jsで書いていくチュートリアル vol1](https://qiita.com/n0bisuke/items/6e1f56678b2eb6318594)

この時はVue.js v2だったのですが、久々に見たらv3がリリースされてたのでアップデートしてみました。サッと調べて書いたくらいなので間違い等あれば指摘頂けると嬉しいです。
WebRTCといいつつ通信手前までなので悪しからず

何かと利用するかもしれないので残しておきます。

## 最終イメージ

こんな感じでセレクトボックスでカメラを選択するとカメラ映像がWebサイト上に描画されます。

> ![](https://i.gyazo.com/5a3d0821b198c8f291fdd19320b62fd8.gif)


## コード全文

今回はカメラだけに集中して見たので、過去記事でやっていたマイクの記述をまるっと削除しています。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Camera Test</title>
  </head>

  <body>
    <h1>WebカメラVue v3テスト</h1>

    <div id="app">
        <p>
            カメラ: 
            <select v-model="selectedVideo" @change="onChange">
            <option disabled value="">Please select one</option>
            <option v-for="(video, key, index) in videos" v-bind:key="index" :value="video.value">
                {{ video.text }}
            </option>
            </select>
        </p>
        <video id="my-video" muted="true" width="500" autoplay playsinline></video>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //Vue v3
        const app = Vue.createApp({
            data: () => ({
                videos: [],
                selectedVideo: '', //追記
            }),

            mounted: async function() {
                //デバイスへのアクセス
                const deviceInfos = await navigator.mediaDevices.enumerateDevices();

                //カメラの情報を取得
                deviceInfos
                    .filter(deviceInfo => deviceInfo.kind === 'videoinput')
                    .map(video => this.videos.push({text: video.label || `Camera  ${this.videos.length - 1}`, value: video.deviceId}));
            },

            methods: {
                onChange: function (){
                    if(this.selectedVideo != '') this.connectLocalCamera();
                },

                connectLocalCamera: async function (){
                    const constraints = {
                        video: this.selectedVideo ? { deviceId: { exact: this.selectedVideo } } : false
                    }

                    const stream = await navigator.mediaDevices.getUserMedia(constraints);
                    document.getElementById('my-video').srcObject = stream;
                }
            },

        });
        app.mount('#app');
 
      </script>
  </body>
</html>
```

## Vue.js 2系から3系での書き方変更

### 2系の書き方

```js
const app = new Vue({
    el: '#app',
    data: {

    },
    methods: {

    },
    mounted: async function () {

    }
});
```

### 3系で変えたところ

* `new Vue` => `Vue.createApp`
* `el: '#app'` => `app.mount('#app');`
* CDNの読み込み `<script src="https://unpkg.com/vue@next"></script>`

といったところを変更したらうまく動作しました。

```js
const app = Vue.createApp({
    data: {
    },
    methods: {
    },
    mounted: async function () {
    }
});
app.mount('#app');
```

> 参考: [Vue.js 3.0(beta 20) helloworld](https://qiita.com/ha6_6ru/items/f346c8b09eda2221a2f8)

## 所感など

思ったより変更箇所がなくてよかった。
（Vue.js v3の利点などは全然キャッチアップできてない）

今回の話題とは別問題な気がしますが、キャプチャーボード経由でMacの画面を出すことも出来たけど解像度が低い問題を解決できないか探りたいです。

> ![](https://i.gyazo.com/76c1d97343ec4ddcc4777e057174d5f3.png)