Edited at

WebRTCデバッグ入門


はじめに



自己紹介



今日のスライドの目的


  • WebRTCサービスを開発する際に必要となる、各種デバッグ技術をお伝えします



前提条件


  • Webブラウザでの利用を前提とします


  • WebRTCハンズオン の知識が最低限必要となりますので、まだ読んでいない方は先にご一読ください。

  • MediaChannelのみしか扱いません

  • デバッグ方法やそのためのノウハウをご紹介するだけなので、事象解決には別の努力がきっと必要です



目次


  • よくあるトラブルユースケース

  • その他知っておくと便利なトピックする



よくあるトラブルユースケース


  • うまくつながらない時がある



「つながらない」場合の切り分け王道パターン


  • 切り分け1:ネットワーク的に接続されているか

  • 切り分け2:音声、映像ストリームが流れているか



切り分け1


  • ネットワーク的に接続されているかどうかを確認する


    • Chromeの場合


      • アドレスバーで chrome://webrtc-internals

      • 一つだけ 太字Conn-xxxx-x-x という項目がある(有効なTransport/輸送路)


        • 存在しなければネットワーク的に接続されているか

        • ある場合でもタイムスタンプが更新されていない場合はその時点で利用されていない









  • サンプル

no1.png


  • 表示されている項目と意味(重要なものだけ抜粋)

項目
意味

timestamp
タイムスタンプ
現在利用しているTransportかどうかはこのタイムスタンプが更新されているかどうかで判断

googxxxxAddress
ローカル・リモートそれぞれのIPアドレスとポート番号

xxxxCandidateId
ローカル・リモートそれぞれで採択されたCandidate情報のID※1(通信するためのIPアドレス、ポート番号等の候補情報)
このIDでサイト内を検索すると詳細が確認できる

googxxxxCandidateType
ローカル・リモートそれぞれのCandidateタイプ
relay : TURN経由の接続
それ以外 : TURNを使用せずにダイレクト接続



  • ※1 採択されたCandidate情報


    • これはFirefoxの方が見やすい


      • アドレスバーで about:webrtc





no2.png



切り分け2


  • 音声、映像ストリームが流れているかを確認する


    • Chromeの場合


      • アドレスバーで chrome://webrtc-internals


        • AudioTrackとVideoTrack情報を確認する



          • ssrc_xxxxxxx_send : 送信側でAudioとVideoで2つ(Track単位)


          • ssrc_xxxxxxx_recv : 受信側で同じく2つ



        • 送受信バイト数がカウントアップしていればストリームは流れている









  • サンプル

no3.png


  • 表示されている項目と意味(重要なものだけ抜粋)

項目
意味

msid
MediaStreamIDでAudioTrackとVideoTrackを束ねた1つのStreamを指す
JavaScriptから識別することができる

timestamp
タイムスタンプ
有効なTrackかどうかはこのタイムスタンプが更新されているかどうかで判断

bytesSent
送受信バイト数

mediaType
audio/video

packetsLost
パケットがロストした場合に表示される

ssrc
Synchronisation Sourceという。ここではRTP(リアルタイムプロトコル)で利用する識別子

transportId
先程見た Conn-xxxx-x-x に該当
このTrackがどのTransport(輸送路)を利用しているかわかる

googCodecName
仕様しているコーデック
Audioであれば、Opusが主流
Videoであれば、VP8H264が主流

googTrackId
TrackIDでJavaScriptから識別することもができる



  • 参考:Transport、MediaStream、Trackの関係

no4.png



よくあるトラブルユースケース


  • カメラの映像やマイクの音声が取得できない



