Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Webrtc bootcamp handson

1,030 views

Published on

WebRTC Conference Japan 2016の WebRTC Boot Camp ハンズオン資料です

Published in: Technology
  • Be the first to comment

Webrtc bootcamp handson

  1. 1. WebRTC Conference Japan 2016 WebRTC Boot Camp ハンズオン インフォコム株式会社 がねこまさし
  2. 2. リソース • スライドのURL – http://www.slideshare.net/mganeko/webrtc- bootcamp-handson – 短縮 http://goo.gl/cA9CV5 • 元になるソースコード – https://github.com/mganeko/bootcamp – 短縮 https://goo.gl/HfXTmT • 参考 – WebRTCを試すために必要なもの (Qiita) • http://goo.gl/hSfYc9 – お手軽なWebサーバーの立て方 (Qiita) • http://goo.gl/0C18j5
  3. 3. PART 1 カメラを使ってみよう
  4. 4. navigator.getUserMedia() • カメラの映像/マイクの音声を取得できます • ベンダーブレフィックスが付いています – Chrome: navigator.webkitGetUserMedia() – Firefox: navigator.mozGetUserMedia() • 最新の仕様では、navigator.MediaDevices.getUserMedia() – ※今日は使いません • ユーザに許可を求めるダイアログが表示されます • 取得に成功するとMediaStream オブジェクトが得られます • ※Chrome 47からは https://〜でしか利用できなくなりました – http://localhost は例外として利用できます
  5. 5. コード例 // プレフィックスを吸収する navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // カメラの映像を取得する場合 navigator.getUserMedia( {video : true}, function(stream) { // 成功時のコールバック }, function(err) { // エラー時のコールバック } );
  6. 6. マイクの音声も取得する場合 // カメラの映像とマイクの音声を取得する場合 navigator.getUserMedia( {video : true, audio: true}, function(stream) { // 成功時のコールバック }, function(err) { // エラー時のコールバック } ); ※会場でやるとうるさいので、今日は音声無しでお願いします
  7. 7. 映像をvideo要素で再生 • window.URL.createObjectURL(stream) でURL を取得 – blob://〜 という表記のURLを返す • video要素のsrc に指定して再生 video.src = window.URL.createObjectURL(stream); video.play();
  8. 8. 実際にやってみよう(1)(2) • media_0.html をエディタで開いてください • startCamera() 関数の (1), (2) を記述してみて ください • [start]ボタンを押して、試してみましょう
  9. 9. 解答例 function startCamera() { // (1) getUserMediaを使って、cameraからメディアストリームを取得してください // また、それをlocalStreamにセットしておいてください navigator.getUserMedia( {video : true}, function(stream) { // success localStream = stream; // (2) それを localVideo に表示してください localVideo.src = window.URL.createObjectURL(localStream); localVideo.play(); }, function(err) { // error console.error('getUserMedia error', err); } ); }
  10. 10. 映像の停止 • video.pause() • window.URL.revokeObjectURL(url) でURLを解放 • ストリームを停止 – MediaStream.stop() はChrome 47から使えなくなりました – MediaTrack.stop() を使う必要があります MediaStream MediaTrack MediaTrack
  11. 11. 実際にやってみよう(3)(4) • 先ほどの続きで、stopCamera() 関数の (3), (4) を記述してみてくだい – MediaStreamを停止させるための関数を stopStream(stream) として用意していますので、 ご利用ください • [start]→[stop]ボタンを押して、試してみましょ う
  12. 12. 解答例 function stopCamera() { // (3) localVideoの再生を停止させてください localVideo.pause(); window.URL.revokeObjectURL(localVideo.src); localVideo.src = ''; // Firefox ではWARNING // (4) メディアストリームを停止させてください stopStream(localStream); localStream = null; }
  13. 13. 参考:新しい getUserMedia • Media Capture and Streamsでは、新しいAPIが定義され ています – http://www.w3.org/TR/mediacapture-streams/ • navigator.MediaDevices.getUserMedia() • Promiseを返します navigator.mediaDevices.getUserMedia( {video: true} ).then(function (stream) { // 成功時の処理 }).catch(function (reason) { // 例外時の処理 });
  14. 14. PART 2 通信してみよう
  15. 15. RTCPeerConnection • WebRTC通信には、RTCPeerConnetionを使用 – ブラウザとブラウザの間で直接Peer-to-Peer通信を行う – UDP/IPを使用 • TCP/IPのようにパケットの到着は保障しない • オーバーヘッドが少ない • 通信のリアルタイム性を重視 • UDPのポート番号は動的に割り振られる(49152 ~ 65535) • ベンダーブレフィックスが付いている – Chrome: window.webkitRTCPeerConnetion – Firefox: window.mozRTCPeerConnection
  16. 16. RTCPeerConnection • Peer-to-Peer 通信を確立するために、2種類の情報を 交換する – SDP (Session Description Protocol) – ICE Candidate (Interactive Connectivity Establishment Candidate) • SDP ... 通信するPeerの能力や、条件について – 映像、音声、データーの有無 – 使いたいコーデック、使いたい帯域幅、など – 通信を始める側: Offer – 通信に応答する側: Answer • ICE Candidate – 通信に使う経路の情報
  17. 17. SDP と ICE • ICE Candidate…経路の情報を示す。複数ある場合も多い • P2Pによる直接通信 • STUNによる、NAT通過のためのポートマッピング – → 最終的にはP2Pになる • TURNによる、リレーサーバーを介した中継通信 SDP SDPICE
  18. 18. ご注意 • ICE Candidate を収集するには、デバイスが ネットワークに繋がっている必要があります – ネットワーク無し、localhostのみだとICE candidate が収集できない • ハンズオンは、テザリング等でデバイスをネッ トワークに接続してから、実行してください – 外部と実際には通信しませんが、外部と接続でき るネットワークが必要です
  19. 19. シグナリング • 最初は通信相手のことをお互い知らない • 情報をなんらかの方法で交換する必要あり – → シグナリング • 通常は仲介役となるサーバーを用意 – → シグナリングサーバー • 今日は、仲介役は「あなた」 – → 手動でシグナリング
  20. 20. デモ
  21. 21. SDPの交換の概略: Offer側 • Offer SDP を生成 – RTCPeerConnection.createOffer() • 自分のSDPを覚える – RTCPeerConnection.setLocalDescription() • 相手に送る • 相手から Answer SDP を受け取ったら、それを覚える – RTCPeerConnection.setRemoteDescription() ※非同期処理になるので、コールバックを使って記述
  22. 22. SDPの交換の概略: Answer側 • 相手から Offer SDP を受け取ったら、それを覚える – RTCPeerConnection.setRemoteDescription() • Answer SDP を生成 – RTCPeerConnection.createAnswer() • 自分のSDPを覚える – RTCPeerConnection.setLocalDescription() • 相手に送り返す ※非同期処理になるので、コールバックを使って記述
  23. 23. コードの概略 // プレフィックスを吸収する RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection; // PeerConnectionオブジェクトを生成する var peerConnection = new RTCPeerConnection({"iceServers":[]}); // iceServersは NAT/Firewall越えを行う場合に指定 // 今回は指定は空っぽでOK // Offer SDPを生成する peerConnection.createOffer( function(sessionDescription) { // 成功した場合 }, function(err) { // 失敗した場合 }, {} // オプション指定 );
  24. 24. コードの概略(続き) // Answer SDPを生成する peerConnection.createAnswer( function(sessionDescription) { // 成功した場合 }, function(err) { // 失敗した場合 }, {} // オプション指定 ); // SDP を受け取った場合 peerConnection.setRemoteDescription(sessionDescription, function() { // 成功 }, function(err) { // 失敗 } );
  25. 25. ICE Candidateの交換の概略 • ICE Candidate (通信経路の候補)は複数個ある • 非同期に順々に収集される – RTCPeerConnection.onicecandidate() • 早く見つかったものから随時交換… Trcikle ICE – 早く繋がるケースが多い • 全て見つけてから、まとめて交換… Vanilla ICE – 処理はシンプル。※今日はこちらを利用
  26. 26. Trickle ICE によるシグナリング
  27. 27. Vanilla ICE によるシグナリング
  28. 28. コードの概略 peerConection.onicecandidate = function (evt) { if (evt.candidate) { // 個々のcandidateを収集をした時の処理 // Trikle ICE の場合、ここで処理する } else { // 全てのICE candidateが収集し終わったタイミング // Vanilla ICE の場合、ここで処理する var sdpWithICE = peerConnection.localDescription.sdp; } };
  29. 29. 手動シグナリングをやってみよう (1)〜(7) • hand_vanilla_0.html をエディタで開いてください • makeOffer()関数の(1),(2)を記述してみてください • setOfferText()関数の(3),(4)を記述してみてください • makeAnswer()関数の(5),(6)を記述してみてください • setAnswerText()関数の(7)を記述してみてください
  30. 30. 解答例 function makeOffer() { // (1) createOfferを呼び出して、Offer SDPを生成する peerConnection.createOffer(function (sessionDescription) { // in case of success // (2) 生成されたSDPを、peerConnetionにセットする // ※Vanilla ICEを用いるため、すぐにはOfferを相手に送信しない peerConnection.setLocalDescription(sessionDescription, function() { console.log('setLocalDescription() succsess'); // ※Trickle ICEの場合は、このタイミングでOffer SDPを相手に送信する // ※Vanilla ICEの場合には、まだ送らない }, function(err) { console.error('setLocalDescription() ERROR: ', err); } ); console.log('-- Create Offer SDP --'); console.log(sessionDescription); }, function (err) { // in case of error console.error('Create Offer failed:', err); }, mediaConstraints); }
  31. 31. 解答例 // Offerを受け取る function setOfferText(text) { // SDPの文字列からRTCSessionDescriptionのオブジェクトを生成 var offer = new RTCSessionDescription({ type : 'offer', sdp : text, }); // (3) 生成したオブジェクトを、peerConnetionにセットする // 相手側のSDPをセットする peerConnection.setRemoteDescription(offer, function() { console.log('setRemoteDescription(offer) succsess'); // (4) さらに、適切なタイミングで用意している関数 makeAnswer() を呼び出す // コールバックが呼ばれたら、Answerを生成する makeAnswer(); }, function(err) { console.error('setRemoteDescription(offer) ERROR: ', err); } ); }
  32. 32. 解答例 // Answer を生成する function makeAnswer() { // (5) createAnswerを呼び出して、Answer SDPを生成する peerConnection.createAnswer(function (sessionDescription) { // in case of success // (6) 生成されたSDPを、peerConnetionにセットする // ※Vanilla ICEを用いるため、すぐにはOfferを相手に送信しない peerConnection.setLocalDescription(sessionDescription, function() { console.log('setLocalDescription() succsess'); // ※Trickle ICEの場合は、このタイミングでAnswer SDPを相手に送信する // ※Vanilla ICEの場合には、まだ送らない }, function(err) { console.error('setLocalDescription() ERROR: ', err); } ); console.log(sessionDescription); }, function (err) { // in case of error console.error('Create Answer failed:', err); }, mediaConstraints); }
  33. 33. 解答例 // Answerを受け取る function setAnswerText(text) { // SDPの文字列からRTCSessionDescriptionのオブジェクトを生成 var answer = new RTCSessionDescription({ type : 'answer', sdp : text, }); // (7) 生成したオブジェクトを、peerConnetionにセットする // 相手側のSDPをセットする peerConnection.setRemoteDescription(answer, function() { console.log('setRemoteDescription(answer) succsess'); }, function(err) { console.error('setRemoteDescription(answer) ERROR: ', err); } ); }
  34. 34. Thank you! 34 END

×