mediasoupのインストールと基本的な実装
mediasoupとは
- nodejsのSFUサーバのライブラリ。ライブラリなので基本的にメディア(映像、音声)の受信、配信のみを行います。
- クライアントはwebRTCを想定しています。
SFUとは
SFU(Selective Forwarding Unit)とは配信者に代わり映像、音声を視聴者に配信する仕組み。配信の代行的なことを行うサーバですかね。
とりあえず環境情報ともろもろ
OS
debian 8.8node
version 6.10npm
3.10.0
調査期間 : 2017/5/20 〜 2017/6/2 調査期間中にいろいろ仕様とか変わっているかもしれませんので、、ご了承下さい。
mediasoupのインストール
npmにてインストールすることができるが、mediasoupの実装がC++なのでコンパイルできる環境を用意
apt-get install gcc g++ make build-essential
※ pythonも必要だか、バージョンが2.x系じゃないといけないみたいです。なので2.x系のやつが使える環境にしておきます。
package.json
... "dependencies": { .... "mediasoup": "1.2.0" } ....
npm でインストール
npm install
mediasoupの実装
大体の流れとして下記のリスト。
- roomの作成
- roomからPeerの取得
- PeerからPeerConnectionの作成
—- シグナリング処理 —-
4. SDPのOfferを作成し、localDescriptionにセット、クライアントにSDPを送信
5. クライアントからAnswerが返ってきてremoteDescriptionにセット
0. mediasoupの準備
const mediasoup = require("mediasoup");
クライアントと接続するときに使用するクラスの読み込み
const RTCPeerConnection = mediasoup.webrtc.RTCPeerConnection; const RTCSessionDescription = mediasoup.webrtc.RTCSessionDescription;
mediasoupのサーバ設定
const mediaServer = mediasoup.Server({ ... });
※ 設定内容参照 : https://mediasoup.org/api/#Server-dictionaries
1. roomの作成
クライアントが接続するroomを作成。そのroomにいるユーザが配信した場合は同一のroomに接続している全ユーザに配信されます。 room作成
const roomOptions = { mediaCodecs: [ { kind: 'audio', name: 'audio/opus', clockRate: 48000, payloadType: 111 }, { kind: 'video', name: 'video/vp8', clockRate: 90000, payloadType: 100 } ] }; mediaServer.createRoom(roomOptions) .then(function(room) { // 引数のroomが作成したroomになる });
※ roomOptionsは作成するroomのオプション、コーデックとかを設定
参照:
https://mediasoup.org/api/#RtpDictionaries-RtpCodecParameters
https://mediasoup.org/api/#server-createRoom
2. roomからPeerの作成
クライアントとメディアストリームの配信、受信を行います。
Peerの作成
peer = room.Peer("peerName");
peerName: room内のPeerの名前になります。ひとつのroom内に同じ名前のPeerを作成することはできないため、注意が必要(別のroomならOK)。
3. PeerからPeerConnectionの作成
Peerからコネクションを作成します。webRTCのPeerConnectionみたいな感じです。
だけどちょっと違うようです。
コネクションの作成
peerConnection = new RTCPeerConnection({ peer: peer });
引数の設定はここを参照: https://mediasoup.org/api/#webrtc-RTCPeerConnection-dictionaries
usePlanBはSDPの規格になるため、これでシグナリングが成功しないときもあるかも、
chromeとfirefoxで違いがあるため要注意(2017/5/30 現在)
—- シグナリング処理 —-
シグナリングの方法はwebRTCでは決まっていない。そのため、どんな実装でもいいのだが、今回はwebSocketにて行います。
実装も簡単、一番楽ですし、情報も多い。
4. SDPのOfferを作成し、localDescriptionにセット、クライアントにSDPを送信
webRTCのシグナリングで使用するSDPの作成を行う。mediasoupからofferを送らないとシグナリングができないようです。
なので、クライアントがofferを送ってきて、setRemoteDescriptionでセットするとエラーになってしまいました…
offerの作成
peerConnection.createOffer({ offerToReceiveAudio: 1, offerToReceiveVideo: 1 }) .then(function(desc) { // 作成したSDPをローカルの情報として保存 peerConnection.setCapabilities(desc); return peerConnection.setLocalDescription(desc); }) .then(function() { // webSocket経由でクライアントにSDPの情報を送信 const message = JSON.stringify(peerConnection.localDescription.serialize()); return ws.send(message); })
5. クライアントからAnswerが返ってきてremoteDescriptionにセット
offerをクライアントに送信し、無事にanswerが返ってきたらその情報をリモートの情報としてConnectionにセットする
remote = new RTCSessionDescription(description); peerConnection.setRemoteDescription(remote);
これで無事にmediasoupとクライアントでコネクションが確立できて、通信ができるようになります(なるはず)。