ブラウザのデバイス認識状態を確認



  • プルダウンで選択しブラウザをリロードすることで有効になる


    • Chrome
      no5.png

    • Firefox
      no6.png



  • PCに利用できるマイク、カメラが接続されていない場合、 navigator.mediaDevices.getUserMedia のAPIでエラーが返ってくるので注意


  • Chromeは一度デバイス選択するとその状態が記録されるので、うっかりアクセスをブロックすると、以後ブロックを明示的に開場するまで利用できないので注意




  • ブラウザで認識しているのに映像が出ない、音が聞こえない場合に考えられること


    • Video


    • navigator.mediaDevices.getUserMediaで指定するキャプチャサイズ(widthheight)の映像をWebカメラから取得できない

    • Audio

    • PC側のマスターボリュームが0になっているなど





よくあるトラブルユースケース


  • PCやブラウザの動作が重い、途中で映像が止まる、音が途切れる



P2P接続によるマシン負荷が高い


  • P2Pによるビデオチャットを複数本同時に行こない(フルメッシュ接続)多人数ビデオチャットを実現する場合、マシンへの負荷が増大する


    • no7.jpeg

    • PCなどでは主にエンコード処理の負荷が原因

    • モバイル端末ではデコード処理も負荷要因になる可能性も





P2P接続によるマシン負荷が高い


  • 対策1



    • navigator.mediaDevices.getUserMedia で指定するキャプチャサイズを小さくする

    • 画面共有等はフレームレートを下げる(Firefoxでは効かない)



function startVideo() {

navigator.mediaDevices.getUserMedia({
video: {
width: {
min: 320,
max: 1280
},height: {
min: 240,
max: 720
},frameRate: {
min: 1,
max: 10
}
},
audio: true})
.then(function (stream) { // success
playVideo(localVideo,stream);
localStream = stream;
}).catch(function (error) { // error
console.error('mediaDevice.getUserMedia() error:', error);
return;
});
}



ネットワークの品質(速度等)が良くない


  • WebRTCにはネットワーク帯域を推定し動的に転送レートを変動させるが、限度がある

  • 【注意】プロバイダが提供する速度測定サイトの結果はWebRTCではあまりあてにならない


    • 速度測定サイトはプロバイダが提供するサーバとの転送速度を測るものだから

    • WebRTCではEnd-to-Endでの速度を測定する必要がある






参考:WebRTCはどのくらいの通信帯域を利用するのか



  • 送信する映像のサイズ、フレームレート数によってい左右される


    • 測定条件



  • カメラ前の画面の動きはほぼ無い


  • ローカルで計測(ネットワーク遅延は無視)


  • ブラウザは Chrome M54



  • コーデック:VP8


    • 測定結果



設定
ビットレート

640x480/30fps

no10.png
1.5Mbps前後

320x240/30fps

no11.png
600kbps前後

320x240/10fps

no12.png
400kbps前後

1920x1080/30fps

no13.png
2Mbps前後



  • WebRTCによるアプリケーションを実業務で開発導入する場合は、ネットワーク設計まで含めて考慮憂する必要がある



P2P接続によるマシン負荷が高い


  • 対策2


    • WebRTCプラットフォームサービスが提供するMCUやSFUを利用する

    • MCUやSFUを自分で建てて運用する(上級)





MCU(Multipoint Control Unit)


  • メディアサーバを用意して映像音声をミキシングすることで、人数が増えた場合でも、送受信するメディアの数が変わらない

  • トランスコード、オーバーレイ、録画、録音、何でもできるが、サーバ側の処理で画面レイアウトが決まってしまう等、クライアント側での自由度がない

  • 代表例:Skype

no8.jpeg



SFU(Selective Forwarding Unit)


  • 送信側のMediaをサーバで受信者数分スプリットして配信することで、送信側の負荷(エンコード負荷)を押さえることができる


  • 受信者の処理能力にバラツキがある場合には、RTCPを利用し品質をコントロールする機能が、SFU側に必要となる


    • Simulcast+SVCという技術を組み合わせて解決する方法もある(この場合は、受信側の対応が必須)



  • 代表例:Google Hangout


no9.jpeg



