LoginSignup
116
102

More than 3 years have passed since last update.

SkyWay初心者からステップアップしよう

Last updated at Posted at 2018-04-19
1 / 64

はじめに


自己紹介

  • なかゆうすけ(@yusuke84
  • 仕事:
  • コミュニティ
    • WebRTC Meetup Tokyo 主催
    • WebRTC Beginners Tokyo 主催

この資料は何?

  • サポート等で問い合わせが多いSkyWayのティップスを厳選して紹介します

達成したいゴール

  • SkyWayを利用するエンジニアの困った:tired_face:を、1つでも多く解決し ハッピー:heart_eyes: になってもらう
  • SkyWay初心者からSkyWay中級者へステップアップしてもらう

今日お話する内容

  • SkyWaySDKの通信モデル
  • SkyWayの通信要件
  • SkyWayを利用したWebRTC通信のコネクティビティ(メディアコネクションの場合)を確認する
  • SkyWayを利用する際の通信帯域
  • SkyWayの動作確認済みブラウザとOS
  • SkyWayを配信に利用する場合のティップス

本題に入る前に…お知らせ


ダッシュボードで利用量の閲覧ができるようになりました

スクリーンショット 2018-04-19 6.45.28.png

  • APIキー毎に直近2ヶ月分閲覧可能
  • 更新頻度は1日に数回程度
  • 利用量は1MB単位で切り上げ
  • Enterprise Edition利用のお客様は今まで通り「料金・請求」の明細画面からも確認可能

Enterprise EditonへのAPIキー移行ができるようになりました

スクリーンショット 2018-04-19 7.00.00.png

  • Community EditionからEnterprise Editionへ移行可能
    • 逆はできない
  • サービス停止無しで移行可能
  • 利用量表示のデータはCommunity Editionでの実績が反映されますが、課金は移行完了した時点から開始

SkyWaySDKの通信モデル

SkyWayを利用するにあたり、知っておくべき概念です。


Peer

  • SkyWayを利用して何らかのサービスを作る場合、最初にPeer(ピア)というインスタンスを作成する
  • Peerは、SkyWayのシグナリングサーバや、他のクライアントとの接続を管理するエージェント

PeerID

  • Peerを作成(new Peer)すると、作成したPeerがシグナリングサーバへ接続する
  • 接続が成功すると、Peer.openイベントの発火と共に、SkyWayサーバ側がランダムに作成するPeer IDという値を取得できる
  • Peer IDはPeerを一意に識別するためのID
  • 接続が失敗した場合はPeer.errorイベントが発火する

通信モデルその1「電話モデル」

  • 電話で通話する場合と同様に1:1で通信するモデル
  • 通信を開始する場合には、相手のPeerIDを何らかの手段で知る必要がある

音声・映像(メディアチャンネル)

  1. 相PeerIDを指定して相手に発信(peer.call)
  2. callイベントが着信側で発火
  3. そのcall要求に対してanswer()を呼ぶことで通信確立
  4. 音声・映像はStreamイベントの発火とともに取得できる

データの場合(データチャンネル)

  1. peer.connect()で相手に接続要求
  2. 接続が確立するとconnectionイベントが発火
  • メディアチャンネルと異なりanswer()を明示的に呼ぶ必要がない

通信モデルその2「ルームモデル」

  • 同一ルームに存在するすべてのPeerで会話するモデル
  • ルームの名前空間はAPIキー毎に独立している
  • APIキーが違う場合は同一ルーム名でも別ルームと扱われて相互通信は出来ない
  • ルームの実現方式にはフルメッシュとSFUの2種類がある
    • 両者の違いはの詳細はこちら
    • 同一APIキー上にフルメッシュとSFUで方式で同時に同一ルーム名のルームを作ることは出来ない

  1. ルーム名を指定してルームに参加(peer.joinRoom)
  2. 他の参加者からメディアを受信した場合はRoom.streamイベントが発火する
  3. Room.Close()でルームからの退出する
  • ルームの削除は参加者が全員退出したら行われる
    • 明示的に消す方法はなし

メディアストリームの扱い

  • SkyWayのSDKではメディアストリームは入力時に渡して出力時に取得するのみが原則となる
    • iOS/Android SDKはメディア作成APIを搭載しているが入力はプログラム側から行う

sdk-mediastream-processing.png


SkyWayの通信要件


その1(管理系)

  • ディスパッチャ
    • TCP443(HTTPS Protocol)
    • dispatcher.webrtc.ecl.ntt.com
  • シグナリングサーバ
    • TCP443(プロトコルはSocket.io依存)
    • *.webrtc.ecl.ntt.com
    • シグナリングサーバは複数台構成のためワイルドカードで記載

その2(WebRTC関連)

  • P2P通信
    • ポート番号はUDPハイポートレンジを利用し毎回ランダムに決定
    • IPアドレスもクライアントアドレスは環境に合わせて変わる
  • STUN通信
    • UDP3478(STUN Protocol)
    • stun.webrtc.ecl.ntt.com
    • 役割
      • 自分自身のIPアドレスとポート番号を取得
      • STUNサーバへアクセスが出来ずP2P通信も出来ない場合は、TURNサーバで代用

  • TURN通信
    • TCP443,UDP443(低コストでつながる方を勝手に選択)
    • turn.webrtc.ecl.ntt.com
    • 役割
      • P2P通信できない場合の代替手段

TURN通信は3パターン

  • AさんのみTURN(プロトコル)を利用する場合

image.png


  • AさんとBさん両方が同一のTURN(プロトコル)を利用する場合

image.png


  • AさんとBさん両方が別々のTURN(プロトコル)を利用する場合

image.png


TURNサーバは極力使わないようにネットワーク設計する

  • UDPによるハイポートの通信を規制しない
  • STUNサーバへのアクセスを許可する
  • エンタープライズユースの場合はNATタイプに気を使う

image.png


絶対TURNサーバが必要な場合

  • UDP通信が禁止
    • TURNプロトコル(TCP)を利用した通信をするしかない
  • 通信相手をACL等で制限する必要がある
    • 通信相手を固定する場合はTURNサーバのアドレスで固定するしかない
  • IPv6アドレスを持ったPeerがSFUやIPv4アドレスのPeerと通信する場合

SkyWayを利用したWebRTC通信のコネクティビティ(メディアコネクションの場合)を確認する


予備知識〜SkyWay SDKのオブジェクト構造〜

全SDK共通

  • Peer Class/Object
    • シグナリングサーバとの接続を管理する
  • MediaConnection Class/Object
    • メディアコネクション(映像・音声のP2P通信)を管理する
  • DataConnection Class/Object
    • データコネクション(データのP2P通信)を管理する
  • SFURoom Class/Object
    • SFUのRoom接続を管理する
  • MeshRoom Class/Object
    • MeshのRoom接続を管理する

iOS/Android SDKのみ

  • iOS

    • SKWNavigator
      • ブラウザのgetUserMedia APIに相当
    • SKWMediaStream
      • メディアストリーム
    • SKWVideo
      • 映像を表示するレンダラービューオブジェクト
  • Android

    • Navigator
      • ブラウザのgetUserMedia APIに相当
    • MediaStream
      • メディアストリーム
    • Canvas
      • 映像を表示するレンダラービューオブジェクト

シグナリングサーバとの接続が確立できたことを把握

  • 全SDK共通
    • new Peer実行
    • Peer Class/Objectのopenイベントが発火する
    • 以降の処理はすべてこのイベントが発火してから実施する

(参考)new Peerを実行すると内部的には何が行われるのか?

  1. ディスパッチャーサーバから接続対象のシグナリングサーバを取得
    • シグナリングサーバは複数台で冗長構成を取っているため接続対象のサーバをディスパッチャーサーバに毎回問い合わせる
    • signaling-xxxxxxx.webrtc.ecl.ntt.com 等のURLを取得
  2. シグナリングサーバへの接続
    • 認証サーバ連携している場合は認証情報の検証
    • PeerIDの生成
    • TURNサーバ接続用の認証情報取得
  3. シグナリングサーバとは常時接続された状態を維持
    • 定期的にping/pongを実施
  4. openイベントが発火

メディア通信が開始されたことを把握

  • JS SDK

    • MediaConnectionオブジェクトまたはRoomオブジェクトのstreamイベント
  • iOS/Android SDK

    • P2Pの場合
      • SKWMediaConnection on:SKW_MEDIACONNECTION_EVENT_STREAM
      • MediaConnection.MediaEventEnum.STREAM
    • Roomの場合
      • SKWRoom on:SKW_ROOM_EVENT_STREAM
      • Room.RoomEventEnum.STEAM

これらのイベントが発火すると実際にメディアデータが送受信される


通信状況をモニターする

  • iOS/Android SDK
    • 機能としては用意されてないが、Webアプリと相互接続する場合、ブラウザ側で確認可能
  • JS SDK
    • ChromeまたはFirefoxのWebRTC開発者向けツールでモニタリング
    • 詳しくは次のページで

Chrome WebRTC Internalsの使い方

  • 情報量が多いのでChromeがオススメ
  • WebRTCで通話中に別のタブで開発者向けツールにアクセス
    • chrome://webrtc-internals/

WebRTC Internals その1

internals1.png

  • WebRTC通信を行っているブラウザのタブ毎にタブが作られるので、該当部分を選択
    • TimeとEventはWebRTCの接続シーケンスがログとして出ている
    • リアルタイムで更新される

  • ICE Connection Stateをチェック

internals2.png

  • ICEとはInteractive Connectivity Establishmentの略で、WebRTCによる通信経路定めるためのプロトコル

  • ICEのステータス遷移

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f363635312f61393966396635362d646166322d326132382d383465352d3336376236326230353436622e706e67.png

ステータス 内容
connnected 通信可能な接続を発見した
でもまだ他の経路情報も探索中
completed すべての経路を探査し終わり通信に利用する経路が確定した

WebRTC Internals その2

internals3.png

  • メディアの通信が行われている場合は、必ず一つだけ太字になっている部分がある
    • 無ければ接続がうまく行っていない

  • チェックする箇所は以下の通り
項目 意味
bytesReceived 受信バイト数
カウンタがリアルタイムに更新される
bytesSent 送信バイト数
カウンタがリアルタイムに更新される
googLocalAddress 自分自身の通信に利用しているIPアドレスとポート番号
TURNサーバを利用している場合はTURNサーバのアドレスとなる
googLocalCandidateType 通信経路の種類を識別
relayはTURNサーバ利用
googRemoteAddress 相手の通信に利用しているIPアドレスとポート番号
TURNサーバを利用している場合はTURNサーバのアドレスとなる
googRemoteCandidateType 通信経路の種類を識別
relayはTURNサーバ利用

WebRTC Internals その3

internals4.png

  • 通信するメディアのAnalyticsが表示される
    • 大まかな帯域等を把握することが出来る
    • 受信側、送信側でそれぞれ確認できる

SkyWayを利用する際の通信帯域


通信帯域はあくまで目安です

用途 帯域
1:1音声通話 40kbps
1:1ビデオ通話(SD) 500kbps
1:1ビデオ通話(HD) 1.5Mbps
4人ビデオ会議(SD) 1.5Mbps

出展: SkyWay利用モデル


 実際どうなの?

  • 計測条件
    • Chrome M66
    • コーデック:VP8
    • フレームレート:指定なし
    • MacBookPro 13inch 2016モデル
    • Logicool BRIO
  • 計測方法
    • カメラの前に座って会議をやっている前提(動き少なめ)
    • 同一PC内でP2Pビデオチャットを実施しwebrtc-internalsで確認

条件 帯域
320x240(QVGA) 320_240_30.png
450kbps前後
640x480(VGA) 640_480_30.png
1.6Mbps前後
720x480(SD) 720_480_30.png
1.6Mbps前後
1024x768(XGA) 1024_768_30.png
1.6Mbps前後
1280x720(HD) 1280_720_30.png
1.6Mbps前後
1920x1080(フルHD) 1920_1080_30.png
1.6Mbps前後
3840x2160(4K UHDTV) 3840_2160_30.png
2Mbps前後

  • 帯域を考える上でのポイント
    • アプリの作りである程度コントロール可能
    • 利用シーンによって変動幅が異なる
      • Web会議用は比較的変動が少ない
      • スマホやスマートグラス等動きがある場合はかなり変動幅が大きい

SkyWayの動作確認済みブラウザとOS

  • ChromeとFirefoxに正式対応

    • 安定版の最新2バージョンに対応
      • 例: 2018.04.19現在 最新の安定版は Version66 なので、動作確認済みブラウザは66と65
    • ブラウザは約6週間でアップデートされるため、JS SDKのアップデートへの追従はお早めに
  • Edge(一部機能のみ対応)

    • P2PとRoom(Meshモード)のみ利用可能
    • Room(SFUモード)への対応予定:無し
      • EdgeがMultiStream機能に対応していないから
  • Safari(一部機能のみ対応)

    • P2PとRoom(Meshモード)のみ利用可能
    • Room(SFUモード)への対応予定:有り
      • 現在のSFUはビデオコーデックがVP8固定のため利用不可
      • 今後コーデックの切り替え機能をリリース予定

  • iOS

    • iOS 8+
  • Android

    • Android 4.2+ (API Level 17+)
  • EPSON MOVERIO BT-300/350

    • Android SDKで動作

SkyWayを配信に利用する場合のティップス


配信に利用できる機能


受信のみモード

  • 自身のMediaStreamをオプションに渡さずに、Roomへjoinすることで受信のみモードになる
// 例
const room = peer.joinRoom("roomName", {
  mode: 'mesh'
});
  • この時、MediaStreamをオプションに渡して参加したメンバがいる場合、そのメンバから受信のみモードメンバへ片方向通信が実現できる

videoReceiveEnabled/audiReceiveEnabled

  • 映像と音声を単独で受信のみにすることが出来る
// 例:音声だけ受信したいしたい
const room = peer.joinRoom("roomName", {
  mode: 'mesh',
  audioReceiveEnabled: true
});

  • 映像と音声を単独で受信のみにすることが出来る
// 例:音声は送受信、映像は受信だけしたい
const room = peer.joinRoom("roomName", {
  mode: 'mesh',
  stream: audioOnlyStream,
  videoReceiveEnabled: true
});

おことわり…


  • replaceStreamで、受信のみモードから通常モード(MediaStreamを送信するモード)への切り替えは動作保障対象外(2018.04.19現在)
    • 送信していたMediaStreamを単純に差し替える用途では問題なく利用可能

それぞれの機能の利用可否まとめ

機能 JS SDK iOS SDK Android SDK
受信のみモード :white_check_mark: :white_check_mark: :white_check_mark:
videoReceiveEnabled/audiReceiveEnabled :white_check_mark: :x: :x:

機能 meshモード sfuモード
受信のみモード :white_check_mark: :white_check_mark: ※1
videoReceiveEnabled/audiReceiveEnabled :white_check_mark: :x:
  • ※1:ワークアラウンドが必要(不要になりました)

配信等のユースケースで活用する場合、SFUモードが必要になることが多いと思います。以後、受信のみモード☓SFUモードreplaceStream☓SFUモードの組み合わせで利用する際のワークアラウンドにフォーカスします。


受信のみモード☓SFUモードのワークアラウンド

2019.04.09 追記
SFUの不具合が解消されたため、このワークアラウンドは不要となりました。


受信のみモードをSFUモードで利用する場合、送信される映像が受信のみモードのユーザ上で再生されない問題がある。この問題は、SkyWayのSFUサーバから映像の再生に必要なキーフレーム※参考情報(外部サイト)が、受信のみモードのユーザに届かないため発生している。

次に示す方法で回避可能。また、送信されるのが音声のみの場合は問題なく利用できる


SkyWayサポートコミュニティ:受信のみモードを併用した多人数でのSFUの利用で開発者の方が記載していただいている、ダミーのjoinRoomを実行する方法が一番良い。

const skyway = new Peer({key:'APIKEY'});
const room = skyway.joinRoom('roomName',{mode: 'sfu'});
room.on('open',async (peerId) => {
    try {
        await dummyRoomJoin();
    } catch (err){
        console.error(err);
    }
});

function dummyRoomJoin(){
    return new Promise((resolve, reject) => {
        const dummyPeer = new Peer({key:'APIKEY'});
        dummyPeer.on('open',() => {
            const dummyRoom = dummyPeer.joinRoom('roomName',{mode: 'sfu'});
            dummyRoom.on('open',() => {
                dummyRoom.close();
            });
            dummyRoom.on('close',() => {
                dummyPeer.destroy();
                resolve();
            });
            dummyRoom.on('error',(err) => {
                reject(err);
            });
        });
    });
};

この他に、canvasで作成した1px X 1pxのダミーストリームを送信する方法もあるが、受信のみモードのユーザからSFUへのUpstreamのメディアコネクションが生成されるため、Roomに参加するユーザ全体の負荷が高くなる。おすすめしない。


replaceStream☓SFUモード

SFUモードでreplaceStreamを利用し、受信のみモードから通常モードへの切り替えを行うのは動作対象外。つまり、以下のようなユースケースについては、現状正常に動作しない。

  1. 全員が受信のみモードでRoom参加
  2. あるユーザがreplaceStreamを利用して映像・音声の送信者になる
  3. 他の参加者は受信のみモードで視聴する
  • この場合、3のタイミングで、他の参加者に対してstreamイベントが発火しない
  • JS SDKに関しては、誰かが一人でも通常モードで参加していれば、受信のみモードから通常モードへの切替時は可能

まとめ

  • SkyWaySDKの通信モデル
  • SkyWayの通信要件
  • SkyWayを利用したWebRTC通信のコネクティビティ(メディアコネクションの場合)を確認する
  • SkyWayを利用する際の通信帯域
  • SkyWayの動作確認済みブラウザとOS
  • SkyWayを配信に利用する場合のティップス
116
102
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
116
102