東京node学園祭2013
WebRTCを始めよう
2013.10.26
インフォコム株式会社
技術企画室
がねこまさし
m.ganeko@infocom.co.jp

1
はじめに
• 本資料は以下の情報を参考に、作成しています。
– WebRTC 本家のサイト
• http://www.webrtc.org/

– HTML5 ROCKS
• http://www.html5rocks.com/en/tutor...
自己紹介: 経験した開発言語
仕事で使った言語
昔

趣味で使った言語

勉強だけした言語

C
C++

Visual C++ 1.0〜6.0
Java
PHP, JavaScript
Python, JavaScript
Objective...
What’s WebRTC

• Web Real-Time Communication の略称
– Webブラウザ上で、Real-Time Communication
を可能にするフレームワーク
– HTML5の一部

• 複数の技術の連携で...
質問タイム 1
• (1) WebRTC という言葉を聞いたことがあ
る人は?
• (2) WebRTCのサンプルに触ったことがあ
る人は?
• (3) WebRTCを使ったコードを書いたこと
がある人は?
5
WebRTCサンプルの例
• apprtc https://apprtc.appspot.com/
• Cube Slam https://www.cubeslam.com/
• 紹介記事
– http://t3n.de/news/cube-s...
なぜWebRTCに注目するのか?
通信手段の破壊的進化
キャリア型通信
固定電話
携帯電話
(TV放送)

手段の例

インフラを持つ
キャリアが支配

市場

ユーザメリット

事業者メリット

利用方法

世界中の人と会話
できる
×
単独...
利用方法のイメージ
■ユーザが組み合わせて利用 → Wordで見積書作成

合計:568,900

電卓で計算、ワードに手動で転記

■製品/サービスに組み込んで利用 → Excelで見積書作成

システムが合計を
計算、自動で結果
を反映する...
WebRTCの構成要素
• ユーザーメディア
– カメラ
– マイク
– 画面キャプチャ

• ストリーム (MediaStream)
• P2P通信 (RTCPeerConnection)
• データ通信 (DataChannel)
• 関連...
メディア関連
WebRTCの基本的な動きの説明
カメラを使ってみる

10
では、見てみましょう
• カメラいろいろ
– ローカル取得版 (Chrome用)
– http://localhost/rtc/camera.html

11
←ミラー(左右反転)

←伸縮

上下反転、回転→

白黒、セピア→
※CSSとの組み合わせ
12
自分撮りカメラ (Chrome)
<html>
<head><title>WebRTC Camera</title></head>
<body>
<video id="video1" autoplay="1"></video>
</body>
...
バリエーション
セピアカメラ
<video id="video1" autoplay="1" style="-webkit-filter: sepia(80%); "></video>
白黒カメラ
<video id="video2" auto...
ミラーカメラの2つのvideoタグの意
味
1つのMediaStreamを
複数の出力先に接続する
ことができる

MediaStream : 出力先 = 1 : n