その他知っておくと便利なトピックする


  • ICEによる自動再接続



ICEとは?


  • ICE(Interactive Connectivity Establishment)はNAT超えするためのユーティリティ

  • WebRTCではICEを利用してP2P通信を確立する


    • ICEの手順

    • 1.通信候補の収集


      • IceCandaidateという情報をブラウザが収集する



    • 2.通信候補の交換


      • シグナリングサーバを介して相手と交換



    • 3.通信候補の整理


      • P2PなのかRelayなのか(つまりTURN経由)等を考慮して優先度が高い順に候補を並べる

      • TrickleICEという手法の場合は省略される



    • 4.通信の試行


      • 一般的にUDPホールパンチングと呼ばれる手法を利用して通信を試みる

      • 新しく候補が見つかることもある



    • 5.通信手段を確定


      • 通信に成功した候補の中からどのルートを使うかを確定する(制御権を持つPeerが決める)







実は繋がったら終わりではない


  • ICEは通信状態をモニタリングしており、一時的な通信断については自動で復旧する

no15.png


  • 例:前回ハンズオンで開発したアプリの場合

    // ICEのステータスが変更になったときの処理

peer.oniceconnectionstatechange = function() {
console.log('ICE connection Status has changed to ' + peer.iceConnectionState);
switch (peer.iceConnectionState) {
case 'closed':
case 'failed':
// ICEのステートが切断状態または異常状態になったら切断処理を実行する
if (peerConnection) {
hangUp();
}
break;
case 'dissconnected':
break;
}
};


  • ICEステータスの変化(コンソール抜粋)


    • 数秒程度の通信断であれば復旧できる可能性あり



ICE connection Status has changed to connected ←接続候補をチェック中

ICE connection Status has changed to completed ←全ての候補のチェックが完了
ICE connection Status has changed to disconnected ←故意に通信を切断
ICE connection Status has changed to connected ←通信断を解除
ICE connection Status has changed to completed ←再び接続
ICE connection Status has changed to disconnected ←故意に通信を切断
ICE connection Status has changed to failed ←そのまま放置すると修復不可状態に
sending close message
ICE connection Status has changed to closed ←ICEのプロセスが全て終了



その他知っておくと便利なトピックする


  • どのようなシーンでTURNサーバは有効なのか?



TURNサーバはどのように利用されるのか?



  • TURNサーバとは?


    • P2Pによる通信ができない場合にリレーするためのサーバ



  • Q. こうやってプログラムすれば全ての通信がTURN経由になると思いますか?


    let pc_config = {"iceServers":[

{"urls":"stun:stun.xxxx.xxx:3478"},
{"urls": "turn:turn.xxxx.xxx:3478?transport=tcp",
"username:": "username",
"credential": "password"
}]
};
let peer = new RTCPeerConnection(pc_config);



  • A. NO


    • TURNサーバはあくまでCandidate候補(接続候補)の1つとして扱われ、実際にTURNサーバを利用するかどうかはネットワークの状況次第でブラウザが判断します

    • STUNのみでつながるか、TURNが必要かの見極めポイント


      • NATタイプによる制限

      • no14.png

      • 公衆wifi等で導入されるプライバシーセパレータ(端末同士の通信をセキュリティ上規制)

      • UDP通信がブロックされており、TCP通信しか利用できない


        • TURNサーバを利用するとクライアント→TURNサーバの通信をTCP(ポート番号も自由に指定可能)で行うことができる









まとめ


  • よくあるトラブルユースケース


    • うまくつながらない時がある

    • カメラの映像やマイクの音声が取得できない

    • PCやブラウザの動作が重い、途中で映像が止まる、音が途切れる



  • その他知っておくと便利なトピックする


    • ICEによる自動再接続

    • どんなシーンでTURNサーバは有効なのか?





参考文献(もっと詳しく知りたい方向け)



ご清聴ありがとうございました!