ある中卒がWeb系エンジニアになるまでと、それからのこと

うつ病で高校を中退したり、たこ焼き屋のオヤジにホームページとたこ焼きを作らされたり、そのホームページが訴えられそうになったり、弁護士を目指したりした後にエンジニアになった人が書くブログ

vueプロジェクトにskywayを導入してビデオ通話する

2020/06/30の日報

Hanasot開発の日報、第4日目です。
今日は

  • vueプロジェクト内に新規ページを追加して、リンクを貼る
  • skywayをvueプロジェクトに導入する

を行いました。
時間としては、

  • Hanasot開発 3h30min
  • 日報ブログ 70min

です。
運動は

  • アンイーブン・スクワット 16reps * 2(軽く吐き気がします...)

です。

vueプロジェクト内に新規ページを追加して、リンクを貼る

今回は対話ページとして、Home.vueやAbout.vueが入っているディレクトリに Dialog.vue を用意しました。
中身は About.vue のコピーです。

vue-routerにパスを追加

まずはvue-routerを編集してパスを追加していきます。実際に触るのは src/router/index.jsです。

f:id:chusotsuengineer:20200630214051p:plain
このファイルを編集します
添付画像のように

import hogehoge from ../views/Hogehoge.vue

と記述してvueファイルを読み込んだ後、

{
  path: '/hogehoge',
  name: 'hogehoge',
  component: Hogehoge,
},

と書いてパスを追加します。
これは anatano-domain/hogehoge というパスにアクセスしたとき、Hogehoge.vue を表示します。このページの名前はhogehogeとします。
という意味ですね。

トップページから対話ページへのリンクを貼る

それができたら添付画像のようにトップページにリンクを追加します。

f:id:chusotsuengineer:20200630214939p:plain
router-linkはaタグに変換されます

<router-link to="/dialogue" class="btn btn-corp btn-l">
  無料で参加する
</router-link>

と記述することで、dialogueページに遷移するaタグが出力されます。
リンクは何通りか方法がありますが、今回はシンプルにしておきます。

skywayをvueプロジェクトに導入する

ここまでで準備はできたので、本題のskyway導入です。 会員登録ページにアクセスして登録を済ませておきます。公式ドキュメントが非常に詳しく作成してあるのでとても導入しやすいです。

skywayの管理画面からアプリを登録する

ここはドキュメント通りに進めていくだけなので割愛します。ibmやらの管理画面と違ってわかりやすいので特に迷うことはありませんでした。利用可能ドメインには「localhost」と「firebaseでホスティングしているドメイン」を登録して、api鍵を保存したらOKです。

skywayのapiを使ってビデオ通話してみる

ここが今日1番時間のかかった部分です。ドキュメントでは1対1の通話を想定して解説してあるので、skyway-multipartyをインストールしてみたり、こちらの記事を再現したりしたのですが、最終的にはドキュメントのコードをvueファイルに落とし込んで実装しました。
ソースコードは下記です。

<template>
  <div>
    <video id="my-video" width="400px" autoplay muted playsinline></video>
    <p id="my-id"></p>
    <textarea id="their-id" v-model="theirID"></textarea>
    <button id="make-call" @click="makeCall">発信</button>
    <video id="their-video" width="400px" autoplay muted playsinline></video>
  </div>
</template>
<script>
  import Peer from 'skyway-js';
  export default {
    name: 'Dialogue',
    data() {
      return {
        localStream: null,
        theirID: '',
        peer: {},
      }
    },
    created() {
      // カメラ映像取得
      navigator.mediaDevices.getUserMedia({video: true, audio: true})
        .then( stream => {
        // 成功時にvideo要素にカメラ映像をセットし、再生
        const videoElm = document.getElementById('my-video')
        videoElm.srcObject = stream;
        videoElm.play();
        // 着信時に相手にカメラ映像を返せるように、グローバル変数に保存しておく
        this.localStream = stream;
      }).catch( error => {
        // 失敗時にはエラーログを出力
        console.error('mediaDevice.getUserMedia() error:', error);
        return;
      });

      // skyway接続
      this.peer = new Peer({
        key: ご自身のapiキーを入れてください',
        debug: 3,
      });
      this.peer.on('open', () => {
        document.getElementById('my-id').textContent = this.peer.id;
      });

      //着信処理
      this.peer.on('call', mediaConnection => {
        mediaConnection.answer(this.localStream);
        this.setEventListener(mediaConnection);
      });
    },
    methods: {
      makeCall() {
        const mediaConnection = this.peer.joinRoom(this.theirID, {
          mode: 'sfu',
          stream: this.localStream,
        });
        this.setEventListener(mediaConnection);
      },
      setEventListener: (mediaConnection) => {
        mediaConnection.on('stream', stream => {
          // video要素にカメラ映像をセットして再生
          const videoElm = document.getElementById('their-video')
          videoElm.srcObject = stream;
          videoElm.play();
        });
      }
    },
  }
</script>
<style scoped>
</style>

基本的にはcreatedフックとdataプロパティとmethodsに振り分けただけです。
ドキュメントと違う部分は下記ですね。

const mediaConnection = this.peer.joinRoom(this.theirID, {
  mode: 'sfu',
  stream: this.localStream,
});

callメソッドをjoinRoomに変えて、modeを選択することでグループ通話になります。現段階では2人分しか表示できないので実質2人通話ですが。
最初は昨日と同じようにcreatedフックなどは無しで、scriptタグ内に処理を書いていたのですがDOM周りのエラーが起きまして。やっぱりvueファイルなのでちゃんとcreatedフックに書かないとだめですね。
もうちょっとリファクタリングできると思うのですが、ちゃんとグループ通話を実装してUIを整えてからリファクタします。
ここまで出来たらこんな感じになるはずです。

f:id:chusotsuengineer:20200630221933p:plain
以前クレーンゲームで取った猫

npm run build と firebase deploy をして公開できたら一旦終わりです。
明日はグループ通話できるようにしていきます。

所感

skyway-multipartyについて

これ2017年で開発が止まっちゃってるのが惜しいですね。wherebyも認知されてるしライブラリがちゃんと使えるようになればもっと広まりそうな気がするんですが。まあskywayの通常のapiを使って結構かんたんにグループ通話までできそうだからいいかな。
他にもビデオ通話のapiで良さげなのがあったら知りたいです。もしご存じの方がいらっしゃったらtwitterかなにかで教えて下さい〜

明日は参加人数に合わせてvideoタグを増やしたり消したりといった、ザ・vueみたいなことをしていく予定です。がんばります。