WebRTC-RTCPeerConnection API
RTCPeerConnection APIは、各ブラウザー間のピアツーピア接続の中核です。RTCPeerConnectionオブジェクトを作成するには、次のように記述します。
var pc = RTCPeerConnection(config);
ここで、config引数には、少なくともキーであるiceServersが含まれています。これは、ICE候補の検索中に使用されるSTUNおよびTURNサーバーに関する情報を含むURLオブジェクトの配列です。code.google.comで利用可能なパブリックSTUNサーバーのリストを見つけることができます
発信者であるか着信者であるかに応じて、RTCPeerConnectionオブジェクトは、接続の両側でわずかに異なる方法で使用されます。
これがユーザーのフローの例です-
onicecandidateハンドラーを登録します。ICE候補は、受信されると、他のピアに送信されます。
onaddstreamハンドラーを登録します。リモートピアから受信したビデオストリームの表示を処理します。
メッセージハンドラを登録します。シグナリングサーバーには、他のピアから受信したメッセージのハンドラーも必要です。メッセージにRTCSessionDescriptionオブジェクトが含まれている場合は、setRemoteDescription()メソッドを使用してRTCPeerConnectionオブジェクトに追加する必要があります。メッセージにRTCIceCandidateオブジェクトが含まれている場合は、addIceCandidate()メソッドを使用してRTCPeerConnectionオブジェクトに追加する必要があります。
getUserMedia()を利用してローカルメディアストリームを設定し、addStream()メソッドを使用してRTCPeerConnectionオブジェクトに追加します。
オファー/アンサー交渉プロセスを開始します。これは、呼び出し元のフローが呼び出し先のフローと異なる唯一のステップです。呼び出し元は、createOffer()メソッドを使用してネゴシエーションを開始し、RTCSessionDescriptionオブジェクトを受信するコールバックを登録します。そして、このコールバックは、この追加する必要がありRTCSessionDescriptionのあなたにオブジェクトをRTCPeerConnectionの使用してオブジェクトsetLocalDescriptionを() 。そして最後に、呼び出し元は、シグナリングサーバーを使用してこのRTCSessionDescriptionをリモートピアに送信する必要があります。一方、呼び出し先は同じコールバックを登録しますが、createAnswer()メソッドに登録します。呼び出し先フローは、呼び出し元からオファーを受け取った後にのみ開始されることに注意してください。
RTCPeerConnection API
プロパティ
RTCPeerConnection.iceConnectionState (read only)−接続の状態を説明するRTCIceConnectionState列挙型を返します。この値が変更されると、iceconnectionstatechangeイベントが発生します。可能な値-
new −ICEエージェントはリモート候補者を待っているかアドレスを収集しています
checking − ICEエージェントにはリモート候補がありますが、まだ接続が見つかりません
connected − ICEエージェントは使用可能な接続を検出しましたが、より良い接続のためにより多くのリモート候補をチェックしています。
completed − ICEエージェントは使用可能な接続を検出し、リモート候補のテストを停止しました。
failed − ICEエージェントはすべてのリモート候補をチェックしましたが、少なくとも1つのコンポーネントに一致するものが見つかりませんでした。
disconnected −少なくとも1つのコンポーネントが生きていません。
closed −ICEエージェントは閉じられています。
RTCPeerConnection.iceGatheringState (read only) −接続のICE収集状態を説明するRTCIceGatheringState列挙型を返します−
new −オブジェクトが作成されたばかりです。
gathering −ICEエージェントは候補者を集める過程にあります
complete ICEエージェントは収集を完了しました。
RTCPeerConnection.localDescription (read only)−ローカルセッションを説明するRTCSessionDescriptionを返します。まだ設定されていない場合はnullになる可能性があります。
RTCPeerConnection.peerIdentity (read only)−RTCIdentityAssertionを返します。これは、idp(ドメイン名)とリモートピアのIDを表す名前で構成されます。
RTCPeerConnection.remoteDescription (read only)−リモートセッションを説明するRTCSessionDescriptionを返します。まだ設定されていない場合はnullになる可能性があります。
RTCPeerConnection.signalingState (read only)−ローカル接続のシグナリング状態を説明するRTCSignalingState列挙型を返します。この状態は、SDPオファーを表します。この値が変更されると、signalingstatechangeイベントが発生します。可能な値-
stable−初期状態。進行中のSDPオファー/アンサー交換はありません。
have-local-offer −接続のローカル側がSDPオファーをローカルに適用しました。
have-remote-offer −接続のリモート側がローカルでSDPオファーを適用しました。
have-local-pranswer −リモートSDPオファーが適用され、SDPpranswerがローカルに適用されました。
have-remote-pranswer −ローカルSDPが適用され、SDPpranswerがリモートで適用されました。
closed −接続が閉じられます。
イベントハンドラー
S.No. | イベントハンドラーと説明 |
---|---|
1 | RTCPeerConnection.onaddstream このハンドラーは、addstreamイベントが発生したときに呼び出されます。このイベントは、MediaStreamがリモートピアによってこの接続に追加されたときに送信されます。 |
2 | RTCPeerConnection.ondatachannel このハンドラーは、データチャネルイベントが発生したときに呼び出されます。このイベントは、RTCDataChannelがこの接続に追加されたときに送信されます。 |
3 | RTCPeerConnection.onicecandidate このハンドラーは、icecandidateイベントが発生したときに呼び出されます。このイベントは、RTCIceCandidateオブジェクトがスクリプトに追加されたときに送信されます。 |
4 | RTCPeerConnection.oniceconnectionstatechange このハンドラーは、iceconnectionstatechangeイベントが発生したときに呼び出されます。このイベントは、iceConnectionStateの値が変更されたときに送信されます。 |
5 | RTCPeerConnection.onidentityresult このハンドラーは、identityresultイベントが発生したときに呼び出されます。このイベントは、getIdentityAssertion()を介したオファーまたはアンサーの作成中にIDアサーションが生成されたときに送信されます。 |
6 | RTCPeerConnection.onidpassertionerror このハンドラーは、idpassertionerrorイベントが発生したときに呼び出されます。このイベントは、IDアサーションの生成中にIdP(Identitry Provider)がエラーを検出したときに送信されます。 |
7 | RTCPeerConnection.onidpvalidation このハンドラーは、idpvalidationerrorイベントが発生したときに呼び出されます。このイベントは、IDアサーションの検証中にIdP(Identitry Provider)がエラーを検出したときに送信されます。 |
8 | RTCPeerConnection.onnegotiationneeded このハンドラーは、交渉が必要なイベントが発生したときに呼び出されます。このイベントはブラウザによって送信され、将来のある時点でネゴシエーションが必要になることを通知します。 |
9 | RTCPeerConnection.onpeeridentity このハンドラーは、peeridentityイベントが発生したときに呼び出されます。このイベントは、この接続でピアIDが設定および検証されたときに送信されます。 |
10 | RTCPeerConnection.onremovestream このハンドラーは、signalingstatechangeイベントが発生したときに呼び出されます。このイベントは、signallingStateの値が変更されたときに送信されます。 |
11 | RTCPeerConnection.onsignalingstatechange このハンドラーは、removestreamイベントが発生したときに呼び出されます。このイベントは、MediaStreamがこの接続から削除されたときに送信されます。 |
メソッド
S.No. | 方法と説明 |
---|---|
1 | RTCPeerConnection() 新しいRTCPeerConnectionオブジェクトを返します。 |
2 | RTCPeerConnection.createOffer() リモートピアを見つけるためのオファー(リクエスト)を作成します。このメソッドの最初の2つのパラメーターは、成功とエラーのコールバックです。オプションの3番目のパラメーターは、オーディオまたはビデオストリームの有効化などのオプションです。 |
3 | RTCPeerConnection.createAnswer() オファー/アンサーネゴシエーションプロセス中にリモートピアが受信したオファーに対するアンサーを作成します。このメソッドの最初の2つのパラメーターは、成功とエラーのコールバックです。オプションの3番目のパラメーターは、作成する回答のオプションです。 |
4 | RTCPeerConnection.setLocalDescription() ローカル接続の説明を変更します。説明は、接続のプロパティを定義します。接続は、古い説明と新しい説明の両方をサポートできる必要があります。このメソッドは、RTCSessionDescriptionオブジェクト、説明の変更が成功した場合のコールバック、説明の変更が失敗した場合のコールバックの3つのパラメーターを取ります。 |
5 | RTCPeerConnection.setRemoteDescription() リモート接続の説明を変更します。説明は、接続のプロパティを定義します。接続は、古い説明と新しい説明の両方をサポートできる必要があります。このメソッドは、RTCSessionDescriptionオブジェクト、説明の変更が成功した場合のコールバック、説明の変更が失敗した場合のコールバックの3つのパラメーターを取ります。 |
6 | RTCPeerConnection.updateIce() リモート候補にpingを実行し、ローカル候補を収集するICEエージェントプロセスを更新します。 |
7 | RTCPeerConnection.addIceCandidate() リモート候補をICEエージェントに提供します。 |
8 | RTCPeerConnection.getConfiguration() RTCConfigurationオブジェクトを返します。これは、RTCPeerConnectionオブジェクトの構成を表します。 |
9 | RTCPeerConnection.getLocalStreams() ローカルMediaStream接続の配列を返します。 |
10 | RTCPeerConnection.getRemoteStreams() リモートMediaStream接続の配列を返します。 |
11 | RTCPeerConnection.getStreamById() 指定されたIDでローカルまたはリモートのMediaStreamを返します。 |
12 | RTCPeerConnection.addStream() ビデオまたはオーディオのローカルソースとしてMediaStreamを追加します。 |
13 | RTCPeerConnection.removeStream() ビデオまたはオーディオのローカルソースとしてMediaStreamを削除します。 |
14 | RTCPeerConnection.close() 接続を閉じます。 |
15 | RTCPeerConnection.createDataChannel() 新しいRTCDataChannelを作成します。 |
16 | RTCPeerConnection.createDTMFSender() 特定のMediaStreamTrackに関連付けられた新しいRTCDTMFSenderを作成します。接続を介してDTMF(デュアルトーン多重周波数)電話信号を送信できます。 |
17 | RTCPeerConnection.getStats() 接続に関する統計を含む新しいRTCStatsReportを作成します。 |
18 | RTCPeerConnection.setIdentityProvider() IdPを設定します。名前、通信に使用されるプロトコル、およびオプションのユーザー名の3つのパラメーターを取ります。 |
19 | RTCPeerConnection.getIdentityAssertion() IDアサーションを収集します。アプリケーションでこのメソッドを処理することは期待されていません。したがって、必要性を予測するためにのみ明示的に呼び出すことができます。 |
接続の確立
それでは、サンプルアプリケーションを作成しましょう。まず、「シグナリングサーバー」チュートリアルで作成したシグナリングサーバーを「ノードサーバー」経由で実行します。
ページには2つのテキスト入力があります。1つはログイン用で、もう1つは接続するユーザー名用です。index.htmlファイルを作成し、次のコードを追加します-
<html lang = "en">
<head>
<meta charset = "utf-8" />
</head>
<body>
<div>
<input type = "text" id = "loginInput" />
<button id = "loginBtn">Login</button>
</div>
<div>
<input type = "text" id = "otherUsernameInput" />
<button id = "connectToOtherUsernameBtn">Establish connection</button>
</div>
<script src = "client2.js"></script>
</body>
</html>
ログイン用のテキスト入力、ログインボタン、他のピアユーザー名用のテキスト入力、および彼に接続するボタンが追加されたことがわかります。次に、client.jsファイルを作成し、次のコードを追加します-
var connection = new WebSocket('ws://localhost:9090');
var name = "";
var loginInput = document.querySelector('#loginInput');
var loginBtn = document.querySelector('#loginBtn');
var otherUsernameInput = document.querySelector('#otherUsernameInput');
var connectToOtherUsernameBtn = document.querySelector('#connectToOtherUsernameBtn');
var connectedUser, myConnection;
//when a user clicks the login button
loginBtn.addEventListener("click", function(event){
name = loginInput.value;
if(name.length > 0){
send({
type: "login",
name: name
});
}
});
//handle messages from the server
connection.onmessage = function (message) {
console.log("Got message", message.data);
var data = JSON.parse(message.data);
switch(data.type) {
case "login":
onLogin(data.success);
break;
case "offer":
onOffer(data.offer, data.name);
break;
case "answer":
onAnswer(data.answer);
break;
case "candidate":
onCandidate(data.candidate);
break;
default:
break;
}
};
//when a user logs in
function onLogin(success) {
if (success === false) {
alert("oops...try a different username");
} else {
//creating our RTCPeerConnection object
var configuration = {
"iceServers": [{ "url": "stun:stun.1.google.com:19302" }]
};
myConnection = new webkitRTCPeerConnection(configuration);
console.log("RTCPeerConnection object was created");
console.log(myConnection);
//setup ice handling
//when the browser finds an ice candidate we send it to another peer
myConnection.onicecandidate = function (event) {
if (event.candidate) {
send({
type: "candidate",
candidate: event.candidate
});
}
};
}
};
connection.onopen = function () {
console.log("Connected");
};
connection.onerror = function (err) {
console.log("Got error", err);
};
// Alias for sending messages in JSON format
function send(message) {
if (connectedUser) {
message.name = connectedUser;
}
connection.send(JSON.stringify(message));
};
シグナリングサーバーへのソケット接続を確立していることがわかります。ユーザーがログインボタンをクリックすると、アプリケーションはユーザー名をサーバーに送信します。ログインが成功すると、アプリケーションはRTCPeerConnectionオブジェクトを作成し、見つかったすべてのicecandidateを他のピアに送信するonicecandidateハンドラーをセットアップします。次に、ページを開いてログインしてみます。次のコンソール出力が表示されます-
次のステップは、他のピアへのオファーを作成することです。次のコードをclient.jsファイルに追加します-
//setup a peer connection with another user
connectToOtherUsernameBtn.addEventListener("click", function () {
var otherUsername = otherUsernameInput.value;
connectedUser = otherUsername;
if (otherUsername.length > 0) {
//make an offer
myConnection.createOffer(function (offer) {
console.log();
send({
type: "offer",
offer: offer
});
myConnection.setLocalDescription(offer);
}, function (error) {
alert("An error has occurred.");
});
}
});
//when somebody wants to call us
function onOffer(offer, name) {
connectedUser = name;
myConnection.setRemoteDescription(new RTCSessionDescription(offer));
myConnection.createAnswer(function (answer) {
myConnection.setLocalDescription(answer);
send({
type: "answer",
answer: answer
});
}, function (error) {
alert("oops...error");
});
}
//when another user answers to our offer
function onAnswer(answer) {
myConnection.setRemoteDescription(new RTCSessionDescription(answer));
}
//when we got ice candidate from another user
function onCandidate(candidate) {
myConnection.addIceCandidate(new RTCIceCandidate(candidate));
}
ユーザーが「接続の確立」ボタンをクリックすると、アプリケーションが他のピアにSDPオファーを提供することがわかります。また、設定onAnswerとonCandidateハンドラを。ページをリロードし、2つのタブで開き、2人のユーザーでログインして、それらの間の接続を確立してみます。次のコンソール出力が表示されます-
これで、ピアツーピア接続が確立されました。次のチュートリアルでは、ビデオとオーディオのストリーム、およびテキストチャットのサポートを追加します。