29
22

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 3 years have passed since last update.

Vue.jsでWebRTCによるビデオ通話機能を作ってみた

Last updated at Posted at 2019-12-05

グレンジ Advent Calendar 2019 6日目担当の raitome です。
グレンジでクライアントエンジニアをやっています。
最近はちょっと違う技術を触ってみたくて、Vue.jsを使って、ビデオ通話機能を作ってみました。
ネットの資料が多いですが、古いものも多くて、すぐ使えるコードが少ないので、
メモのためでもあり、必要なものを簡単にまとめました。

##WebRTCについて
詳細は下記でご覧いただけます。
https://ja.wikipedia.org/wiki/WebRTC
https://qiita.com/yusuke84/items/286f569d110daede721e

##使ったライブラリ
とりあえず手軽にビデオ通話機能を作りたくて、下記のライブラリを使いました。
・simple-peer: https://github.com/feross/simple-peer
  WebRTCベースで、p2pのビデオ通話を簡単に実装できるライブラリ。ファイルの転送などもできるらしい

・ simple-signal-clientとsimple-signal-server: https://github.com/t-mullen/simple-signal
  WebRTCでPeer to Peer通信を行う場合、シグナリングサーバと呼ばれる仲介サーバを用意する必要がありますので、simple-peerのためのシグナルサーバー用ライブラリsimple-signalを使いました。simple-signal-clientはクライアント側で、simple-signal-serverはサーバー側で使います。

他に、シグナルサーバーはSocket通信を使うため、socket.ioとクライアントとサーバー側のライブラリも使います。

(Skyway: https://webrtc.ecl.ntt.com/ というサードパーティのものを使えばもっと早く構築できるらしいが、有料らしいので、今回は自前で色々作ってみました)

##クライアント側の準備
今回は必要な処理だけ紹介します。完成版のコードを割愛します。

###1.必要なもののimport

sample_client.js
    import SimplePeer from 'simple-peer'
    import SimpleSignalClient from 'simple-signal-client'
    import io from 'socket.io-client'

###2.Peerの作成

sample_client.js
    const socket = io("シグナルサーバーのurl" , {secure: true})
    let signalClient = new SimpleSignalClient(socket)

    // 下記の方法でチャットルームの感じで作れる
    signalClient.discover("チャットルームID的な何か") // これを使ってユーザーリストとかを取得できる
    signalClient.on('discover', receiveUserList) // ユーザーリスト処理のfunctionをここに入れる

###2.Peerへの接続リクエスト処理
ビデオ通話したい相手のソケットIDが分かれば、下記のfunctionを使えばシグナルサーバーを経由して接続できます。

sample_client.js
    const { peer } = await signalClient.connect("自分のソケットID",  "チャットルームID的な何か"})

###3.Peerの受信処理

sample_client.js
    signalClient.on('request', async (request) => {
        const { peer } = await request.accept()  // 接続リクエストを承認

        peer.on('connect', () => {
            peer.send("connected")
        })
        peer.on('stream', (remoteStream) => {
              // 向こうから受け取ったPeerのストリームを画面に表示させる
            const videoElement = document.createElement('video')
            videoElement.autoplay = true
            videoElement.srcObject = remoteStream
            container.appendChild(videoElement) // 事前に用意したコンテナに新しく作ったElementを追加する
        })
        peer.on('close', () => {
             // 停止時の必要処理
        })
        // 自分のカメラの映像も向こうに送信するので、ストリームを取得して画面に追加する。下記の関数はあとで説明します
        addLocalCameraStream()
    })

###4. カメラの扱い
下記の処理で、ブラウザがカメラの使用権限を取得して、カメラのストームを扱います。
ブラウザによって挙動が少し違うので、最新版のChromeかFireFoxを使うことをオススメします。
一つ注意点としては、Chromeの場合は、セキュリティの関係で、サーバー側はSSL対応をしないと、下記のメソッドはうまく動きません。

sample_client.js
    addLocalCameraStream() {
        var mediaDevices = navigator.mediaDevices || ((navigator.mozGetUserMedia || navigator.webkitGetUserMedia || navigator.msGetUserMedia) ? {
            getUserMedia(c) {
                return new Promise(((y, n) => {
                    (navigator.mozGetUserMedia || navigator.webkitGetUserMedia).call(navigator, c, y, n);
                }));
            }
        } : null)

        mediaDevices.getUserMedia({ audio: true, video: true }).then((localStream) => {
            peer.currentPeer.addStream(localStream) // これで接続した相手にストリームを送る
            // ここでストリームを画面に表示させる処理を追加してもいい
            }).catch(err => {
        });
    }

ちなみに、mediaDevices.getDisplayMediaを使えば、画面共有機能も作れます。

上記のコードを使えば、クライアント側の最低限の機能が作れます。

##シグナルサーバーの準備
シグナルサーバーのコードは割とシンプルになります。
主に必要に応じてユーザーの管理処理をカスタマイズします。

index.js
    const io = require('socket.io')(server)
    var SimpleSignalServer = require('simple-signal-server')
    var signal = new SimpleSignalServer(io)

    signal.on('request', (request) => {
        request.forward() // リクエストをそのまま進ませる
    })

    signal.on('discover', (request) => {
        // ここでユーザーのソケットIDやルームIDを管理して、request.discoverを使って、全てのpeerの必要な情報を送る
    })

    signal.on('disconnect', (socket) => {
        // 接続切れる時の処理
    })

##最後に
以上でコードを使えば、必要最低限のビデオ通話機能が作れます。少し調整すれば、画面共有機能も作れます。実際にテストしてみたところ、P2Pの関係でもありますが、割とスムーズなビデオ通話ができました。

また、何か不明なところがありましたら、simple-signalのサンプルコードも一緒にご覧いただければ。

29
22
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
29
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?