リモート演劇のためにWebRTCで専用アプリ作ってみた話

## 結論
リモート演劇とWebRTCは相性が良いと思うので、ぜひ皆さんチャレンジしてみてください。意外と簡単だよ！

## はじめに
[大統領師匠](https://daitouryosisyo.com/)という劇団のお手伝いをしているのですが、先日COVID-19の影響で[公演が中止になってしまいました](https://www.instagram.com/p/B_QA8s1lAQ8/)。
鬱々とした日々を送っていたところ、東京都から「[アートにエールを！プロジェクト](https://cheerforart.jp/)」という企画が発表されました。
雑に言うと、リモートでの映像作品を作れば助成金が支給される、という企画です。
このプロジェクトに応募するため、作品を作り始めました。
できた作品はこちらです。
[「刑事と刑事」大統領師匠](https://www.youtube.com/watch?v=NjDYKDglB9w)

## どう表現するか
リモートで作品を作ろうってなると、結局ZoomとかSkypeとかを使ってやるケースが多いのですが、このツール自体が表現手段の一つになっていたら良いのではないか、と考えました。
ちょうど大統領師匠の作家・中田氏からあがってきた台本がお誂え向きだったので、これやるならオリジナルでアプリ作らない？という話を持ちかけました。
たまたま、趣味でオンライン飲みのためのWebRTCブラウザアプリを作っていたので、それを活用する形で制作しました。

## 設計・構築する
大した処理は無いのですが、バックエンドはLaravelでさくっと作りました。
フロントエンドもそこまで複雑ではないのでbladeで。jQueryだけ使ってます。
WebRTCを利用するにあたっては、[Skyway](https://webrtc.ecl.ntt.com/)というNTTコミュニケーションズが提供しているサービスを利用しました。無料枠も結構あって、使い勝手の良いサービスです。わかりやすいドキュメントも充実しているので、そんなに苦労せずに使えると思います。

システムの流れは以下のように考えました。
![スライド1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106534/51c3164b-6aa6-c276-d3df-f455c1934b1f.png)

作品をご覧いただくとわかりますが、物語は上記の流れの繰り返しで進みます。
なので、
- 後輩画面には、電話をかける機能だけあれば良い
- 先輩画面には、通話を開始する機能だけあれば良い
- 別の誰かが、爆発させるキッカケを送ると通話が切れて、先輩画面だけ消える
という機能があれば良いことになります。
（実際には最初と最後に、後輩は自分の画面をオン／オフもしていますが省略。）

それぞれの画面の関係性は以下のようになりました。
![スライド2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106534/32f2c129-1091-07e8-fec8-2da9ba943026.png)

## Skywayについて
「Skyway」はWebRTCを手軽に扱えるマルチプラットフォームのSDKで、NTTコミュニケーションズのサービスです。
私は今回JavaScriptのSDKを使いましたが、[公式のドキュメント](https://webrtc.ecl.ntt.com/api-reference/javascript.html)も日本語ですし、とても扱いやすいと感じました。
EventEmitterを継承しているので、「電話をかける」「爆発する」などの信号はWebSocket感覚で簡単に送ることができました。

例えば、後輩用画面から先輩へのコール開始信号を送っていた部分のコードはこんな感じ。

```javascript:kouhai.js
    $(".call").click(function(){
      // コール音信号送信
      room.send({
        "cmd": "startCall"
      })

      // コール音開始
      callAudio.currentTime = 0
      callAudio.volume = 0.4
      callAudio.play()
    })
```

爆発音の送信も似たような感じ。

```javascript:admin.js
    $(".explode").click(function(){
      // 爆発信号送信
      room.send({
        "cmd": "explode"
      })

      // 爆発音再生
      explodeAudio.currentTime = 0
      explodeAudio.play()
    })
```

撮影用画面で、コール音を含むその他諸々の信号を受けていた部分のコードはこんな感じ。

```javascript:rec.js
    room.on('data', function (_ref) {
      var data = _ref.data

      // メッセージの内容により、ビデオ表示ON/OFF、効果音再生などの処理を行う

      // 後輩から電話かかってくる
      if(data.cmd=="startCall"){
        // コール音開始
        callAudio.currentTime = 0
        callAudio.volume = 0.4
        callAudio.play()
        $(".call").addClass("calling")
        $(".call i").removeClass("fa-phone").addClass("fa-phone-slash")
      }

      // 後輩画面オン
      if(data.cmd=="connect"){
        $(".guestVideo").eq(0).get(0).srcObject = streams[0]
        $(".kouhai").show()
      }
      // 後輩画面オフ
      if(data.cmd=="unconnect"){
        $(".guestVideo").eq(0).get(0).srcObject = null
        $(".kouhai").hide()
      }

      // 電話つながる
      if(data.cmd=="callConnected"){
        // コール音停止・先輩接続（画面表示）
        $(".guestVideo").eq(1).get(0).srcObject = streams[1]
        $(".senpai").show()
        callAudio.pause()
        callAudio.currentTime = 0
      }

      // 爆発
      if(data.cmd=="explode"){
        // 爆発音再生・先輩消滅
        explodeAudio.currentTime = 0
        explodeAudio.play()
        $(".guestVideo").eq(1).get(0).srcObject = null
        $(".senpai").hide()
        $(".call").removeClass("calling")
        $(".call i").removeClass("fa-phone-slash").addClass("fa-phone")
      }
    })
```

`data.cmd`で受け取ったコマンドによって処理を分けているだけです。
処理はかなりシンプルです。
先輩の画面を消したり出したりするところは、videoタグのsrcObjectで操作しています。
これによって役者は、実際に通話がつながったり切断したりする体験をすることになります。

## おわりに
劇場で出来ないということは、演劇関係者にとっては非常に苦しいことでした。
大学で演劇を学び、小劇場の役者として少しでも演劇に関わってきた身としては、現在携わっているソフトウェア開発の領域から違った角度でアプローチしてみたかったのです。
仕事ではUnityやopenFrameworksを使ってメディアアート作品に関わらせていただくこともしばしばあるのですが、今回のこれも一つのメディアアートと呼べるのかなぁ…？
演劇関係者の皆さん、手軽なWebRTCを活用して新しい表現を模索してみてはいかがでしょうか？