15
WebRTCが使えるブラウザ
• Windows / Mac
– Chrome 26~(カメラ、マイクはOK、画面キャプチャは要
設定)
– FireFox 22~(カメラ、マイクはOK、画面キャプチャは
NG)
– Opera 15 ~ (カ...
WebRTCで可能な(通信)形態
• ローカルのみ
– 音声取得→スピーカーで再生
– 動画取得→動画再生
– 画面キャプチャ取得
– 音声録音
– 動画録画
– 静止画保存(Canvas使用)
17
では、見てみましょう
• 10 seconds video message

(Chrome用)

– ローカルで動画、音声、静止画を取得
– サーバにアップロード
– ストリーミング再生
– https://localhost:1235/

...
19
CAUTION!!

要注意ポイント

20
ハウリングの発生
<html>
<head><title>WebRTC Camera</title><head>
<body>
<video id="video1" autoplay="1"></video>
</body>
<script>
...
ハウリングの原理(ローカル)

22
自分でハウリングを防止

1つのUserMedai(カメラ等)か
ら、
複数のMediaStreamを
取り出すことができる

UserMedia: MediaStream = 1 : n

23
WebRTCのアクセス権限
(パーミッション)

24
通信関連
WebRTCを使って、ビデオチャットを作
成
1対1 ・1組限定
1対1・複数組
n対n・複数組
25
通信について
• RTCPeerConnection
– 動画、音声などのMediaStreamを転送する経路
– P2P (Peer to Peer) → ブラウザとブラウザ
– UDP/IP を使用

UDP/IP
RTCPeerConne...
P2P通信を始めるには
• お互い、相手のIPアドレスを知る必要がある
• 使用するポート番号を知る必要がある
– 利用するUDPのポートはダイナミックに割り振られる

• RTCPeerConnectionの通信を始める前に、何らかの手段
で...
P2P開始前のシグナリング
• どちらのブラウザからもわかる、中継役が必要
– →普通はシグナリングサーバーを立てる

• シグナリングのプロトコルは標準化されていない
– 独自の方式
• WebSocket利用(TCP/IP)
• Ajax利...
P2P開始前のシグナリング
• どちらのブラウザからもわかる、中継役が必要
– →普通はシグナリングサーバーを立てる

• シグナリングのプロトコルは標準化されていない
– 独自の方式
• WebSocket利用(TCP/IP)
• Ajax利...
シグナリングで交換される情報
• Session Description Protocol (SDP)
– セッションが含むメディアの種類(音声、映像)、メディ
アの形式(コーデック)
– IPアドレス、ポート番号
– P2Pのデータ転送プロト...
Application

P2P通信確立までの流れ(1) Application
PeerConnection

PeerConnection
socket
connect()
connect

Signaling
Server

socket...
Application

P2P通信確立までの流れ(1) Application
PeerConnection

PeerConnection
socket
connect()
connect

Signaling
Server

socket...
Application

P2P通信確立までの流れ(1) Application
PeerConnection

PeerConnection
socket
connect()
connect

Signaling
Server

socket...
Application

P2P通信確立までの流れ(2) Application
PeerConnection

PeerConnection
socket
onIceCandidate(ice)

send(ice)

send ice

S...
Application

P2P通信確立までの流れ(2) Application
PeerConnection

PeerConnection
socket
onIceCandidate(ice)
send(ice)

send ice

Si...
Application

P2P通信確立までの流れ(2) Application
PeerConnection

PeerConnection
socket
onIceCandidate(ice)
send(ice)

Signaling
Se...
WebRTCで可能な(通信)形態
• 双方向通信 1 to 1
– 1 to 1 の音声通信
– 1 to 1 の映像通信
– 1 to 1 のスクリーンキャプチャ
通信(と音声通信)

シングルテナント
このサーバで1組さま限定
39
では、見てみましょう
• WebRTC 1 to 1 Video Chat (Chrome用)
– http://localhost/rtc/rtc11.html
– ※Simple WebRTC を全面的に参考にしていま
す
• http:/...
1 to 1 signalingサーバー (node.js)
var io = require('socket.io').listen(9001);
io.sockets.on('connection', function(socket) {
...
1 to 1 ブラウザ側 (1) JavaScript
socket.io 関連
<script src="http://localhost:9001/socket.io/socket.io.js"></script>
<script>
var...
1 to 1 ブラウザ側 (2) JavaScript
connection handling
// 通信開始
function connect() {
sendOffer();
}
// 通信終了
function hangUp() {
so...
1 to 1 ブラウザ側 (3) JavaScript
SDP offer / answer
var peerConn = null; // RTCPeerConnection
function sendOffer() {
peerConn =...
1 to 1 ブラウザ側 (4) JavaScript
RTCPeerConnection
function prepareNewConnection() {
var pc_config = {"iceServers":[]};
var pee...
1 to 1 ブラウザ側 (5) JavaScript
Video handling
var localVideo = document.getElementById('local-video');
var remoteVideo = docu...
質問タイム 2
• Socket.ioとは

http://jxck.github.io/socket.io/

– Socket.IO は複数の通信メカニズムを抽象化する
• 全てのブラウザ、デバイスでリアルタイムアプリを実装可能にする
• ...
質問タイム 2 回答編
• Socket.ioのプロトコル
– https://github.com/Jxck/socket.io-spec
– Socket.io のクライアントは最初に接続に利用する通信方
法を決定します
– Socket....
WebRTCで可能な(通信)形態
• 双方向通信
– 1 to 1 の音声通信
– 1 to 1 の映像通信
– 1 to 1 のスクリーンキャプチャ
通信(と音声通信)
マルチテナント化
(複数会議室)

Socket.io の room 機...
1 to 1 multi roomブラウザ側 JavaScript
function onChannelOpened(evt) {
console.log('Channel opened.');
channelReady = true;
var...
1 to 1 multi room サーバー (node.js)
socket.on('enter', function(roomname) {
socket.set('roomname', roomname);
socket.join(roo...
CAUTION!!

はまりポイント 1

52
ICEのやり取り(理想ケース)
User A
createNewPeer

User B
send offer sdp
createNewPeer
setRemoteDescription(sdp)

send answer sdp
setRe...
ICEのやり取り(想定していたケー
ス)
User A
User B
createNewPeer

send offer sdp
createNewPeer
setRemoteDescription(sdp)

send answer sdp
...
ICEのやり取り(想定外のケース)
User A
createNewPeer

User B
send offer sdp
createNewPeer
setRemoteDescription(sdp)
send ice
addIceCandi...
WebRTCで可能な(通信)形態
• 双方向通信
– 1 to 1 の音声通信
– 1 to 1 の映像通信
– 1 to 1 のスクリーンキャプチャ通信(と
音声通信)

– n to n の音声通信
– n to n の映像通信
– n t...
では、見てみましょう
• WebRTC 4 people Video Chat (Chrome用)
– http://localhost/rtc/rtc4.html

57
CAUTION!!

はまりポイント 2

58
1対1の流れ
User A
createNewPeer

User B
send offer sdp (broadcast)

createNewPeer
setRemoteDescription(sdp)
send answer sdp (b...
n対nの流れ:SDP部分で衝突
User B

User A
createNewPeer

send offer sdp (broadcast)

send answer sdp
OK
setRemoteDescription(sdp)

Us...
n対nの流れ:Broadcastを分離
User B

User A
send “call” (broadcast)
createNewPeer

send “call” (broadcast)

send “response”
send of...
4 people ブラウザ側 (1) JavaScript
function call() {
if (! isLocalStreamStarted()) return;
socket.json.send({type: "call"});
}
...
4 people ブラウザ側 (3) JavaScript
function sendOffer(id) {
var conn = getConnection(id);
if (!conn) {
conn = prepareNewConnect...
4 people ブラウザ側 (3) JavaScript
function sendAnswer(id, evt) {
var conn = getConnection(id);
if (! conn) {
conn = prepareNew...
4 people ブラウザ側 (4) JavaScript
function prepareNewConnection(id) {
var pc_config = {"iceServers":[]};
var peer = null;
peer...
4 people ブラウザ側 (5) JavaScript
var MAX_CONNECTION_COUNT = 3;
var connections = {}; // Connection hash
function Connection()...
4 peopleサーバー (node.js)
socket.on('message', function(message) {
// set message sender
message.from = socket.id;
// send to...
WebRTCで可能な(通信)形態 (2)
• 片方向通信
– 1 → 1 の音声通信
– 1 → 1 の映像通信
– 1 → 1 のスクリーンキャプチャ通
信(と音声通信)
– 1 → n の音声通信
– 1 → n の映像通信
– 1 → n...
P2P型のメリット、デメリット
P2P型

• メリット

サーバー型

– サーバを仲介しないので、
オーバーヘッドがない
– 高スペックのサーバー不要
• 社内では、Raspberry Pi で稼働
中

• デメリット
– 通信相手が多い...
ちなみに、node.jsのビルドには一晩かかりました…
70
やっかいな問題 1

71
直接P2Pの経路(同一ネットワーク
内)

動的UDPポート(50000~65535)

72
STUNを使った、ポート情報交換
その後のP2Pの経路(NAT越え)

73
TURNサーバによるリレー中継経路
(Firewall抜け)

74
TURNサーバによるリレー中継経路
(Firewall抜け)

まだ動作せず
Firewall越え、鋭意調査中

75
質問タイム 3
• 誰か、TURNサーバーを自分で稼働させたことありますか?
– http://code.google.com/p/rfc5766-turn-server/

• そのとき、Firewall, proxy等の設定はどうすれば良い...
やっかいな問題 2

77
自分でハウリングを防止

78
相手とのハウリングの抑止?

自動ミュートや、特定音域減衰などの音声処理が必要 → JavaScriptでは不可能??
79
質問タイム 4
• JavaScript でのやり方、ライブラリ知りませんか?
– 音声波形の減算 or 位相反転+加算
– ノイズキャンセリングヘッドホンみたいなことがやりた
い

どなたか、知ってたら教えてください!!

80
まとめ
• WebRTCはパワフル
– カメラ、マイク、画面キャプチャなど、ブラウザの能力を
大きく拡大する
– HTML5の他の機能との相乗効果
• Canvas, CSS, WebAudio API, WebGL

• WebRTCはフレキ...
WebRTCをどんな風に使うかは、
みなさんのアイデア次第で
す!
今日のソースはこちら
https://github.com/mganeko/mgrtc
参考資料はこちら
http://www.slideshare.net/mganeko/2...
おまけ: socket.io 豆知識
• サーバー側で、クライアントの情報を取
得
• IPアドレス
ip = socket.handshake.headers['x-forwarded-for'] ||
socket.handshake.ad...
おまけ: インフォコムグループ紹
介
http://www.infocom.co.jp

87
Thank you!

END
88
Upcoming SlideShare
Loading in...5
×

2013 WebRTC node

10,162

Published on

WebRTCについて、node学園祭2013で発表した資料です

Published in: Technology, Design
0 Comments
20 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
10,162
On Slideshare
0
From Embeds
0
Number of Embeds
24
Actions
Shares
0
Downloads
82
Comments
0
Likes
20
Embeds 0
No embeds

No notes for slide

Transcript of "2013 WebRTC node"

  1. 1. 東京node学園祭2013 WebRTCを始めよう 2013.10.26 インフォコム株式会社 技術企画室 がねこまさし m.ganeko@infocom.co.jp 1
  2. 2. はじめに • 本資料は以下の情報を参考に、作成しています。 – WebRTC 本家のサイト • http://www.webrtc.org/ – HTML5 ROCKS • http://www.html5rocks.com/en/tutorials/webrtc/basics/ – WebRTC for Beginners Muaz Khan • https://www.webrtc-experiment.com/docs/webrtc-for-beginners.html • https://github.com/muaz-khan/WebRTC-Experiment – WebRTC Conference 2013 Atlanta • http://www.webrtcworld.com/conference/west/default.aspx • http://images.tmcnet.com/expo/webrtcconference/pdfs/WebRTC%20SG13AtlantaRe-CapSml.pdf – Socket.io 関連 • 本家 http://socket.io/ 日本語訳 http://jxck.github.io/socket.io/ – その他の多くのブログ • 本利用に含まれる製品名、商標、ロゴは、各権利者に帰属し ます。 – ®、TM 等の表記は省略します 2
  3. 3. 自己紹介: 経験した開発言語 仕事で使った言語 昔 趣味で使った言語 勉強だけした言語 C C++ Visual C++ 1.0〜6.0 Java PHP, JavaScript Python, JavaScript Objective-C Ruby 今 JavaScript, Node.js New! 3
  4. 4. What’s WebRTC • Web Real-Time Communication の略称 – Webブラウザ上で、Real-Time Communication を可能にするフレームワーク – HTML5の一部 • 複数の技術の連携で成り立っている 4
  5. 5. 質問タイム 1 • (1) WebRTC という言葉を聞いたことがあ る人は? • (2) WebRTCのサンプルに触ったことがあ る人は? • (3) WebRTCを使ったコードを書いたこと がある人は? 5
  6. 6. WebRTCサンプルの例 • apprtc https://apprtc.appspot.com/ • Cube Slam https://www.cubeslam.com/ • 紹介記事 – http://t3n.de/news/cube-slam-pong-klon-live-video-473325/ – http://japanese.engadget.com/2013/06/12/google-cube-slamwebrtc-pong/ ここ 6
  7. 7. なぜWebRTCに注目するのか? 通信手段の破壊的進化 キャリア型通信 固定電話 携帯電話 (TV放送) 手段の例 インフラを持つ キャリアが支配 市場 ユーザメリット 事業者メリット 利用方法 世界中の人と会話 できる × 単独で利用 Over The Top Skype, WebEx (YouTube, USTREAM) キャリアに縛られな い 独自の仕組みを提供 する少数のベンダー が参加可能 世界中の人と無料/ 安価で会話できる 限定的なAPI提供 連携可能 ユーザが組み合わ せて利用 Webブラウザ型 WebRTC 特別な仕組みは不要 誰でも参加可能 専用アプリ無しで 会話できる 完全にプログラマブ ル 部品として利用可能 製品/サービスに 組み込んで利用 コールセンター、ECサイト、情報共有システム、など
  8. 8. 利用方法のイメージ ■ユーザが組み合わせて利用 → Wordで見積書作成 合計:568,900 電卓で計算、ワードに手動で転記 ■製品/サービスに組み込んで利用 → Excelで見積書作成 システムが合計を 計算、自動で結果 を反映する 合計:568,900
  9. 9. WebRTCの構成要素 • ユーザーメディア – カメラ – マイク – 画面キャプチャ • ストリーム (MediaStream) • P2P通信 (RTCPeerConnection) • データ通信 (DataChannel) • 関連するAPI、HTML要素 – – – – – – JavaScript (大前提) Video, Audio WebScoket WebAudio API Canvas WebGL 9
  10. 10. メディア関連 WebRTCの基本的な動きの説明 カメラを使ってみる 10
  11. 11. では、見てみましょう • カメラいろいろ – ローカル取得版 (Chrome用) – http://localhost/rtc/camera.html 11
  12. 12. ←ミラー(左右反転) ←伸縮 上下反転、回転→ 白黒、セピア→ ※CSSとの組み合わせ 12
  13. 13. 自分撮りカメラ (Chrome) <html> <head><title>WebRTC Camera</title></head> <body> <video id="video1" autoplay="1"></video> </body> <script> var video1 = document.getElementById('video1'); navigator.webkitGetUserMedia({audio:false, video:true}, function(stream) { // success video1.src = window.webkitURL.createObjectURL(stream); }, function(err) { // error console.log(err); } ); </script> </html> 13
  14. 14. バリエーション セピアカメラ <video id="video1" autoplay="1" style="-webkit-filter: sepia(80%); "></video> 白黒カメラ <video id="video2" autoplay="1" style="-webkit-filter: grayscale(100%);"></video> 痩せカメラ <video id="video2" autoplay="1" style="-webkit-transform: scaleX(0.5);"></video> 貫禄カメラ <video id="video2" autoplay="1" style="-webkit-transform: scaleX(1.5);"></video> ミラーカメラ <video id="video1" autoplay="1" ></video> <video id="video2" autoplay="1" style="-webkit-transform: scaleX(-1);"></video> 逆さカメラ <video id="video2" autoplay="1" style="-webkit-transform: scaleY(-1);"></video> 傾奇カメラ <video id="video6" autoplay="1" style="-webkit-transform: rotate(-30deg);"></video> 14
  15. 15. ミラーカメラの2つのvideoタグの意 味 1つのMediaStreamを 複数の出力先に接続する ことができる MediaStream : 出力先 = 1 : n 15
  16. 16. WebRTCが使えるブラウザ • Windows / Mac – Chrome 26~(カメラ、マイクはOK、画面キャプチャは要 設定) – FireFox 22~(カメラ、マイクはOK、画面キャプチャは NG) – Opera 15 ~ (カメラ、マイクはOK、画面キャプチャは NG) ※JavaScriptには方言がある。要注意 Chrome: webkit~, FireFox: moz~ • Android – Chrome 29~ (カメラ、マイクはOK、画面キャプチャは NG) • iOS 16 – Google曰く、現在開発中で近々ライブラリを出す予定との
  17. 17. WebRTCで可能な(通信)形態 • ローカルのみ – 音声取得→スピーカーで再生 – 動画取得→動画再生 – 画面キャプチャ取得 – 音声録音 – 動画録画 – 静止画保存(Canvas使用) 17
  18. 18. では、見てみましょう • 10 seconds video message (Chrome用) – ローカルで動画、音声、静止画を取得 – サーバにアップロード – ストリーミング再生 – https://localhost:1235/ 18
  19. 19. 19
  20. 20. CAUTION!! 要注意ポイント 20
  21. 21. ハウリングの発生 <html> <head><title>WebRTC Camera</title><head> <body> <video id="video1" autoplay="1"></video> </body> <script> var video1 = document.getElementById('video1'); navigator.webkitGetUserMedia({audio:true, video:true}, function(stream) { // success video1.src = window.webkitURL.createObjectURL(stream); }, function(err) { // error console.log(err); } ); </script> </html> 21
  22. 22. ハウリングの原理(ローカル) 22
  23. 23. 自分でハウリングを防止 1つのUserMedai(カメラ等)か ら、 複数のMediaStreamを 取り出すことができる UserMedia: MediaStream = 1 : n 23
  24. 24. WebRTCのアクセス権限 (パーミッション) 24
  25. 25. 通信関連 WebRTCを使って、ビデオチャットを作 成 1対1 ・1組限定 1対1・複数組 n対n・複数組 25
  26. 26. 通信について • RTCPeerConnection – 動画、音声などのMediaStreamを転送する経路 – P2P (Peer to Peer) → ブラウザとブラウザ – UDP/IP を使用 UDP/IP RTCPeerConnection RTCPeerConnection 26
  27. 27. P2P通信を始めるには • お互い、相手のIPアドレスを知る必要がある • 使用するポート番号を知る必要がある – 利用するUDPのポートはダイナミックに割り振られる • RTCPeerConnectionの通信を始める前に、何らかの手段 でネゴシエーション、合意が必要 – この手順を”シグナリング:Signaling”と呼びます お互いのIPアドレス 利用するUDPポート UDP/IP RTCPeerConnection RTCPeerConnection 27
  28. 28. P2P開始前のシグナリング • どちらのブラウザからもわかる、中継役が必要 – →普通はシグナリングサーバーを立てる • シグナリングのプロトコルは標準化されていない – 独自の方式 • WebSocket利用(TCP/IP) • Ajax利用(HTTP, HTTPS) – 既存のプロトコル • SIP(VoIP用) with WebSocket(TCP/IP) • XMPP(IM用)with WebSocket(TCP/IP) 28
  29. 29. P2P開始前のシグナリング • どちらのブラウザからもわかる、中継役が必要 – →普通はシグナリングサーバーを立てる • シグナリングのプロトコルは標準化されていない – 独自の方式 • WebSocket利用(TCP/IP) • Ajax利用(HTTP, HTTPS) – 既存のプロトコル • SIP(VoIP用) with WebSocket(TCP/IP) • XMPP(IM用)with WebSocket(TCP/IP) ようやく Node.js 登場 ( + socket.io ) 29
  30. 30. シグナリングで交換される情報 • Session Description Protocol (SDP) – セッションが含むメディアの種類(音声、映像)、メディ アの形式(コーデック) – IPアドレス、ポート番号 – P2Pのデータ転送プロトコル → WebRTCでは Secure RTP – 通信で使用する帯域 – セッションの属性(名前、識別子、アクティブな時間、な ど) • Interactive Connectivity Establishment (ICE) – 通信経路の候補をリストアップするためのプロトコル • P2Pによる直接通信 • STUNによる、NAT通過のためのポートマッピング(→P2Pにな る) • TRUNによる、リレーサーバーを介した中継通信 30 – ネットワーク的に近い経路(上から順)が選ばれ
  31. 31. Application P2P通信確立までの流れ(1) Application PeerConnection PeerConnection socket connect() connect Signaling Server socket connect connect() 31
  32. 32. Application P2P通信確立までの流れ(1) Application PeerConnection PeerConnection socket connect() connect Signaling Server socket connect connect() createOffer() offer sdp setLocalDescription(sdp) send(sdp) send sdp send sdp onMessage(sdp) setRemoteDescription(sdp) 32
  33. 33. Application P2P通信確立までの流れ(1) Application PeerConnection PeerConnection socket connect() connect Signaling Server socket connect connect() createOffer() offer sdp setLocalDescription(sdp) send(sdp) send sdp send sdp onMessage(sdp) setRemoteDescription(sdp) createAnswer() answer sdp setLocalDescription(sdp) send sdp send sdp send(sdp) onMessage(sdp) setRemoteDescription(sdp) 33
  34. 34. Application P2P通信確立までの流れ(2) Application PeerConnection PeerConnection socket onIceCandidate(ice) send(ice) send ice Signaling Server socket send ice onMessage(ice) addIceCandidate(ice) 35
  35. 35. Application P2P通信確立までの流れ(2) Application PeerConnection PeerConnection socket onIceCandidate(ice) send(ice) send ice Signaling Server socket send ice onMessage(ice) addIceCandidate(ice) onIceCandidate(ice) send ice send ice send(ice) onMessage(ice) addIceCandidate(ice) 36
  36. 36. Application P2P通信確立までの流れ(2) Application PeerConnection PeerConnection socket onIceCandidate(ice) send(ice) Signaling Server send ice socket send ice onMessage(ice) addIceCandidate(ice) onIceCandidate(ice) send ice send ice send(ice) onMessage(ice) addIceCandidate(ice) onIceCandidate() : end of candidate onIceCandidate() : end of candidate P2P stream transfer 37
  37. 37. WebRTCで可能な(通信)形態 • 双方向通信 1 to 1 – 1 to 1 の音声通信 – 1 to 1 の映像通信 – 1 to 1 のスクリーンキャプチャ 通信(と音声通信) シングルテナント このサーバで1組さま限定 39
  38. 38. では、見てみましょう • WebRTC 1 to 1 Video Chat (Chrome用) – http://localhost/rtc/rtc11.html – ※Simple WebRTC を全面的に参考にしていま す • http://simplewebrtc.com/ – サーバ側は、 Node.js + socket.io を使っていま す 40
  39. 39. 1 to 1 signalingサーバー (node.js) var io = require('socket.io').listen(9001); io.sockets.on('connection', function(socket) { socket.on('message', function(message) { socket.broadcast.emit('message', message); }); signaling socket.on('disconnect', function() { socket.broadcast.emit('user disconnected'); }); }); 41
  40. 40. 1 to 1 ブラウザ側 (1) JavaScript socket.io 関連 <script src="http://localhost:9001/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://localhost:9001/'); socket.on('connect', onChannelOpened) .on('message', onMessage); function onChannelOpened(evt) { } function onMessage(evt) { Signaling if (evt.type === 'offer') { (1) sendAnswer(evt); // receive offer, send answer } else if (evt.type === 'answer') { peerConn.setRemoteDescription(new RTCSessionDescription(evt)); // receive answer } else if (evt.type === 'candidate') { var candidate = new RTCIceCandidate({sdpMLineIndex:evt.sdpMLineIndex, sdpMid:evt.sdpMid, candidate:evt.candidate}); peerConn.addIceCandidate(candidate); // set and send candidate } else if (evt.type === 'bye') { stop(); } } 42
  41. 41. 1 to 1 ブラウザ側 (2) JavaScript connection handling // 通信開始 function connect() { sendOffer(); } // 通信終了 function hangUp() { socket.json.send({type: "bye"}); stop(); } function stop() { peerConn.close(); peerConn = null; } 43
  42. 42. 1 to 1 ブラウザ側 (3) JavaScript SDP offer / answer var peerConn = null; // RTCPeerConnection function sendOffer() { peerConn = prepareNewConnection(); peerConn.createOffer(function (sessionDescription) { // in case of success peerConn.setLocalDescription(sessionDescription); socket.json.send(sessionDescription); }, function () { // in case of error console.log("Create Offer failed"); }, mediaConstraints); } function sendAnswer(evt) { peerConn = prepareNewConnection(); peerConn.setRemoteDescription(new RTCSessionDescription(evt)); peerConn.createAnswer(function (sessionDescription) { // in case of success peerConn.setLocalDescription(sessionDescription); socket.json.send(sessionDescription); }, function () { // in case of error console.log("Create Answer failed"); }, mediaConstraints); } 44
  43. 43. 1 to 1 ブラウザ側 (4) JavaScript RTCPeerConnection function prepareNewConnection() { var pc_config = {"iceServers":[]}; var peer = new webkitRTCPeerConnection(pc_config); peer.onicecandidate = function (evt) { if (evt.candidate) { socket.json.send({type: "candidate", sdpMLineIndex: evt.candidate.sdpMLineIndex, sdpMid: evt.candidate.sdpMid, candidate: evt.candidate.candidate}); } else { } }; Signaling (2) peer.addStream(localStream); peer.addEventListener("addstream", onRemoteStreamAdded, false); peer.addEventListener("removestream", onRemoteStreamRemoved, false) function onRemoteStreamAdded(event) { remoteVideo.src = window.webkitURL.createObjectURL(event.stream); // set stream to video element } function onRemoteStreamRemoved(event) { remoteVideo.src = ""; // clear stream of video element } return peer; } 45
  44. 44. 1 to 1 ブラウザ側 (5) JavaScript Video handling var localVideo = document.getElementById('local-video'); var remoteVideo = document.getElementById('remote-video'); var localStream = null; function startVideo() { navigator.webkitGetUserMedia({video: true, audio: true}, successCallback, errorCallback); function successCallback(stream) { localStream = stream; localVideo.src = window.webkitURL.createObjectURL(stream); localVideo.play(); } function errorCallback(error) { console.error('An error occurred: [CODE ' + error.code + ']'); return; } } function stopVideo() { localVideo.src = ""; localStream.stop(); } 46
  45. 45. 質問タイム 2 • Socket.ioとは http://jxck.github.io/socket.io/ – Socket.IO は複数の通信メカニズムを抽象化する • 全てのブラウザ、デバイスでリアルタイムアプリを実装可能にする • とても手軽にリアルタイムなアプリを 100% JavaScript で作成可能 – 複数のトランスポートをサポート(以下、優先順に) • 'websocket' , 'flashsocket' , 'htmlfile' , 'xhr-polling' , 'jsonp-polling‘ • ではなぜ、クライアントから接続するときに、こう書く の? – var socket = io.connect('http://localhost:9001/'); • WebScoketで接続したいなら、これでも良くね? – io.connect('localhost:9001/'); 47
  46. 46. 質問タイム 2 回答編 • Socket.ioのプロトコル – https://github.com/Jxck/socket.io-spec – Socket.io のクライアントは最初に接続に利用する通信方 法を決定します – Socket.IO の接続の最初には、シンプルな HTTP ハンド シェイクが実行されます (※または HTTPS) – ハンドシェイクが成功すると、以下の結果がクライアン トに送られます • 通信が接続を開始する時に渡される session id • ハードビートの送信が期待される間隔の秒数(heartbeat timeout) • 通信コネクションが応答しなくなり、ソケットが閉じられたと判断し て 通信コネクションを閉じるまでの秒数(close timeout) 48
  47. 47. WebRTCで可能な(通信)形態 • 双方向通信 – 1 to 1 の音声通信 – 1 to 1 の映像通信 – 1 to 1 のスクリーンキャプチャ 通信(と音声通信) マルチテナント化 (複数会議室) Socket.io の room 機能 (join() / leave()) を利用 49
  48. 48. 1 to 1 multi roomブラウザ側 JavaScript function onChannelOpened(evt) { console.log('Channel opened.'); channelReady = true; var roomname = getRoomName(); socket.emit('enter', roomname); } function getRoomName() { // たとえば、 URLに ?roomname とする var url = document.location.href; var args = url.split('?'); if (args.length > 1) { var room = args[1]; if (room != "") { return room; } } return "_defaultroom"; } 50
  49. 49. 1 to 1 multi room サーバー (node.js) socket.on('enter', function(roomname) { socket.set('roomname', roomname); socket.join(roomname); }); function emitMessage(type, message) { var roomname; socket.get('roomname', function(err, _room) { roomname = _room; }); if (roomname) { socket.broadcast.to(roomname).emit(type, message); } else { socket.broadcast.emit(type, message); } } socket.on('message', function(message) { emitMessage('message', message); }); socket.on('disconnect', function() { emitMessage('user disconnected'); }); 51
  50. 50. CAUTION!! はまりポイント 1 52
  51. 51. ICEのやり取り(理想ケース) User A createNewPeer User B send offer sdp createNewPeer setRemoteDescription(sdp) send answer sdp setRemoteDescription(sdp) send ice addIceCandidate(ice) send ice addIceCandidate(ice) Iceを 交互に送信 send ice send ice addIceCandidate(ice) addIceCandidate(ice) end of candidate end of candidate P2P stream transfer 53
  52. 52. ICEのやり取り(想定していたケー ス) User A User B createNewPeer send offer sdp createNewPeer setRemoteDescription(sdp) send answer sdp setRemoteDescription(sdp) send ice send ice end of candidate addIceCandidate(ice) addIceCandidate(ice) addIceCandidate(ice) send ice Iceを片方が 連続して送信 send ice addIceCandidate(ice) end of candidate P2P stream transfer 54
  53. 53. ICEのやり取り(想定外のケース) User A createNewPeer User B send offer sdp createNewPeer setRemoteDescription(sdp) send ice addIceCandidate(ice) send ice end of candidate addIceCandidate(ice) send answer sdp ※エラーとして 弾いていたら 嵌った… setRemoteDescription(sdp) send ice addIceCandidate(ice) Answer SDP を生成前に、 Ice を受け取る ことも可能 約1ヶ月 send ice addIceCandidate(ice) end of candidate P2P stream transfer 55
  54. 54. WebRTCで可能な(通信)形態 • 双方向通信 – 1 to 1 の音声通信 – 1 to 1 の映像通信 – 1 to 1 のスクリーンキャプチャ通信(と 音声通信) – n to n の音声通信 – n to n の映像通信 – n to n のスクリーンキャプチャ 通信(と音声通信) 1会議室に複数人、 かつ複数会議室 56
  55. 55. では、見てみましょう • WebRTC 4 people Video Chat (Chrome用) – http://localhost/rtc/rtc4.html 57
  56. 56. CAUTION!! はまりポイント 2 58
  57. 57. 1対1の流れ User A createNewPeer User B send offer sdp (broadcast) createNewPeer setRemoteDescription(sdp) send answer sdp (broadcast) setRemoteDescription(sdp) send ice send ice addIceCandidate(ice) addIceCandidate(ice) send ice send ice addIceCandidate(ice) addIceCandidate(ice) end of candidate end of candidate P2P stream transfer 59
  58. 58. n対nの流れ:SDP部分で衝突 User B User A createNewPeer send offer sdp (broadcast) send answer sdp OK setRemoteDescription(sdp) User C send offer sdp (broadcast) createNewPeer setRemoteDescription(sdp) OK createNewPeer setRemoteDescription(sdp) OK send answer sdp no peer! → createNewPeer setRemoteDescription(sdp) send offer sdp ※この流れを理解するのに、苦労 約2ヶ月 corrupt! 60
  59. 59. n対nの流れ:Broadcastを分離 User B User A send “call” (broadcast) createNewPeer send “call” (broadcast) send “response” send offer sdp send answer sdp setRemoteDescription(sdp) OK createNewPeer setRemoteDescription(sdp) OK send “response” createNewPeer User C setRemoteDescription(sdp) send offer sdp createNewPeer send answer sdp setRemoteDescription(sdp) OK setRemoteDescription(sdp) OK 61
  60. 60. 4 people ブラウザ側 (1) JavaScript function call() { if (! isLocalStreamStarted()) return; socket.json.send({type: "call"}); } function onMessage(evt) { var id = evt.from; var target = evt.sendto; var conn = getConnection(id); if (evt.type === 'call') { if (! isLocalStreamStarted()) return; if (conn) return; // already connected if (isConnectPossible()) { socket.json.send({type: "response", sendto: id }); } else { console.warn('max connections. so ignore call'); } } else if (evt.type === 'response') { sendOffer(id); return; } } 62
  61. 61. 4 people ブラウザ側 (3) JavaScript function sendOffer(id) { var conn = getConnection(id); if (!conn) { conn = prepareNewConnection(id); } conn.peerconnection.createOffer(function (sessionDescription) { // in case of success conn.iceReady = true; conn.peerconnection.setLocalDescription(sessionDescription); sessionDescription.sendto = conn.id; socket.json.send(sessionDescription); }, function () { // in case of error console.log("Create Offer failed"); }, mediaConstraints); conn.iceReady = true; } 63
  62. 62. 4 people ブラウザ側 (3) JavaScript function sendAnswer(id, evt) { var conn = getConnection(id); if (! conn) { conn = prepareNewConnection(id); } conn.peerconnection.setRemoteDescription(new RTCSessionDescription(evt)); conn.peerconnection.createAnswer(function (sessionDescription) { // in case of success conn.iceReady = true; conn.peerconnection.setLocalDescription(sessionDescription); sessionDescription.sendto = id; socket.json.send(sessionDescription); }, function () { // in case of error console.log("Create Answer failed"); }, mediaConstraints); conn.iceReady = true; } 64
  63. 63. 4 people ブラウザ側 (4) JavaScript function prepareNewConnection(id) { var pc_config = {"iceServers":[]}; var peer = null; peer = new webkitRTCPeerConnection(pc_config); var conn = new Connection(); conn.id = id; conn.peerconnection = peer; peer.id = id; addConnection(id, conn); // send any ice candidates to the other peer peer.onicecandidate = function (evt) { if (evt.candidate) { socket.json.send({type: "candidate", sendto: conn.id, sdpMLineIndex: evt.candidate.sdpMLineIndex, sdpMid: evt.candidate.sdpMid, candidate: evt.candidate.candidate}); } else { conn.established = true; // end of candidates } }; … 65
  64. 64. 4 people ブラウザ側 (5) JavaScript var MAX_CONNECTION_COUNT = 3; var connections = {}; // Connection hash function Connection() { // Connection Class var self = this; var id = ""; // socket.id of partner var peerconnection = null; // RTCPeerConnection instance var established = false; // is Already Established var iceReady = false; } function getConnection(id) { var con = null; con = connections[id]; return con; } function addConnection(id, connection) { connections[id] = connection; } getConnectionCount(), isConnectPossible(), deleteConnection(id), …, etc. 66
  65. 65. 4 peopleサーバー (node.js) socket.on('message', function(message) { // set message sender message.from = socket.id; // send to specific target var target = message.sendto; if (target) { io.sockets.socket(target).emit('message', message); return; } // broadcast in room emitMessage('message', message); }); 67
  66. 66. WebRTCで可能な(通信)形態 (2) • 片方向通信 – 1 → 1 の音声通信 – 1 → 1 の映像通信 – 1 → 1 のスクリーンキャプチャ通 信(と音声通信) – 1 → n の音声通信 – 1 → n の映像通信 – 1 → n のスクリーンキャプチャ通 信(と音声通信) 68
  67. 67. P2P型のメリット、デメリット P2P型 • メリット サーバー型 – サーバを仲介しないので、 オーバーヘッドがない – 高スペックのサーバー不要 • 社内では、Raspberry Pi で稼働 中 • デメリット – 通信相手が多いと組み合わ せ爆発で通信経路が増える • • • • • 2人 3人 4人 5人 6人 P2P型4人 サーバー型4人 → 1経路 → 3経路 → 6経路 → 10経路 → 15経路 69
  68. 68. ちなみに、node.jsのビルドには一晩かかりました… 70
  69. 69. やっかいな問題 1 71
  70. 70. 直接P2Pの経路(同一ネットワーク 内) 動的UDPポート(50000~65535) 72
  71. 71. STUNを使った、ポート情報交換 その後のP2Pの経路(NAT越え) 73
  72. 72. TURNサーバによるリレー中継経路 (Firewall抜け) 74
  73. 73. TURNサーバによるリレー中継経路 (Firewall抜け) まだ動作せず Firewall越え、鋭意調査中 75
  74. 74. 質問タイム 3 • 誰か、TURNサーバーを自分で稼働させたことありますか? – http://code.google.com/p/rfc5766-turn-server/ • そのとき、Firewall, proxy等の設定はどうすれば良いの? どなたか、知ってたら教えてください!! 76
  75. 75. やっかいな問題 2 77
  76. 76. 自分でハウリングを防止 78
  77. 77. 相手とのハウリングの抑止? 自動ミュートや、特定音域減衰などの音声処理が必要 → JavaScriptでは不可能?? 79
  78. 78. 質問タイム 4 • JavaScript でのやり方、ライブラリ知りませんか? – 音声波形の減算 or 位相反転+加算 – ノイズキャンセリングヘッドホンみたいなことがやりた い どなたか、知ってたら教えてください!! 80
  79. 79. まとめ • WebRTCはパワフル – カメラ、マイク、画面キャプチャなど、ブラウザの能力を 大きく拡大する – HTML5の他の機能との相乗効果 • Canvas, CSS, WebAudio API, WebGL • WebRTCはフレキシブル – ローカルのみ、1対1、n対n – 双方向、片方向(ブロードキャスト型) • WebRTCは破壊的技術 – だれでも市場/アプリに参入できる • WebRTCはプログラマブル – 自分たちの製品/サービスに組み込める 84
  80. 80. WebRTCをどんな風に使うかは、 みなさんのアイデア次第で す! 今日のソースはこちら https://github.com/mganeko/mgrtc 参考資料はこちら http://www.slideshare.net/mganeko/2013-web-rtctechcross 質問、情報、アイデアは → m.ganeko@infocom.co.jp 85
  81. 81. おまけ: socket.io 豆知識 • サーバー側で、クライアントの情報を取 得 • IPアドレス ip = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address.address; • トランスポート (websocket, ajax …) tr = io.transports[socket.id].name; 86
  82. 82. おまけ: インフォコムグループ紹 介 http://www.infocom.co.jp 87
  83. 83. Thank you! END 88
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×