Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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サーバーを自前で用意したり、フロントエンドの技術だけではまかないきれない部分も出て来ますが、試してみるにはよいのではと思います。(有料プランもありだと思います)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした