ブラウザ越しにお花見しよう!

GASHOO Inc. Advent Calendar 2017土曜日担当、9日目を飾ります、t-kusakabeです。 先日ハッカソンにて、HanamiとWebRCTを触る機会があったのでその時したことをまとめて見ようと思います。 ということでWebRTCを使ってお花見です。

Hanami

以前のAdvent Calendarでも簡単に紹介したのですが、HanamiはRubyのFWです。 GashooでHanamiを採用したのもこの時に触ったのがきっかけでした。

WebRTC

WevRTCとはブラウザ間でビデオや音声などのデータをやりとりできるようにしてくれるくんです。 「appear.in」などはWebRTCを使って事例としてよく取り上げられているような気がします。

実際に動かして見る

※本来であればFWなどを使う必要はないのですが、この時僕がただHanamiを使いたかったのとHanamiを使ってWebRTCを動作させるのに若干詰まったところがあったためあえてHanamiを使っています。 今回作るのはビデオ通話です。

hanami new

まずはスケルトンを作成します。

hanami new プロジェクト名(今回はhanami_web_rtcとしました)

この状態で

bundle exec hanami server

と、するとサーバーが起動します。 localhost:2300 にアクセスすると、Hanamiのデフォルトページが確認できると思います。

topページの用意

ひとまずtopページだけ作成しておきます。 HanamiはほとんどのコマンドがRoRと類似しているのでRoR経験者はわかりやすいかもです。

bundle exec hanami g action web tops#index

これでcontroller以下にindex.rbが生成されます。

apps/web/controllers
└── tops
    └── index.rb

Hanamiではaction毎にclassが存在するのでfat controllerになりにくい感があると思います。 これで localhost:2300/tops にアクセスすることができるようになると思います。

template

actionを作成することができたので、次はtemplateを作ります。 Hanamiはtemplate以下にerbを書いていきます。

apps/web/templates
├── application.html.erb
└── tops
    └── index.html.erb

index.html.erbにvideoタグを設置していきます。

<div class="pure-g">
  <!-- video area -->
  <div class="pure-u-2-3" id="video-container">
    <video id="their-video" autoplay></video>
    <video id="my-video" muted="true" autoplay></video>

    <video id="video" autoplay muted></video>
    <video id="others-video" autoplay></video>
  </div>

  <!-- steps -->
  <div class="pure-u-1-3">
    <h2>skyway video chat</h2>

    <p>your id: <span id="my-id">...</span></p>
    <p>share this id with others so they can call you.</p>
    <h3>make a call</h3>
    <form id="make-call" class="pure-form">
      <input type="text" placeholder="call user id..." id="callto-id">
      <button href="#" class="pure-button pure-button-success" type="submit">call</button>
    </form>
    <form id="end-call" class="pure-form">
      <p>currently in call with <span id="their-id">...</span></p>
      <button href="#" class="pure-button pure-button-success" type="submit">end call</button
    </form>
  </div>
</div>

PeerJS

今回はWebRTCを使うのにPeerJSを使用します。 普通にWebRTCを使うだけならPeerJSと他のビルドインサーバーがあれば実装できるのですが、今回はHanamiを使いますw

こちらのページ より、まずはAPIのkeyを生成します。 Sign Upして、鍵を発行してください。

PeerJSを使ってビデオ通話するためのscriptを書く。

PeerJSを使ってビデオ通話するためのscriptを書いていきます。 上記で作成したAPIkeyも用意しておいてください。

apps/web/assets/javascripts
└── script.js

上記のように新しくfileを作ります。

console.log('start webRTC!')

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

var peer = new Peer({key: 'PeerJSのAPIkey'});
 
peer.on('open', function(){
    console.log('connect')
    $('#my-id').text(peer.id);
});


var myStream;
$(function(){
  navigator.getUserMedia({audio: true, video: true}, function(stream){
    myStream = stream;
    $('#video').prop('src', URL.createObjectURL(stream));
  }, function(){});
});

function callTo(peerId){
  var call = peer.call(peerId, myStream)

  call.on('stream', function(othersStream){
    $('#others-video').prop('src', URL.createObjectURL(othersStream))
  })
}

peer.on('call', function(call){
  call.answer(myStream);
  call.on('stream', function(othersStream){
    $('#others-video').prop('src', URL.createObjectURL(othersStream));
  });
});

APIkeyを適切に設定してください。

HanamiにPeerJSを読み込ませる

まずは上記で作成したscript.jsを読み込ませます。

apps/web/templates
├── application.html.erb
└── tops
    └── index.html.erb

template以下のapplication.html.erbにscriptを追加します。

<!DOCTYPE html>
<html>
  <head>
    <title>Web</title>
    <%= favicon %>
  </head>
  <body>
    <%= yield %>
    <%= javascript src="script.js" %>
  </body>
</html>

script.jsではPeerJSを使用しているためPeerJSを読み込ませます。 今回はCDNですることにします。 が、ここに一番手間取りました。。。

<html>
  <head>
    <title>Web</title>
    <%= favicon %>
  </head>
  <body>
    <%= yield %>
    <%= javascript src="https://code.jquery.com/jquery-3.2.1.min.js" %>
    <%= javascript src="https://cdn.webrtc.ecl.ntt.com/skyway-latest.js" %>
    <%= javascript src="http://cdn.peerjs.com/0.3/peer.min.js" %>
    <%= javascript src="script.js" %>
  </body>
</html>

と、すれば動作すると思ったのですが、なぜかCDNが読み込まれませんでした。。。 どうやらセキュリティ的にCDNを使うには一手間いるようです。 今回は以下の方法をとりました。(他に適切な方法があればご教授ください。。。)

apps/web/application.rbに以下を追記します。

security.content_security_policy "https://skyway.io/dist/0.3/peer.js;"
security.content_security_policy "https://skyway.io/dist/multiparty.min.js;"
security.content_security_policy "https://cdn.peerjs.com/0.3/peer.min.js;"

どうやら使用するものをあらかじめ明示しておく必要があるみたいです。 ひとまずこの方法で動作することが確認できました。

これで localhost:2300/tops にアクセスします。

完成!

どうでしょうか? ひとまずこれでビデオ機能が実装できました! IDで繋げることもできるのでいろいろ試してみてください。

まとめ

今回はビデオ機能だけでしたがチャット等も実装することができるので是非是非試してみてください!

今回作ったもの