WebRTC Update 2016 Summer

# はじめに

この資料は [HTML5 Confrence 2016 の講演資料](http://events.html5j.org/conference/2016/9/session/#session_id_b5)です。

---

# 自己紹介

- 名前: なかゆうすけ（[@Tukimikage](https://twitter.com/Tukimikage)）
- 仕事:
  - [SkyWay](https://skyway.io)のDevrel
  - [HTML5 Experts.jp](https://html5experts.jp)の運営
- コミュニティ：
  - [WebRTC Meetup Tokyo](https://atnd.org/groups/webrtc)主催

---

# スペシャルサンクス

- この資料を作るにあたりサポートしてくれた、同僚の@iwashi86氏に感謝

---

# 講演のターゲット

---

# ターゲット

- WebRTCを使ってみたいと考えているWebエンジニアの方
- WebRTCを実際に使っているWebエンジニアの方

---

# では、始めます

---

# HAPPY BIRTHDAY

---

# HAPPY BIRTHDAY

- WebRTCは今年で誕生５周年

---

![webrtcorg.png](https://qiita-image-store.s3.amazonaws.com/0/6651/d36b2dde-abff-4f2b-daa6-1051f028c2dd.png)

---

# WebRTCの登場

- 2011.6.1 Google release of WebRTC source code
  - https://lists.w3.org/Archives/Public/public-webrtc/2011May/0022.html
      - Harald Alvestrand@Google 氏のメール
  - GoogleがWebRTCのソースコードを公開した

- 5周年を記念して同氏よりメッセージがMLに流れていたので抜粋してみる

---

# ５年間でWebRTCはどれだけ成長したのか？

- 全世界でWebRTC対応ブラウザは約２億台以上稼働
- Chromeでは１週間に
  - 10億分のビデオストリームがやり取りされている
  - 500TB以上のデータがDataChannelでやり取りされている
  - （感想：Chromeって利用状況かなり細かく計測してるんですね）
- 2016/6/9時点で951のWebRTCに関するプロダクトやベンダーが活動
- Facebbokメッセンジャーやハングアウト等、Android/iOSでWebRTC機能が実装されたアプリのダウンローヅ数は数十億規模

---

# WebRTCを取り巻く環境の変化

- TwillioやToxbox、AT&T、シスコなどが開発者のためのプラットフォームサービスを提供
- GoogleはWebRTCにロイヤリティフリーのコーデック（OpusやVP8）を提供
  - 音声通信の約80%はOpus
  - VP9が最近登場しVP8よりも通信料を約30%削減可能（代わりにCPU使用率は上がる）
- [Alliance for Open Media](http://aomedia.org/)は業界横断的にロイヤリティフリーのコーデックの品質改善のために活動している

---

# これから成し遂げたいこと

- オーディオとビデオの品質改善、相互運用性向上
  - （感想：H.264の相互接続等課題多い印象）
- ネットワーク要件（LTE普及によるモバイル環境での利用シーン増加等）の変化への追従
- Web以外への適用領域への展開（例えばVRと組み合わせとか）
   
---

# WebRTC☓コミュニティ

- WebRTCの開発にコミュニティは必要不可欠な存在になっている。
- オープンな場で開発を行うことの価値を証明した。
- 今後もWebRTCが利用できることの価値は時間とともに成長していく。
- これは始まりにすぎない。

---

# あれ、ちょっと待てよ…

---

# 「これは始まりにすぎない」

---

# WebRTC辛い…＿|￣|○

- 去年話題になったフレーズ
- なぜ辛いのか？
  - ブラウザの実装やOSSのWebRTCスタックに対しては日々変更が入る
  - 破壊的な変更もあったりして、サービス運営側は大変　等等

---

- 社内の一例（libwebrtcのコミットログウォッチとか・・・）

<img width="835" alt="libwebrtc.png" src="https://qiita-image-store.s3.amazonaws.com/0/6651/dde66f43-2441-b9ab-5fa6-b1fc99b6355e.png">

---

# しかし、WebRTCは進化する

いずれは、WebRTCはリアルタイムコミュニケーションのスタンダードになるだろう

---

![民主化1.png](https://qiita-image-store.s3.amazonaws.com/0/6651/d5a43c7a-c3f0-6b2c-43d7-698b01ad976c.png)

---

# リアルタイムコミュニケーションの歴史

- 最初のリアルタイムコミュニケーションは電話
- 1876年以来、電話会社が独占

---

![民主化2.png](https://qiita-image-store.s3.amazonaws.com/0/6651/ff4ace4b-00a1-f96b-e7d3-3d07f44988a8.png)

---

# リアルタイムコミュニケーションの歴史

- 2000年前後に、NapsterやSkypeがインターネット上でリアルタイム・コミュニケーションを実現

---

![民主化3.png](https://qiita-image-store.s3.amazonaws.com/0/6651/20b68572-682c-8d40-e5b6-2e69bb454ec2.png)

---

# リアルタイムコミュニケーションの歴史

- 2011年にWebRTCの最初の草案が発表
- 全てのソフトウェアエンジニアがリアルタイムコミュニケーションを扱える時代が到来
- リアルタイムコミュニケーションの民主化が始まった

---

# リアルタイムコミュニケーションの民主化

- 市場のニーズは確実にある
- サービスを開発するものとしては避けては通れない

---

# 開発者はどうするべきか？

- 技術の進歩をウォッチ
- 適宜開発に取り入れる
    - 今の段階で、一度決めたら仕様変更NGな案件には使いにくいかも
- 辛いので開発者支援サービスは積極的に使いましょう
    - 辛さはみんなで分かち合えば乗り越えられる

---

# 今日みなさんにお伝えすること

- WebRTCの最新動向（いろいろな切り口から）
- WebRTCを利用する上で知っておいて欲しい技術的なトピックス

---

# ゴール（皆さんに達成してもらいたいこと）

- WebRTC界隈のトレンドをざっくり把握した気になる
- WebRTCを利用したくなる
- WebRTCに関する様々な情報の調べ方が身につく

---

# WebRTC概要

---

# WebRTC概要

- 知識レベルを合わせるために概要を少し紹介

---

# WebRTC概要

### WebRTCでできるようになる事

1. ブラウザ間で直接通信ができる
2. ストリーミングデータを扱える
3. カメラとマイクが使える

![image](https://qiita-image-store.s3.amazonaws.com/0/6651/6b297c0c-e622-afc4-5213-75b2a3c4b9f3.png) 

---

# WebRTC概要（基礎編）

### WebRTCはリアルタイムコミュニケーションのオープン標準技術

1. ライセンス料やパテント料が不要
2. 技術の中身は４つ（ざっくり）
    1. 暗号化、到達・順序保証、流量・輻輳制御を実現
    2. NATを超えてP2P通信をする手順を確立
    3. オーディオとビデオのコーデックを規定
    4. JavaScriptから利用できるブラウザAPIを提供
3. ブラウザとネイティブアプリの両方で利用可能
    - Googleが中心となって公開するOSSのスタック（C++製を利用し、コンパイルすれば、ネイティブアプリを始め様々な環境にWebRTC機能をインストール可能
        - Chromeの実装もこれがベースになっている
        - 既存の電話のようなレガシー技術から今話題のIoT等、新旧問わず相性が良い

---

# WebRTC概要（基礎編）

### WebRTCの対応状況

||Windows|Mac|Android|iOS|
|:-----------------|:--:|:--:|:--:|:--:|
|Chrome|:o:|:o:|:o:|:x:|
|Firefox|:o:|:o:|:o:|:x:|
|IE|:x:|-|-|-|
|Edge|:o:|-|-|-|
|Safari|-|:x:|-|:x:|
|NativeApp|:o:|:o:|:o:|:x:|

- IE: プラグイン利用が必須
- Edge: 現在対応中（詳しくは後述）
- Safari: Ericssonが `WebRTC in WebKit`プロジェクトを立ち上げ、開発を支援。WebKitへの実装が進められている

---

# WebRTC概要（詳細編）

- WebRTCが繋がる仕組み、要素技術の解説は今回の発表では行いません
- ご興味がある方は次の資料をお読みください
    - [注目の最新技術「WebRTC」とは？ -技術概要と事例紹介-](http://www.slideshare.net/yusukenaka52/webrtc-55072423)

---

# WebRTCの技術的習熟度

---

# WebRTCの技術的習熟度

- 有名なガートナーレポートによれば
  - 2016年版では**流行期（Peak of Inflated Expectations）**の終盤
  - 流行期とは？
        - 世間の注目が大きくなり、過度の興奮と非現実的な期待が生じることが多い。成功事例が出ることも多いが、多くは失敗に終わる。 wikipediaより

---

# WebRTCの技術的習熟度

- 安定期までは2年〜5年
  - 2015年から同じステータスなのであと１〜４年位かな？

---

# WebRTCの標準化の仕組み

---

# 標準化の役割

- WebRTCの全体アーキテクチャや各種プロトコルはIETFで標準化
- Webブラウザに搭載されるAPIはW3Cで標準化

---

# IETFでの標準化

- WebRTCの全体アーキテクチャや各種プロトコルはIETFで標準化
![image](https://qiita-image-store.s3.amazonaws.com/0/6651/e2e82faf-6264-3fe1-b7ef-c986bc6c9299.png)

---

# IETFでの標準化

- 細かい話が多く且つ、今日ご参加の皆さんには正直あまり関係のない話なので、同僚の@iwashi86氏の「[勉強会資料 - 2016/8月時点 WebRTCの標準化動向からいくつか](http://www.slideshare.net/iwashi86/20168webrtc)」から例を一つご紹介 
    - **ICE Network Cost(draft-thatcher-ice-network-cost-00)**
        - ICEで収集した通信経路情報にネットワークコスト情報（算出方法は実装依存）を付加し、このコストを加味して通信経路を選定できるようにする

- WebRTCの技術要素の殆どがIETFで議論されているので興味がある方はウォッチしてみるとよいのでは


---

# W3Cでの標準化

- Webブラウザに搭載されるAPIはW3Cで標準化
![image](https://qiita-image-store.s3.amazonaws.com/0/6651/c9db8239-efc9-1d77-26c1-a5fa346e2e88.png)

---

# W3Cでの標準化

- ORTCという兄弟仕様もあり
![image](https://qiita-image-store.s3.amazonaws.com/0/6651/731e6c15-df63-847a-92e9-4e85e754353b.png)

---

# W3Cでの標準化

WebRTCとORTCという２つの仕様についての今後の展望（個人の所感ですが）

---

# W3Cでの標準化

- WebRTC Working Groups
    - 現在のWebRTC1.0の仕様をFIXするために粛々と作業している
    - 実際問題遅れまくりだけど・・・

---

# W3Cでの標準化

- ORTC Community Groups
    - こちらは次世代のRTC APIを作るために議論を行っている
    - Community Groupsは公式な仕様書を作ることができないので、議論した成果はWebRTC WGの方にインプットされていくはずである
    - 実際にWebRTC WGはORTC CGでの検討結果を適宜取り入れている
        - `RTCRtpSender` / `RTCRtpRecevicer` 等
    - WebRTC開発者としては、WebRTCの仕様をウォッチしておけば事足りる
        - 厳密にはWebRTC WGの仕様とブラウザの実装をウォッチする必要があるけど・・
    - MS EdgeがWebRTC1.0対応を表明しているため、今後現実世界でORTCを利用するシーンは無い(はず)
      - 参考：[Roadmap update for Real Time Communications in Microsoft Edge](https://blogs.windows.com/msedgedev/2016/04/13/roadmap-update-for-real-time-communications-in-microsoft-edge/)

---

# API仕様でチェックしておくポイント

---

# 注意

- ブラウザに実装されていないAPI、ブラウザの実装が先行しているため独自実装なAPIが多々あるので、注意
- 新しい情報と従来からの情報が混じってますが、特に区別する必要性がないため注釈等はなし

---

# W3CのExamplesを例にご紹介

- [WebRTC 1.0: Real-time Communication Between Browsers - W3C Working Draft 03 August 2016](https://www.w3.org/TR/webrtc/) より

```js
var signalingChannel = new SignalingChannel();
var configuration = { "iceServers": [{ "urls": "stuns:stun.example.org" }] };
var pc;

// call start() to initiate
function start() {
    pc = new RTCPeerConnection(configuration);

    // send any ice candidates to the other peer
    pc.onicecandidate = function (evt) {
        signalingChannel.send(JSON.stringify({ "candidate": evt.candidate }));
    };

    // let the "negotiationneeded" event trigger offer generation
    pc.onnegotiationneeded = function () {
        pc.createOffer().then(function (offer) {
            return pc.setLocalDescription(offer);
        })
        .then(function () {
            // send the offer to the other peer
            signalingChannel.send(JSON.stringify({ "desc": pc.localDescription }));
        })
        .catch(logError);
    };

    // once remote video track arrives, show it in the remote video element
    pc.ontrack = function (evt) {
        if (evt.track.kind === "video")
          remoteView.srcObject = evt.streams[0];
    };

    // get a local stream, show it in a self-view and add it to be sent
    navigator.mediaDevices.getUserMedia({ "audio": true, "video": true }, function (stream) {
        selfView.srcObject = stream;
        if (stream.getAudioTracks().length > 0)
            pc.addTrack(stream.getAudioTracks()[0], stream);
        if (stream.getVideoTracks().length > 0)
            pc.addTrack(stream.getVideoTracks()[0], stream);
    }, logError);
}

signalingChannel.onmessage = function (evt) {
    if (!pc)
        start();

    var message = JSON.parse(evt.data);
    if (message.desc) {
        var desc = message.desc;

        // if we get an offer, we need to reply with an answer
        if (desc.type == "offer") {
            pc.setRemoteDescription(desc).then(function () {
                return pc.createAnswer();
            })
            .then(function (answer) {
                return pc.setLocalDescription(answer);
            })
            .then(function () {
                signalingChannel.send(JSON.stringify({ "desc": pc.localDescription }));
            })
            .catch(logError);
        } else if (desc.type == "answer") {
            pc.setRemoteDescription(desc).catch(logError);
        } else {
            log("Unsupported SDP type. Your code may differ here.");
        }
    } else
        pc.addIceCandidate(message.candidate).catch(logError);
};

function logError(error) {
    log(error.name + ": " + error.message);
}
```

---

# RTCPeerConnectionのConfuguration

```js
var configuration = { "iceServers": [{ "urls": "stuns:stun.example.org" }] };
var pc;

// call start() to initiate
function start() {
    pc = new RTCPeerConnection(configuration);
```

- 設定可能な項目

|項目|意味|
|:--|:--|
|iceServers|STUN/TURNサーバのURLを指定|
|iceTransportPolicy |**relay:** P2PによるIPアドレスの漏洩等を防ぐ場合にTURNサーバ利用を強制する<BR>**all:** 全ての通信経路候補から選択する|
|bundlePolicy|audio,video,dataを一つの通信経路上（＝特定のIP/Port-IP/Port）で送信する仕組み（bundle）のポリシーを決める。bundleに対応していないクライアントが来た場合にどうするかを決める|
|rtcpMuxPolicy|RTPとRTCPを同一通信経路でやり取りする仕組みのポリシーを決める。rtcpMuxに対応していないクライアントの場合にどうするかを決める<BR>**require**（rtcpMux必須）を選ぶと、生成されるcandidateの数が半分になる|

---

# createOffer

```js
    // let the "negotiationneeded" event trigger offer generation
    pc.onnegotiationneeded = function () {
        pc.createOffer().then(function (offer) {
            return pc.setLocalDescription(offer);
        })
        .then(function () {
            // send the offer to the other peer
            signalingChannel.send(JSON.stringify({ "desc": pc.localDescription }));
        })
        .catch(logError);
    };

```

- APIのコールバックはPrimise仕様に変わっている
  - createOfferについては、Firefoxが昨年、Chromeがつい最近対応済み
- `pc.onnegotiationneeded` 大事！
  - Offer/Answerの発火タイミングをブラウザが支持してくれる
  - addStream / removeStream 等を利用する場合は必須

---

# ontrack

```js
    // once remote video track arrives, show it in the remote video element
    pc.ontrack = function (evt) {
        if (evt.track.kind === "video")
          remoteView.srcObject = evt.streams[0];
    };

```

- `pc.onaddStream` というイベントが有ったけど、あちらはもうオワコン
- WebRTCの世界はStreamをTrack単位で扱う方向に変わってきている
  - `pc.ontrack` は大事

---

# Trackとは？

- WebRTCにおける通信経路の概念図

![image](https://qiita-image-store.s3.amazonaws.com/0/6651/9e52a445-4c38-22b4-f779-9a3577d6b265.png)

---

# getUserMedia

```js
    // get a local stream, show it in a self-view and add it to be sent
    navigator.mediaDevices.getUserMedia({ "audio": true, "video": true }, function (stream) {
        selfView.srcObject = stream;
        if (stream.getAudioTracks().length > 0)
            pc.addTrack(stream.getAudioTracks()[0], stream);
        if (stream.getVideoTracks().length > 0)
            pc.addTrack(stream.getVideoTracks()[0], stream);
    }, logError);
```

- `getUserMedia`は[Device and Sensors WG](https://www.w3.org/2009/dap/)と[WebRTC WG](https://www.w3.org/2011/04/webrtc/)の合同TF
- 仕様書としてはRTCPeerConnectionとは別だが、議論の主導権はWebRTC WGが握っている
- `navigator.getUserMedia()`は旧来の仕様なので注意
- こちらもCallbackのPromise化が進んでいる

---

# 今後重要になるAPI仕様

---

# RTCRtpSender/RTCRtpReceiver

- MediaStreamTrackの送信、受信に関する様々な制御が可能
- Firefoxにはすでに`getSender`/`getReceiver`が搭載されている

```js
peer.getSenders()
Array [ RTCRtpSender, RTCRtpSender ]

peer.getSenders()[0]
RTCRtpSender { track: AudioStreamTrack }

peer.getSenders()[1]
RTCRtpSender { track: VideoStreamTrack }
```

---

# RTCRtpSender/RTCRtpReceiver

- 仕様書通りに実装されれば、例えば、`RTCRtpSender.setParameters`でコーデックのパラメーター（`maxBitrate`や`maxFramerate`）等の調整が可能
  - 今はSDPを直接修正するしか無い

---

# RTCRtpSender/RTCRtpReceiver

- こんなやつを書き換える
  - 参考:[H.264によるビデオチャットを行う](http://qiita.com/yusuke84/items/9ae2f170b8ae2fea5e1d)

```
m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:Xcn23/VduEyHSDiF
a=ice-pwd:bVgn5UOhyAjHWySy9C0otLmi
a=fingerprint:sha-256 47:6D:93:03:82:4A:22:6F:A2:65:4E:26:7E:D9:ED:0E:51:54:8F:D8:EE:DF:62:C1:36:E4:0C:97:49:32:BE:C3
a=setup:actpass
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=sendrecv
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:107 H264/90000
a=rtcp-fb:107 ccm fir
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 goog-remb
a=rtcp-fb:107 transport-cc
a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:116 red/90000
a=rtpmap:117 ulpfec/90000
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=101
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=107
a=rtpmap:98 rtx/90000
a=fmtp:98 apt=116
```

---

# RTCRtpTransceiver

- `setCodecPrefences`でコーデックの種類を指定できる
- `setDirection`でメディアの方向、活性非活性を設定可能
  - `sendrecv` : 送受信
  - `sendonly` : 送信のみ
  - `recvonly` : 受信のみ
  - `inactive` : 非活性
- 現状は`createOffer` / `createAnser`のオプションである`offerToReceiveVideo` / `offerToReceiveAudio`で設定

---

# RTCRtpTransceiver

- `offerToReceiveVideo` / `offerToReceiveAudio`と方向の組み合わせ

|それぞれの値|Offer側のSDPの方向|Answer側のSDPの方向|
|:--:|:--:|:--:|
|true|sendrecv|sendrecv|
|true|sendrecv|sendrecv|
|false|sendonly|recvonly|
|false|sendonly|recvonly|

- Offer側に依存する
- ディフォルトは `true`
- `inactive`の使いドコロは？
  - 途中でメディアの送信を止めたい場合
  - MultiStream時に途中で参加者が離脱した場合
  - トランスポートのウォームアップ

---

# 覚えておいたほうがいい仕様

---

# RTCIceTransport

- P2Pのコネクションを管理する
- そもそもICEとは？
    - ICE(Interactive Connectivity Establishment, RFC5245)
    - STUN/TURNといったプロトコルを利用してNATを超えるための手順が規定されている

---

# RTCIceTransport

#### ICEについておさらい

- シグナリングを通して収集したCandidate（後述）の情報を元に通信可能かどうかを試行する

- 試行には[UDPホールパンチング](https://ja.wikipedia.org/wiki/UDP%E3%83%9B%E3%83%BC%E3%83%AB%E3%83%91%E3%83%B3%E3%83%81%E3%83%B3%E3%82%B0)という手法を用いる（ここでは割愛）

![image](https://qiita-image-store.s3.amazonaws.com/0/6651/ea3c95ef-fdff-f860-0378-fb81c8a0f510.png)

---

# RTCIceTransport

#### RTCIceTransportState

- 接続の試行はステータス管理されている

<img width="625" alt="icetransportstate.png" src="https://qiita-image-store.s3.amazonaws.com/0/6651/12ffd52a-702f-ebce-cffa-ce3397bc8057.png">
*引用元：https://www.w3.org/TR/webrtc/#idl-def-rtcicetransport*

- ポイントは `dissconnected`
    - 通信状態が悪いなどで`dissconnected`になった場合は勝手に再接続する
        - モバイル環境やwifiと3gの切替時には重宝する機能可能性がある
    - `failed`になると失敗する（通信断）

---

# RTCIceCandidate

#### Candidateについておさらい

- Candidateは通信を試行するための各種情報の集まり

```
candidate:3692472706 1 udp 2122260223 192.168.1.1…eration 0 ufrag ot0u network-id 1 network-cost 10
```

- 含まれている主要なもの
  - プライオリティ（接続優先度）
  - IPアドレス
  - プロトコル(tcp/udp)
  - ポート
  - タイプ（次頁）
  - network-cost（Chromeのみ、最近つくようになったはず）

---

# RTCIceCandidate

|タイプ|意味合い|
|:--:|:--|
|host|NICから得られるアドレス|
|srfix|STUNによって得られるNATの外側のアドレス|
|prflx|UDPヒールパンチング中に発見したアドレス|
|relay|TURNに対しての接続が許可された時に取得できるアドレス|

- どういう経路でP2Pの通信が確立したかを確認したり、逆に通信経路を限定したりいろいろとできる

---

# RTCIceCandidate

#### ティップス：IPリーク問題

- 参考：[webrtcH4cKS: ~ How to stop a leak – the WebRTC notifier](https://webrtchacks.com/webrtc-notify/)

- 先述したとおり様々なIPアドレス情報を収集し全てを交換するため、相手に知られたくないIPアドレスまで漏れてしまう可能性がある

- 対処策
    - ブラウザ側で発見されないようにする
        - ChromeはExtension（[WebRTC Network Limiter](https://chrome.google.com/webstore/detail/webrtc-network-limiter/npeicpdbkakmehahjeeohfdhnlpdklia)）が公開されている

---

# RTCStats

- 統計情報収集用API


- [WebRTC 1.0: Real-time Communication Between Browsers - W3C Working Draft 03 August 2016](https://www.w3.org/TR/webrtc/) より

```js

var baselineReport, currentReport;
var selector = pc.getSenders()[0].track;

pc.getStats(selector).then(function (report) {
    baselineReport = report;
})
.then(function() {
    return new Promise(function(resolve) {
        setTimeout(resolve, aBit); // ... wait a bit
    });
})
.then(function() {
    return pc.getStats(selector);
})
.then(function (report) {
    currentReport = report;
    processStats();
})
.catch(function (error) {
  log(error.toString());
});

```

---

# RTCStats

- `chrome://webrtc-internals`のような情報をプログラム側から収集可能
- 現在のAPI実装はブラウザの独自実装
- [callstats.io](http://callstats.io/)のようなStatsを収集してくれるサービスも有る
- 実装したイメージ（次頁）

---

<img width="974" alt="webrtc-stats.png" src="https://qiita-image-store.s3.amazonaws.com/0/6651/63dade71-3206-cf84-2b91-4557988aa70f.png">

---

# API仕様の話はこれで終わりです

---

# 最近のブラウザアップデート状況

---

# Chrome

---

# Chrome（M49〜M53）

#### 独自仕様でガンガンいろいろなものを入れてくる

- MediaRecoder APIサポート
  - ブラウザ上で映像音声の録音が可能に
  - [公式デモ](https://webrtc.github.io/samples/src/content/getusermedia/record/)
- Remote Audio TrackをWebAudioAPIやMediaRecoderAPIで操作可能に
  - 開発者的には待ちに待った機能で活用するとこんなことができる
    - [ブラウザでMCU作ってみた@mganeko](http://www.slideshare.net/mganeko/webrtc-build-mcu-on-browser)
- DTLSのハンドシェイク等にECDSA証明書が利用可能になった
  - それまではRSA証明書のみ
- ECDSAベースの証明書生成にも対応

---

# Chrome（M49〜M53）

- H.264対応
  - M50でフラグ付き
  - M51でFirfoxとの相互接続性を向上
  - M52でフラグなしの正式サポート
- Opusがv1.1からv1.1.2へアップグレード
- Audio Screen　Shareに対応
  - WindowsとChromeOSに限定されるが、システムオーディオをシェア可能
- Canvas Caputure Streamに対応
  - Canvasの映像からMediaStreamを生成し送信することが可能
- pc.createOffer()のpromise対応
- AndroidにてCamera 2 APIをサポート（パフォーマンス向上）
- navigator.webKitGetUserMediaのベンダープレフィックスを削除
- navigator.mediaDevices.getUserMedia()に対応

---

# Firefox(44〜50)

#### 標準仕様に則った地道なアップデートが多い

- Simulcastの試験実装開始
- RTCRtpEncodingParametersに対応
- RTCRtpSender.setParameters()に対応
- ICE Restart対応
- MediaRecorder　on Androidに対応
- MediaStream.addTrackイベントに対応
- MediaStreamTrack.readyState()に対応

---

# ChromeとFirefoxの相互接続

#### ティップス：MultiStream対応

- 複数のストリームを同じ通信経路（トランスポート）上でやり取りする場合の方式がChromeとFirefoxで異なる
- 具体的にはSDPのセッション記述部、メディア記述部の記載が変わる
- Chromeは`Plan B`、Firefoxは`Unified Plan`という方式をとっており、将来的には`Unified Plan`に統一される
  - 参考: [Need to implement WebRTC "Unified Plan" for multistream](https://bugs.chromium.org/p/chromium/issues/detail?id=465349)
- 現在は、ChromeとFirefoxでマルチストリームの相互接続をするにはSDPの変換が必要

---

# Edge

- 2015/9 にORTC対応
 - [adaptor.js](https://github.com/webrtc/adapter)というshimを使えばChrome/Firefoxと相互接続可能
 - ビデオコーデックが H.264UCのみなので音声のみ
- 2016/8 にWebRTC1.0の機能が一部実装始めている
  - H.264/AVCの実装も進んでいる

![edge-flang.png](https://qiita-image-store.s3.amazonaws.com/0/6651/91ddc436-d4d2-572b-c78a-6faee7aa0757.png)

- あと少し！

---

# Safari

- WebKitの実装は始まっている

<img width="1199" alt="webkit-webrtc.png" src="https://qiita-image-store.s3.amazonaws.com/0/6651/c7851953-d5b5-eb51-f71f-af4841d1e49e.png">
https://webkit.org/status/#specification-webrtc

---

# WebRTCネイティブアプリアプリ対応

---

# ネイティブアプリアプリで利用する方法はいくつか

- ハイブリッドアプリ
  - Electron
  - Cordova
- ネイティブアプリ
  - React-Native
  - libwebrtc(WebRTCのOSSスタック)を自分でビルドして利用する

---

# メディアサーバーの動向

---

# P2PだけじゃないWebRTC

- WebRTCはP2Pが基本だが、複数人での同時利用や録音録画などを行う場合にメディアサーバー(MCU/SFU) を利用することができる

---

# MCU

![SFUMCUイメージ.jpg](https://qiita-image-store.s3.amazonaws.com/0/6651/35c60228-8ce8-ca5a-d298-8e2153e4b230.jpeg)

- 全てPeerからのメディアを集約、ミキシングし配信
- Peerの負荷をMCU側に集約
- 全てのストリームをエンコード／デコードするため、MCUのCPU性能がボトルネックになる（エンコードを1本化する方式も存在する）
- トランスコード、オーバーレイ、録画、録音、何でもできる

---

# SFU

![SFUMCUイメージ_SFU1.jpg](https://qiita-image-store.s3.amazonaws.com/0/6651/47844be7-2093-098e-26d7-6c6f3918128e.jpeg)
![SFUMCUイメージ_SFU2.jpg](https://qiita-image-store.s3.amazonaws.com/0/6651/07aeb58d-f283-4cfa-1941-4966bf6b20b1.jpeg)

- 各Peerからのメディアを必要数分複製し配信
- 配信に必要な帯域の一部（上り分）をSFU側に集約
- 全てのストリームの復号化／暗号化を行う
- ストリーム自体に手を加えないがめSFUの負荷は軽い
- SVC+Simulcastと組み合わせることにより真価を発揮する

---

# SVC+Simulcastとは？

- 同時に複数のPeerに映像を送る場合、Peer毎に受信環境が違う可能性がある
  - 例えば、自宅PCとLTEスマホ等
- SVCというコーデックの仕組みとSimulcastを使えば、受信者に合わせた適切な解像度・ビットレートの動画を配信することができる
- 仕組みがない場合、SFUでは一番低レベルな受信者に合わせることになり、全員の品質を落とすことになる

---

# MCU/SFUの代表的なプロダクト

|プロダクト名|SFU|MCU|録音・録画|OSS|
|:--:|:--:|:--:|:--:|:--:|
|[Intel Collaboration Suite for WebRTC](https://software.intel.com/en-us/webrtc-sdk)|:o:|:o:|:o:|:x:|
|[Janus+Janus VideoRoom plugin](https://janus.conf.meetecho.com/docs/janus__videoroom_8c.html)|:o:|:o:|:o:|:o:|
|[Jitsi VideoBridge](https://jitsi.org/Projects/JitsiVideobridge)|:o:|:x:|:o:|:o:|
|[Kurent](http://www.kurento.org/)|:o:|:x:|:o:|:o:|
|[Lincode](http://lynckia.com/licode/)|:x:|:o:|:o:|:o:|
|[Medooze](http://www.medooze.com/)|:o:|:x:|:x:|:o:|
|[SORA](http://sora.shiguredo.jp/)|:o:|:x:|:o:|:x:|
|[PowerMedia XMS](http://www.dialogic.com/en/products/media-server-software/xms.aspx)|:x:|:o:|:o:|:x:|

- @iwashi86氏の「[WebRTC MediaServer(SFU/MCU)の情報まとめ](http://iwashi.co/2016/09/03/webrtc-sfu-mcu-summary)」が参考になります

---

# プラットフォームサービスの動向

---

# プラットフォームサービスの動向

- マルチに使えるもの、業界に特化したものいろいろと出ている
- 是非活用してみてください

|プロダクト名|SDK|特徴|
|:--:|:--:|:--:|:--:|
|[TokBox](https://tokbox.com/)|JS/Android/iOS|SFUを利用したMediaConnectionのみ提供|
|[Skylink](https://skylink.io/)|JS/Android/iOS|IE/Safariプラグインを提供|
|[ICELINK](https://www.frozenmountain.com/products/icelink)|JS/Android/iOS/Windows/Linux　等|対応プラットフォームが多い|
|[Intel Collaboration Suite for WebRTC](https://software.intel.com/en-us/webrtc-sdk)|JS/Android/iOS/Windows|先述したメディアサーバーやGateWayサービスなども提供|
|[SkyWay](https://skyway.io/)|JS/Android/iOS|日本語サポートが可能|
|[CafeX](https://www.cafex.com/)|JS/Android/iOS|コンタクトセンターに特化|
|[Twillio](https://www.twilio.com/webrtc)|Android/iOS|SIP to WebRTCのGateWayを提供|

---

# テストサービスの動向

---

# テストサービスの動向

- [testRTC](http://testrtc.com/)
  - WebRTCのテスト、モニタリング、分析プラットフォーム

---

# WebRTCの情報収集チャネルを紹介

---

# 最新のネタを収集したい時は？

- [WebRTC Standard](https://webrtcstandards.info/)
  - 各ブラウザのアップデート状況や標準化の状況が更新される
  - 頻度高め
- [WebRTC Hacks](https://webrtchacks.com/)
  - WebRTCの技術系トピックスが豊富
  - Chad Hart氏が運営
- [bloggeek](https://bloggeek.me/)
  - 技術よりな話題からビジネス寄りな話題まで幅広く載っている
  - Tsahi Levent-levi氏のブログ
- [WebRTC by Dr Alex](http://webrtcbydralex.com/)
  - Alex. Gouaillard氏のブログ
- [WebRTC News](https://news.google.com/news/section?hl=en&gl=us&pz=1&ned=us&q=webrtc)
　  - google news
　  - Bizよりな情報が知りたいときはチェック

---

# ブラウザのアップデート情報を収集したいときは？

- [Discuss-webertc](https://groups.google.com/forum/#!forum/discuss-webrtc)
  - ChromeやFirefoxのリリース情報が毎回神
- [mozilla.dev.media](https://groups.google.com/forum/?hl=ja#!forum/mozilla.dev.media)
  - Firefoxに関するWebRTCやWebAudio関連の議論が展開されている
- [Microsoft Edeg Dev blog](https://blogs.windows.com/msedgedev/)
  - Edgeのアップデートについてはこちらで
- [Webkit](https://webkit.org/blog/)
  - Safari/Webkitの最新開発状況はこちら

---

# 日本語情報を収集したいときは？

- [WebRTC-JP Slack](http://webrtc-jp-slackin.herokuapp.com/)
  - 質問したら誰かが答えてくれる
  - ギブテクノ精神で
- [Twitterハッシュタグ #webrtcjp](https://twitter.com/search?q=%23webrtcjp&src=typd)
  - 日本語情報発信中

---

# 最後に・・・

---

# ちょっと宣伝

- WebRTC Meetup Tokyo
  - ２ヶ月に一回開催（次回は10月）
  - https://atnd.org/groups/webrtc
  - 参加者のレベルは高め

- WebRTCハンズオン勉強会
  - 9/19
  - http://connpass.com/event/35114/
  - 初心者向けです！（もう埋まってるけど・・・）

---

# 今日話したこと

- WebRTC五周年の話
- 目標設定
- WebRTC概要
- WebRTCの技術的習熟度
- WebRTCの標準化の仕組み
- API仕様でチェックしておくべきポイント
- 今後重要になるAPI仕様
- 最新ブラウザアップデート状況
- WebRTCネイティブアプリアプリ対応
- ディアサーバーの動向
- プラットフォームサービスの動向
- テストサービスの動向
- WebRTCの情報収集チャネルを紹介

---

# 最後までお付き合いいただきありがとうございます

---

# 参考文献

- https://webrtc.org/
- https://ortc.org/faq/
- https://www.w3.org/TR/webrtc
- http://www.slideshare.net/iwashi86/20168webrtc
- http://webrtc-security.github.io/report_ja/
- http://iwashi.co/2016/09/03/webrtc-sfu-mcu-summary
- http://jxck.hatenablog.com/entry/ortc-to-webrtcnv