4
2

More than 5 years have passed since last update.

Nuxt.js + SkyWayを使ってWebRTCを実装

Posted at

WebRTCはブラウザ同士で直接動画や音声などのリアルタイムなコミュニケーションを実現するAPIの定義になります。基本的にはICEサーバーを使って自分の情報を取得し、相手のブラウザにそれを認識させる事によってブラウザ同士の通信を実現します。

WebRTCの仕組み

WebRTCではICEサーバーという特殊なサーバーを用います。ブラウザ同士の通信にはNATがあるため、ICEサーバーを使ってこの問題を解決します。ICEサーバーにはSTUN、TURNというものがあります。
Googleなども無料でSTUNを公開していますが、今回はSkyWayを使うので、そこはあまり意識しなくてもいいかもしれません。

ICEサーバーでは自分の情報を取得することができます。
そしてその取得した情報を相手に伝えないといけません。

その情報を相手に伝える為にシグナリングサーバーというサーバーを使います。
このサーバーは相手に情報を教えてあげる仲介をしてくれます。
自分はNode.js + socket.ioで実装しました。

実際にはシグナリングサーバーは必須ではありません。
例えば自分のIDを相手にメールやチャットなどで伝える事で自分のブラウザへ入力する事で通信を開始する事ができます。

実際にシグナリングさせる

実装

今回はNuxt.jsを用いて実装しました。
ソースコードは長くなってしまうので抜粋しています。
挙動としては、発信側が通信を開始し、受信側が承認することで開始するイメージです。

server


  const io = socketio.listen(server)

  io.on('connection', socket => {
    socket.on('send peer id', id => {
      io.emit('emit peer id', id)
    })

    socket.on('answer peer id', id => {
      io.emit('answer peer id', id)
    })

    socket.on('disconnect', () => {
      console.log('disconnected')
    })
  })

cliant(発信側)

  async created() {
    this.company = services.find(
      service => service.slug === this.$route.params.company
    )
    this.inquiry = this.$route.params.inquiry || 'hoge'
    const constraints = { audio: true, video: true }
    const stream = await navigator.mediaDevices.getUserMedia(constraints)
    this.user.stream = stream
  },
  mounted() {
    this.socket = io()
    this.socket.on('answer peer id', id => {
      this.peer.call(id, this.user.stream)
    })

    this.peer = new Peer({
      key: this.APIKey,
      debug: 3
    })

    this.peer.on('call', call => {
      call.answer(this.user.stream)
      call.on('stream', stream => {
        this.operatorStream = stream
        const el = document.getElementById('video1')
        el.srcObject = stream
        el.play()
      })
    })
  },
  methods: {
    call() {
      this.socket.emit('send peer id', this.peer.id)
    }
  }

cliant(受信側)


  async created() {
    const constraints = { audio: true, video: true }
    const stream = await navigator.mediaDevices.getUserMedia(constraints)
    this.localStream = stream
  },
  mounted() {
    this.socket = io()
    this.socket.on('emit peer id', id => this.user.id = id)

    this.peer = new Peer({
      key: this.APIKey,
      debug: 3
    })

    this.peer.on('call', call => {
      call.answer(this.localStream)
      call.on('stream', stream => {
        this.userStream = stream
        const el = document.getElementById('videoUser')
        el.srcObject = stream
        el.play()
      })
    })
  },
  methods: {
    answered() {
      const call = this.peer.call(this.user.id , this.localStream);
      call.on('stream', stream => {
        this.socket.emit('answer peer id', this.peer.id)
      });
    },
  },

videoタグをrefsで取得てsrcObjectに入れたかったのですが、うまく取得できなかったのでidで取得しています。その他にもtemplateで<video :srcObject='stream'>もやってみましたがダメでした。

最後に

WebRTCを取り扱うのであれば、今回のようなSkyWayやPeer.jsを使うと簡単に実現できます。
実運用を考えるとSTUNサーバーを自前で用意したり、フロントエンドの技術だけではまかないきれない部分も出て来ますが、試してみるにはよいのではと思います。(有料プランもありだと思います)

4
2
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
4
2